🎩 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
13
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.6.1
to
0.7.0
+142
-3
dist/operation-schema.js

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

* JSON Schema (draft-07 compatible) for ONE document operation: the full
* ten-variant union accepted by `parseFolioDocumentOperationBatch` in
* thirteen-variant union accepted by `parseFolioDocumentOperationBatch` in
* `@stll/folio-core`, one `oneOf` variant per entry in

@@ -209,3 +209,3 @@ * `FOLIO_DOCUMENT_OPERATION_TYPES`. Intended for LLM tool definitions and

type: "object",
description: "Apply inline formatting to the text covered by a range handle. Direct mode only (formatting is not representable as a tracked change).",
description: "Apply inline formatting to the text covered by a range handle in direct or tracked mode.",
properties: {

@@ -432,2 +432,141 @@ ...operationMetaProperties,

additionalProperties: false
},
{
type: "object",
description: "Insert a row next to the row containing the anchor block.",
properties: {
...operationMetaProperties,
type: {
type: "string",
enum: ["insertTableRow"]
},
blockId: blockIdProperty,
position: {
type: "string",
enum: ["after", "before"],
description: "Insert after the anchor row (default) or before it. Defaults to \"after\"."
},
cellTexts: {
type: "array",
description: "Initial text for physical cells in source order; omitted cells stay empty.",
items: { type: "string" }
}
},
required: [
"id",
"type",
"blockId"
],
additionalProperties: false
},
{
type: "object",
description: "Delete the row containing the anchor block.",
properties: {
...operationMetaProperties,
type: {
type: "string",
enum: ["deleteTableRow"]
},
blockId: blockIdProperty
},
required: [
"id",
"type",
"blockId"
],
additionalProperties: false
},
{
type: "object",
description: "Insert a column next to the column containing the anchor block.",
properties: {
...operationMetaProperties,
type: {
type: "string",
enum: ["insertTableColumn"]
},
blockId: blockIdProperty,
position: {
type: "string",
enum: ["after", "before"],
description: "Insert after the anchor column (default) or before it. Defaults to \"after\"."
},
cellTexts: {
type: "array",
description: "Initial text for newly created physical cells in row order.",
items: { type: "string" }
}
},
required: [
"id",
"type",
"blockId"
],
additionalProperties: false
},
{
type: "object",
description: "Delete the column containing the anchor block.",
properties: {
...operationMetaProperties,
type: {
type: "string",
enum: ["deleteTableColumn"]
},
blockId: blockIdProperty
},
required: [
"id",
"type",
"blockId"
],
additionalProperties: false
},
{
type: "object",
description: "Merge a region targeted by an opposite-cell anchor or a downward row count. Tracked mode supports vertical-only regions with empty continuation cells.",
properties: {
...operationMetaProperties,
type: {
type: "string",
enum: ["mergeTableCells"]
},
blockId: blockIdProperty,
endBlockId: {
type: "string",
minLength: 1,
description: "Stable paragraph anchor inside the opposite corner cell."
},
rowCount: {
type: "integer",
minimum: 2,
description: "Number of grid rows to merge downward from the anchored cell."
}
},
required: [
"id",
"type",
"blockId"
],
oneOf: [{ required: ["endBlockId"] }, { required: ["rowCount"] }],
additionalProperties: false
},
{
type: "object",
description: "Split one spanned table cell into individual cells. Tracked mode supports vertical-only spans.",
properties: {
...operationMetaProperties,
type: {
type: "string",
enum: ["splitTableCell"]
},
blockId: blockIdProperty
},
required: [
"id",
"type",
"blockId"
],
additionalProperties: false
}

@@ -461,3 +600,3 @@ ]

enum: FOLIO_DOCUMENT_OPERATION_MODES,
description: "How edits land: \"tracked-changes\" (default) proposes revisions for human review, \"direct\" applies immediately. `formatRange` and `insertSignatureTable` support \"direct\" only."
description: "How edits land: \"tracked-changes\" (default) proposes revisions for human review, \"direct\" applies immediately. `insertSignatureTable` supports \"direct\" only. Tracked cell merge and split operations support unambiguous vertical-only topology."
},

@@ -464,0 +603,0 @@ atomic: {

@@ -14,2 +14,3 @@ //#region src/parse.ts

const MAX_OPERATION_TEXT_LENGTH = 1e5;
const MAX_TABLE_INSERTION_CELL_TEXTS = 256;
/** Plain-language error for a string argument over {@link MAX_OPERATION_TEXT_LENGTH}. */

@@ -61,4 +62,4 @@ 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.`;

};
const OPERATION_TYPES = "replaceInBlock, replaceRange, commentOnRange, insertAfterBlock, insertBeforeBlock, replaceBlock, deleteBlock";
const isOperationType = (value) => value === "replaceInBlock" || value === "replaceRange" || value === "commentOnRange" || value === "insertAfterBlock" || value === "insertBeforeBlock" || value === "replaceBlock" || value === "deleteBlock";
const OPERATION_TYPES = "replaceInBlock, replaceRange, commentOnRange, formatRange, insertAfterBlock, insertBeforeBlock, replaceBlock, deleteBlock, insertTableRow, deleteTableRow, insertTableColumn, deleteTableColumn, mergeTableCells, splitTableCell";
const isOperationType = (value) => value === "replaceInBlock" || value === "replaceRange" || value === "commentOnRange" || value === "formatRange" || value === "insertAfterBlock" || value === "insertBeforeBlock" || value === "replaceBlock" || value === "deleteBlock" || value === "insertTableRow" || value === "deleteTableRow" || value === "insertTableColumn" || value === "deleteTableColumn" || value === "mergeTableCells" || value === "splitTableCell";
const readTextRange = (value, index) => {

@@ -100,3 +101,3 @@ const path = `operations[${index}].range`;

const commentField = typeof comment === "string" ? { comment: { text: comment } } : {};
if (type === "replaceRange" || type === "commentOnRange") {
if (type === "replaceRange" || type === "commentOnRange" || type === "formatRange") {
const range = readTextRange(raw["range"], index);

@@ -113,2 +114,24 @@ if (typeof range === "string") return range;

}
if (type === "formatRange") {
const rawFormatting = raw["formatting"];
if (!isPlainObject(rawFormatting)) return `operations[${index}] (formatRange) requires a \`formatting\` object.`;
const formatting = {};
for (const key of [
"bold",
"italic",
"underline"
]) {
const value = rawFormatting[key];
if (value === void 0) continue;
if (typeof value !== "boolean") return `operations[${index}].formatting.${key} must be a boolean when provided.`;
formatting[key] = value;
}
if (Object.keys(formatting).length === 0) return `operations[${index}] (formatRange) requires at least one formatting property.`;
return {
id: opId,
type,
range,
formatting
};
}
const replace = raw["replace"];

@@ -126,2 +149,44 @@ if (typeof replace !== "string") return `operations[${index}] (replaceRange) requires a string \`replace\`.`;

if (!isNonEmptyString(blockId)) return `operations[${index}].blockId must be a non-empty string.`;
if (type === "insertTableRow" || type === "insertTableColumn") {
const position = raw["position"];
if (position !== void 0 && position !== "after" && position !== "before") return `operations[${index}] (${type}) \`position\` must be "after" or "before" when provided.`;
const rawCellTexts = raw["cellTexts"];
if (rawCellTexts !== void 0 && !Array.isArray(rawCellTexts)) return `operations[${index}] (${type}) \`cellTexts\` must be an array of strings when provided.`;
if (rawCellTexts !== void 0 && rawCellTexts.length > MAX_TABLE_INSERTION_CELL_TEXTS) return `operations[${index}] (${type}) \`cellTexts\` has ${rawCellTexts.length.toLocaleString()} entries, over the ${MAX_TABLE_INSERTION_CELL_TEXTS.toLocaleString()}-cell limit.`;
const cellTexts = [];
for (const [cellIndex, cellText] of (rawCellTexts ?? []).entries()) {
if (typeof cellText !== "string") return `operations[${index}] (${type}) \`cellTexts[${cellIndex}]\` must be a string.`;
if (cellText.length > 1e5) return explainTextTooLong(`operations[${index}] (${type}) \`cellTexts[${cellIndex}]\``, cellText.length);
cellTexts.push(cellText);
}
return {
id: opId,
type,
blockId,
...position !== void 0 && { position },
...rawCellTexts !== void 0 && { cellTexts }
};
}
if (type === "deleteTableRow" || type === "deleteTableColumn" || type === "splitTableCell") return {
id: opId,
type,
blockId
};
if (type === "mergeTableCells") {
const endBlockId = raw["endBlockId"];
const rowCount = raw["rowCount"];
if (isNonEmptyString(endBlockId) && rowCount === void 0) return {
id: opId,
type,
blockId,
endBlockId
};
if (endBlockId === void 0 && typeof rowCount === "number" && Number.isInteger(rowCount) && rowCount >= 2) return {
id: opId,
type,
blockId,
rowCount
};
return `operations[${index}] (mergeTableCells) requires exactly one non-empty \`endBlockId\` or integer \`rowCount\` of at least 2.`;
}
if (type === "replaceInBlock") {

@@ -128,0 +193,0 @@ const find = raw["find"];

+39
-12

@@ -86,5 +86,4 @@ import { FOLIO_AGENT_TOOL_NAMES } from "./types.js";

* (see `FOLIO_DOCUMENT_OPERATION_JSON_SCHEMA` in `operation-schema.ts`):
* - excluded types: `formatRange` and `insertSignatureTable` (direct-only,
* not representable as tracked changes for human review) and
* `commentOnBlock` (covered by the dedicated `add_comment` tool);
* - excluded types: `insertSignatureTable` (direct-only) and `commentOnBlock`
* (covered by the dedicated `add_comment` tool);
* - `id` is optional here (auto-generated `op-1`, `op-2`, … by `parse.ts`)

@@ -96,10 +95,6 @@ * where the contract requires it;

* insert/replace formatting knobs (`inheritFormatting`, `pageBreakBefore`,
* `preserveFormatting`, `styleId`, `position`, `parties`, `quote`,
* `formatting`) are not exposed to the model.
* `preserveFormatting`, `styleId`, `parties`, `quote`,
* except `formatting`) are not exposed to the model.
*/
const SUGGEST_CHANGES_EXCLUDED_OPERATION_TYPES = /* @__PURE__ */ new Set([
"formatRange",
"commentOnBlock",
"insertSignatureTable"
]);
const SUGGEST_CHANGES_EXCLUDED_OPERATION_TYPES = /* @__PURE__ */ new Set(["commentOnBlock", "insertSignatureTable"]);
/**

@@ -129,5 +124,15 @@ * The contract operation types `suggest_changes` exposes to the model,

},
endBlockId: {
type: "string",
minLength: 1,
description: "For cell merging, a block in the opposite corner cell."
},
rowCount: {
type: "integer",
minimum: 2,
description: "For vertical cell merging, the number of grid rows to merge downward."
},
range: {
...FOLIO_TEXT_RANGE_JSON_SCHEMA,
description: "Required for `replaceRange` and `commentOnRange`: copy the range object returned by `find_text`."
description: "Required for `replaceRange`, `commentOnRange`, and `formatRange`: copy the range object returned by `find_text`."
},

@@ -146,2 +151,24 @@ find: {

},
position: {
type: "string",
enum: ["after", "before"],
description: "For row or column insertion, place the new structure after the anchor or before it."
},
cellTexts: {
type: "array",
description: "For row or column insertion, initial text for new physical cells in source order, up to 100,000 characters per cell.",
maxItems: 256,
items: { type: "string" }
},
formatting: {
type: "object",
description: "Required for `formatRange`: set one or more inline properties to enable or disable.",
properties: {
bold: { type: "boolean" },
italic: { type: "boolean" },
underline: { type: "boolean" }
},
minProperties: 1,
additionalProperties: false
},
comment: {

@@ -296,3 +323,3 @@ type: "string",

name: FOLIO_AGENT_TOOL_NAMES.readChanges,
description: "Read pending tracked changes (insertions and deletions) awaiting human review. Use this to see the effect of edits already suggested via `suggest_changes` before proposing more.",
description: "Read pending tracked changes awaiting human review. Use this to see the effect of edits already suggested via `suggest_changes` before proposing more.",
inputSchema: {

@@ -299,0 +326,0 @@ type: "object",

@@ -1,2 +0,2 @@

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

@@ -139,6 +139,6 @@ //#region src/types.d.ts

};
/** A pending tracked change (insertion or deletion), shaped to match {@link FolioDocxReviewer.getChanges}. */
/** A pending tracked change, shaped to match {@link FolioDocxReviewer.getChanges}. */
type FolioAgentChange = {
id: string;
type: "insertion" | "deletion";
type: FolioReviewChange["type"];
author: string;

@@ -145,0 +145,0 @@ text: string;

{
"name": "@stll/folio-agents",
"version": "0.6.1",
"version": "0.7.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.",

@@ -5,0 +5,0 @@ "keywords": [

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