🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

@stll/folio-agents

Package Overview
Dependencies
Maintainers
1
Versions
15
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@stll/folio-agents - npm Package Compare versions

Comparing version
0.7.0
to
0.8.0
+50
-5
dist/execute.js
import { explainTextTooLong, parseAddCommentInput, parseSuggestChangesInput } from "./parse.js";
import { FOLIO_AGENT_TOOL_NAMES } from "./types.js";
import { FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, createFolioAITextRangeHandle, getFolioDocumentOutline, readFolioDocumentSection } from "@stll/folio-core/server";
import { FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, createFolioAITextRangeHandle, getFolioDocumentOutline, hashFolioAIBlockText, normalizeFolioAIBlockText, readFolioDocumentSection } from "@stll/folio-core/server";
//#region src/execute.ts

@@ -16,2 +16,11 @@ const isPlainObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);

const VALID_TOOL_NAMES = Object.values(FOLIO_AGENT_TOOL_NAMES);
/**
* The same normalized-text hash the core snapshot/apply machinery uses for
* `precondition.blockTextHash` (see `hashFolioAIBlockText` /
* `normalizeFolioAIBlockText`). Computed straight from a block's `text`
* rather than looked up from `snapshot.anchors` so every read path (main
* document, a section, a find_text match) can attach it without threading
* the anchors map around — it is defined to produce the exact same value.
*/
const blockTextHashOf = (text) => hashFolioAIBlockText(normalizeFolioAIBlockText(text));
/** `find_text` requires a short `query` and caps how much of a large match set it returns in one call. */

@@ -64,3 +73,4 @@ const MAX_QUERY_LENGTH = 1e3;

kind: block.kind,
text: block.text
text: block.text,
blockTextHash: blockTextHashOf(block.text)
})));

@@ -127,3 +137,4 @@ };

kind,
text
text,
blockTextHash: blockTextHashOf(text)
})),

@@ -168,2 +179,12 @@ totalBlocks: resolved.section.blocks.length,

const WORD_CHARACTER_AT_START = /^[\p{L}\p{M}\p{N}_]/u;
/**
* Window (UTF-16 code units) sliced on each side of a match for the
* whole-word boundary check. The regexes above only ever test the single
* grapheme adjacent to the match, but a surrogate pair or a base character
* with stacked combining marks can span a few code units — this window is
* generous enough to cover that while staying a constant, not
* `block.text.length`. Without a bound, `.slice(0, at)` / `.slice(at + len)`
* on every match makes a whole-word search O(n^2) in the block's length.
*/
const WORD_BOUNDARY_WINDOW = 8;
const findTextMatches = (blocks, query, matchCase, wholeWord, getTargetPage, pageFilter) => {

@@ -176,6 +197,7 @@ const matches = [];

let occurrence = 0;
let blockTextHash;
for (const match of block.text.matchAll(expression)) {
const at = match.index;
const matchedText = match[0];
if (wholeWord && (WORD_CHARACTER_AT_END.test(block.text.slice(0, at)) || WORD_CHARACTER_AT_START.test(block.text.slice(at + matchedText.length)))) continue;
if (wholeWord && (WORD_CHARACTER_AT_END.test(block.text.slice(Math.max(0, at - WORD_BOUNDARY_WINDOW), at)) || WORD_CHARACTER_AT_START.test(block.text.slice(at + matchedText.length, at + matchedText.length + WORD_BOUNDARY_WINDOW)))) continue;
const range = createFolioAITextRangeHandle({

@@ -194,2 +216,3 @@ blockId: block.id,

const contextEnd = Math.min(block.text.length, at + matchedText.length + CONTEXT_RADIUS);
blockTextHash ??= blockTextHashOf(block.text);
matches.push({

@@ -199,2 +222,3 @@ type: "main",

blockId: block.id,
blockTextHash,
range,

@@ -222,3 +246,3 @@ occurrenceInBlock: occurrence,

const matchedText = match[0];
if (wholeWord && (WORD_CHARACTER_AT_END.test(text.slice(0, at)) || WORD_CHARACTER_AT_START.test(text.slice(at + matchedText.length)))) continue;
if (wholeWord && (WORD_CHARACTER_AT_END.test(text.slice(Math.max(0, at - WORD_BOUNDARY_WINDOW), at)) || WORD_CHARACTER_AT_START.test(text.slice(at + matchedText.length, at + matchedText.length + WORD_BOUNDARY_WINDOW)))) continue;
if (matches.length < MAX_FIND_MATCHES) matches.push({

@@ -329,2 +353,19 @@ type: "story",

});
/**
* Attach a `precondition.blockTextHash` guard to every operation before
* handing the batch to the bridge.
*
* When the caller (the model) already echoed a `precondition` on the
* operation — sourced from a `blockTextHash` returned by an earlier
* `read_document` / `read_section` / `find_text` call — that is honored
* as-is: it is the only signal that can catch a document edit made
* BETWEEN that read and this apply call.
*
* When no precondition was supplied, fall back to stamping one from this
* call's own fresh `bridge.snapshot()`, matching the previous behavior.
* This fallback cannot detect cross-call staleness — the snapshot it reads
* from is taken right before applying, so it always matches the current
* live document — but it still guards a later operation in the SAME batch
* against an earlier operation in that batch touching the same block.
*/
const applyOperations = (bridge, operations) => {

@@ -334,2 +375,6 @@ const snapshot = bridge.snapshot();

for (const operation of operations) {
if (operation.precondition !== void 0) {
guardedOperations.push(operation);
continue;
}
const blockId = operation.type === "replaceRange" || operation.type === "commentOnRange" || operation.type === "formatRange" ? operation.range.blockId : operation.blockId;

@@ -336,0 +381,0 @@ const blockTextHash = snapshot.anchors[blockId]?.textHash;

+12
-5

@@ -72,9 +72,16 @@ import { FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, FOLIO_DOCUMENT_OPERATION_MODES, InvalidFolioDocumentOperationBatchError, UnsupportedFolioDocumentOperationVersionError, parseFolioDocumentOperationBatch } from "@stll/folio-core/server";

};
const preconditionJsonSchema = {
/**
* JSON Schema for the contract's optional `precondition` guard: `{
* blockTextHash }`, echoed from a `blockTextHash` returned by a document
* read (`read_document`, `read_section`, `find_text`). Exported so
* `tools.ts` can attach the same shape to `suggest_changes` and
* `add_comment` without redeclaring it.
*/
const FOLIO_PRECONDITION_JSON_SCHEMA = {
type: "object",
description: "Optional guard: the operation is skipped (reason `preconditionFailed`) unless the target block's normalized text hash still matches.",
description: "Optional guard against editing a block that changed since you read it: echo the `blockTextHash` returned by read_document / read_section / find_text for this block. The operation is skipped (reason `preconditionFailed`) unless the target block's current normalized text hash still matches.",
properties: { blockTextHash: {
type: "string",
pattern: NORMALIZED_TEXT_HASH_PATTERN,
description: "Normalized hash of the target block's text."
description: "Normalized hash of the target block's text, from a prior document read."
} },

@@ -116,3 +123,3 @@ required: ["blockTextHash"],

},
precondition: preconditionJsonSchema
precondition: FOLIO_PRECONDITION_JSON_SCHEMA
};

@@ -666,2 +673,2 @@ const blockIdProperty = {

//#endregion
export { FOLIO_DOCUMENT_OPERATION_BATCH_JSON_SCHEMA, FOLIO_DOCUMENT_OPERATION_JSON_SCHEMA, FOLIO_TEXT_RANGE_JSON_SCHEMA, folioDocumentOperationBatchSchema };
export { FOLIO_DOCUMENT_OPERATION_BATCH_JSON_SCHEMA, FOLIO_DOCUMENT_OPERATION_JSON_SCHEMA, FOLIO_PRECONDITION_JSON_SCHEMA, FOLIO_TEXT_RANGE_JSON_SCHEMA, folioDocumentOperationBatchSchema };

@@ -14,2 +14,15 @@ import { FolioAIEditOperation } from "@stll/folio-core/server";

declare const MAX_OPERATION_TEXT_LENGTH = 100000;
/**
* Aggregate cap on the SUM of every text-bearing field's length across one
* `suggest_changes` call. Each field alone is bounded by
* {@link MAX_OPERATION_TEXT_LENGTH} and each call by
* {@link MAX_OPERATIONS_PER_CALL} operations, but an operation can carry
* several capped fields (e.g. `comment` plus `text`), and a table-insertion
* operation can carry up to {@link MAX_TABLE_INSERTION_CELL_TEXTS} capped
* cell texts — so a maximally-shaped batch could still push roughly
* 50 * 256 * 100,000 ~= 1.28B characters into the tracked-changes engine in
* one call even though every per-field cap was respected. This budget bounds
* the running total instead.
*/
declare const MAX_TOTAL_OPERATION_TEXT_LENGTH = 2000000;
/** Plain-language error for a string argument over {@link MAX_OPERATION_TEXT_LENGTH}. */

@@ -46,2 +59,2 @@ declare const explainTextTooLong: (label: string, length: number) => string;

//#endregion
export { MAX_OPERATIONS_PER_CALL, MAX_OPERATION_TEXT_LENGTH, ParseAddCommentResult, ParseSuggestChangesResult, explainTextTooLong, parseAddCommentInput, parseSuggestChangesInput };
export { MAX_OPERATIONS_PER_CALL, MAX_OPERATION_TEXT_LENGTH, MAX_TOTAL_OPERATION_TEXT_LENGTH, ParseAddCommentResult, ParseSuggestChangesResult, explainTextTooLong, parseAddCommentInput, parseSuggestChangesInput };

@@ -15,5 +15,46 @@ //#region src/parse.ts

const MAX_TABLE_INSERTION_CELL_TEXTS = 256;
/**
* Aggregate cap on the SUM of every text-bearing field's length across one
* `suggest_changes` call. Each field alone is bounded by
* {@link MAX_OPERATION_TEXT_LENGTH} and each call by
* {@link MAX_OPERATIONS_PER_CALL} operations, but an operation can carry
* several capped fields (e.g. `comment` plus `text`), and a table-insertion
* operation can carry up to {@link MAX_TABLE_INSERTION_CELL_TEXTS} capped
* cell texts — so a maximally-shaped batch could still push roughly
* 50 * 256 * 100,000 ~= 1.28B characters into the tracked-changes engine in
* one call even though every per-field cap was respected. This budget bounds
* the running total instead.
*/
const MAX_TOTAL_OPERATION_TEXT_LENGTH = 2e6;
/** Plain-language error for a string argument over {@link MAX_OPERATION_TEXT_LENGTH}. */
const explainTextTooLong = (label, length) => `${label} is ${length.toLocaleString()} characters, over the ${MAX_OPERATION_TEXT_LENGTH.toLocaleString()}-character limit; shorten it or split it into multiple operations.`;
/** Plain-language error when the running total across all operations exceeds {@link MAX_TOTAL_OPERATION_TEXT_LENGTH}. */
const explainAggregateTextTooLong = (index) => `operations[${index}] pushes suggest_changes' combined text over the ${MAX_TOTAL_OPERATION_TEXT_LENGTH.toLocaleString()}-character aggregate limit across all operations; split the edit across multiple suggest_changes calls.`;
/** Normalized text hashes (`hashFolioAIBlockText`) look like `h` followed by base-36 digits. */
const NORMALIZED_TEXT_HASH_PATTERN = /^h[0-9a-z]+$/;
/**
* Parse an optional `precondition: { blockTextHash }` field, present on
* `add_comment` / `suggest_changes` operation arguments when the caller
* echoes a `blockTextHash` returned by an earlier `read_document` /
* `read_section` / `find_text` call. Guards the eventual apply against a
* document edit made between that read and this call — `execute.ts`
* otherwise has no way to distinguish "the model never read this block" from
* "the model read it and it has since changed".
*
* Returns `undefined` when omitted, the parsed precondition when valid, or a
* plain-language error string otherwise.
*/
const readOperationPrecondition = (value) => {
if (value === void 0) return;
if (!isPlainObject(value)) return "`precondition` must be an object when provided.";
const blockTextHash = value["blockTextHash"];
if (!isNonEmptyString(blockTextHash) || !NORMALIZED_TEXT_HASH_PATTERN.test(blockTextHash)) return "`precondition.blockTextHash` must be a normalized block text hash, echoed from read_document / read_section / find_text.";
return { blockTextHash };
};
/** Decrement the shared budget by `length`; returns true once the aggregate cap is exceeded. */
const consumeTextBudget = (budget, length) => {
budget.remaining -= length;
return budget.remaining < 0;
};
/**
* Validate `add_comment`'s raw tool-call arguments and build the

@@ -51,2 +92,7 @@ * `commentOnBlock` {@link FolioAIEditOperation} it applies. Pure: does not

};
const precondition = readOperationPrecondition(args["precondition"]);
if (typeof precondition === "string") return {
ok: false,
error: `add_comment's ${precondition}`
};
return {

@@ -59,3 +105,4 @@ ok: true,

comment: { text },
...quote !== void 0 ? { quote } : {}
...quote !== void 0 ? { quote } : {},
...precondition !== void 0 ? { precondition } : {}
}

@@ -79,3 +126,3 @@ };

if (typeof endOffset !== "number" || !Number.isInteger(endOffset) || endOffset <= startOffset) return `${path}.endOffset must be an integer greater than startOffset.`;
if (!isNonEmptyString(selectedTextHash) || !/^h[0-9a-z]+$/.test(selectedTextHash)) return `${path}.selectedTextHash must be a normalized text hash.`;
if (!isNonEmptyString(selectedTextHash) || !NORMALIZED_TEXT_HASH_PATTERN.test(selectedTextHash)) return `${path}.selectedTextHash must be a normalized text hash.`;
return {

@@ -90,5 +137,22 @@ type,

};
/** Validate + map one `suggest_changes` operation, or return a plain-language error string. */
const buildSuggestedOperation = (raw, index) => {
/**
* Validate + map one `suggest_changes` operation, or return a plain-language
* error string. Parses the shared `precondition` field itself (every
* operation variant accepts it, so it does not belong to any one type's
* branch below) and merges it onto whatever {@link buildSuggestedOperationCore}
* builds.
*/
const buildSuggestedOperation = (raw, index, budget) => {
if (!isPlainObject(raw)) return `operations[${index}] must be an object.`;
const precondition = readOperationPrecondition(raw["precondition"]);
if (typeof precondition === "string") return `operations[${index}] ${precondition}`;
const built = buildSuggestedOperationCore(raw, index, budget);
if (typeof built === "string") return built;
return precondition === void 0 ? built : {
...built,
precondition
};
};
/** Type-and-shape-specific half of {@link buildSuggestedOperation}. */
const buildSuggestedOperationCore = (raw, index, budget) => {
const type = raw["type"];

@@ -101,3 +165,6 @@ const blockId = raw["blockId"];

if (comment !== void 0 && typeof comment !== "string") return `operations[${index}].comment must be a string when provided.`;
if (typeof comment === "string" && comment.length > 1e5) return explainTextTooLong(`operations[${index}].comment`, comment.length);
if (typeof comment === "string") {
if (comment.length > 1e5) return explainTextTooLong(`operations[${index}].comment`, comment.length);
if (consumeTextBudget(budget, comment.length)) return explainAggregateTextTooLong(index);
}
const opId = isNonEmptyString(id) ? id : `op-${index + 1}`;

@@ -142,2 +209,3 @@ const commentField = typeof comment === "string" ? { comment: { text: comment } } : {};

if (replace.length > 1e5) return explainTextTooLong(`operations[${index}] (replaceRange) \`replace\``, replace.length);
if (consumeTextBudget(budget, replace.length)) return explainAggregateTextTooLong(index);
return {

@@ -162,2 +230,3 @@ id: opId,

if (cellText.length > 1e5) return explainTextTooLong(`operations[${index}] (${type}) \`cellTexts[${cellIndex}]\``, cellText.length);
if (consumeTextBudget(budget, cellText.length)) return explainAggregateTextTooLong(index);
cellTexts.push(cellText);

@@ -200,4 +269,6 @@ }

if (find.length > 1e5) return explainTextTooLong(`operations[${index}] (replaceInBlock) \`find\``, find.length);
if (consumeTextBudget(budget, find.length)) return explainAggregateTextTooLong(index);
if (typeof replace !== "string") return `operations[${index}] (replaceInBlock) requires a string \`replace\`.`;
if (replace.length > 1e5) return explainTextTooLong(`operations[${index}] (replaceInBlock) \`replace\``, replace.length);
if (consumeTextBudget(budget, replace.length)) return explainAggregateTextTooLong(index);
return {

@@ -216,2 +287,3 @@ id: opId,

if (text.length > 1e5) return explainTextTooLong(`operations[${index}] (${type}) \`text\``, text.length);
if (consumeTextBudget(budget, text.length)) return explainAggregateTextTooLong(index);
return {

@@ -229,2 +301,3 @@ id: opId,

if (text.length > 1e5) return explainTextTooLong(`operations[${index}] (replaceBlock) \`text\``, text.length);
if (consumeTextBudget(budget, text.length)) return explainAggregateTextTooLong(index);
return {

@@ -265,4 +338,5 @@ id: opId,

const operations = [];
const budget = { remaining: MAX_TOTAL_OPERATION_TEXT_LENGTH };
for (const [index, raw] of rawOperations.entries()) {
const built = buildSuggestedOperation(raw, index);
const built = buildSuggestedOperation(raw, index, budget);
if (typeof built === "string") return {

@@ -280,2 +354,2 @@ ok: false,

//#endregion
export { MAX_OPERATIONS_PER_CALL, MAX_OPERATION_TEXT_LENGTH, explainTextTooLong, parseAddCommentInput, parseSuggestChangesInput };
export { MAX_OPERATIONS_PER_CALL, MAX_OPERATION_TEXT_LENGTH, MAX_TOTAL_OPERATION_TEXT_LENGTH, explainTextTooLong, parseAddCommentInput, parseSuggestChangesInput };
import { FOLIO_AGENT_TOOL_NAMES } from "./types.js";
import { FOLIO_TEXT_RANGE_JSON_SCHEMA } from "./operation-schema.js";
import { FOLIO_PRECONDITION_JSON_SCHEMA, FOLIO_TEXT_RANGE_JSON_SCHEMA } from "./operation-schema.js";
import { FOLIO_DOCUMENT_OPERATION_TYPES } from "@stll/folio-core/server";

@@ -92,6 +92,8 @@ //#region src/tools.ts

* `{ text }` object;
* - the review metadata (`severity`, `area`), `precondition` guard, and the
* insert/replace formatting knobs (`inheritFormatting`, `pageBreakBefore`,
* `preserveFormatting`, `styleId`, `parties`, `quote`,
* except `formatting`) are not exposed to the model.
* - the review metadata (`severity`, `area`) and the insert/replace
* formatting knobs (`inheritFormatting`, `pageBreakBefore`,
* `preserveFormatting`, `styleId`, `parties`, `quote`, except `formatting`)
* are not exposed to the model. `precondition` IS exposed (see
* `FOLIO_PRECONDITION_JSON_SCHEMA`) so the model can guard an edit against
* staleness introduced between an earlier read and this call.
*/

@@ -174,3 +176,4 @@ const SUGGEST_CHANGES_EXCLUDED_OPERATION_TYPES = /* @__PURE__ */ new Set(["commentOnBlock", "insertSignatureTable"]);

description: "Optional comment explaining this edit, attached to the affected text, up to 100,000 characters."
}
},
precondition: FOLIO_PRECONDITION_JSON_SCHEMA
},

@@ -191,3 +194,3 @@ required: ["type"],

name: FOLIO_AGENT_TOOL_NAMES.readDocument,
description: "Read the full document body as a list of blocks (paragraphs, headings, list items). Call this first, or whenever you need fresh block ids after a mutation — block ids from a stale read may no longer resolve.",
description: "Read the full document body as a list of blocks (paragraphs, headings, list items). Call this first, or whenever you need fresh block ids after a mutation — block ids from a stale read may no longer resolve. Each block includes a `blockTextHash`; echo it as `precondition.blockTextHash` on a suggest_changes / add_comment operation to guard against the block changing before that call runs.",
inputSchema: {

@@ -217,3 +220,3 @@ type: "object",

name: FOLIO_AGENT_TOOL_NAMES.readSection,
description: "Read one logical heading section using a handle from get_document_outline. Content is block-bounded and paginated with an afterBlockId cursor, avoiding a full-document read.",
description: "Read one logical heading section using a handle from get_document_outline. Content is block-bounded and paginated with an afterBlockId cursor, avoiding a full-document read. Each block includes a `blockTextHash`; echo it as `precondition.blockTextHash` on a suggest_changes / add_comment operation.",
inputSchema: {

@@ -260,3 +263,3 @@ type: "object",

name: FOLIO_AGENT_TOOL_NAMES.findText,
description: "Search a document, section, rendered page, or story and return `{ matches, truncated, totalMatches }`. Main-story matches include a stable block and exact range; other stories return story-relative offsets. Every match includes surrounding context. `matches` is capped at 200 entries; `truncated` is true and `totalMatches` reports the real count when there were more — narrow the query or scope instead of assuming you saw every hit.",
description: "Search a document, section, rendered page, or story and return `{ matches, truncated, totalMatches }`. Main-story matches include a stable block, exact range, and `blockTextHash` (echo it as `precondition.blockTextHash` on a later suggest_changes / add_comment operation); other stories return story-relative offsets. Every match includes surrounding context. `matches` is capped at 200 entries; `truncated` is true and `totalMatches` reports the real count when there were more — narrow the query or scope instead of assuming you saw every hit.",
inputSchema: {

@@ -349,3 +352,4 @@ type: "object",

description: "The comment body, up to 100,000 characters."
}
},
precondition: FOLIO_PRECONDITION_JSON_SCHEMA
},

@@ -358,3 +362,3 @@ required: ["blockId", "text"],

name: FOLIO_AGENT_TOOL_NAMES.suggestChanges,
description: "Propose one or more edits as tracked changes for a human to accept or reject — nothing is applied directly to the visible text. Each operation needs a blockId from `read_document` or `find_text`; if the document changed since that read, re-read it and retry with fresh ids (a skip reason will say so). At most 50 operations per call — batch larger edits across multiple calls. Each `find` / `replace` / `text` / `comment` string is capped at 100,000 characters.",
description: "Propose one or more edits as tracked changes for a human to accept or reject — nothing is applied directly to the visible text. Each operation needs a blockId from `read_document` or `find_text`; if the document changed since that read, re-read it and retry with fresh ids (a skip reason will say so). Pass the `blockTextHash` from that read as `precondition.blockTextHash` to guard against the document changing between the read and this call. At most 50 operations per call — batch larger edits across multiple calls. Each `find` / `replace` / `text` / `comment` string is capped at 100,000 characters.",
inputSchema: {

@@ -361,0 +365,0 @@ type: "object",

@@ -61,2 +61,11 @@ import { FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, FolioAITextRangeHandle, FolioDocumentOperationIssue, FolioDocumentOperationReceipt, FolioDocumentOutlineEntry, FolioDocumentSectionHandle, FolioDocumentStoryHandle, FolioReviewChange } from "@stll/folio-core/server";

text: string;
/**
* Normalized-text hash of this block at read time. Echo it back as
* `precondition.blockTextHash` on a `suggest_changes` / `add_comment`
* operation targeting this block so the apply call is guarded against
* edits made to the document between this read and that apply — without
* it, only same-call staleness within one `suggest_changes` batch is
* caught.
*/
blockTextHash: string;
};

@@ -69,3 +78,4 @@ /** One main-story `find_text` match. Existing consumers can keep using its block and range directly. */

};
blockId: string; /** Stable handle that can be passed directly to `show_in_document` or a range operation. */
blockId: string; /** Normalized-text hash of the whole containing block; see {@link FolioAgentBlock.blockTextHash}. */
blockTextHash: string; /** Stable handle that can be passed directly to `show_in_document` or a range operation. */
range: FolioAITextRangeHandle; /** 0-based index of this occurrence within its block. */

@@ -72,0 +82,0 @@ occurrenceInBlock: number; /** Real rendered page when a live paginated surface supplies it. */

{
"name": "@stll/folio-agents",
"version": "0.7.0",
"version": "0.8.0",
"description": "Framework-neutral LLM tool layer over folio's ai-edits engine: function-calling tools so an agent can read and mutate .docx documents through @stll/folio-core.",

@@ -57,3 +57,3 @@ "keywords": [

"dependencies": {
"@stll/folio-core": "^0.6.0"
"@stll/folio-core": "^0.12.0"
},

@@ -60,0 +60,0 @@ "main": "./dist/index.js",

Sorry, the diff of this file is too big to display