@caupulican/pi-ai 0.81.12 → 0.81.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -200,15 +200,18 @@ function transformValue(issue, mode) {
200
200
  function applyTransform(candidate, issue, mode) {
201
201
  const transform = transformValue(issue, mode);
202
202
  if (!transform)
203
- return false;
203
+ return undefined;
204
204
  if (transform.type === "delete") {
205
- return deleteValueAtPath(candidate, issue.path);
205
+ return deleteValueAtPath(candidate, issue.path) ? candidate : undefined;
206
206
  }
207
207
  if (transform.value === undefined)
208
- return false;
208
+ return undefined;
209
209
  if (!schemaChecks(issue.schema, transform.value))
210
- return false;
211
- return setValueAtPath(candidate, issue.path, transform.value);
210
+ return undefined;
211
+ if (issue.path.length === 0) {
212
+ return isRecord(transform.value) ? transform.value : undefined;
213
+ }
214
+ return setValueAtPath(candidate, issue.path, transform.value) ? candidate : undefined;
212
215
  }
213
216
  function refreshIssueValue(candidate, issue) {
214
217
  return { ...issue, value: getValueAtPath(candidate, issue.path) };
@@ -217,7 +220,7 @@ export function repairToolArguments(toolName, schema, args, errors, checkWholeAr
217
220
  const issues = analyzeToolArgumentErrors(toolName, schema, args, errors);
218
221
  if (issues.length === 0)
219
222
  return undefined;
220
- const candidate = structuredClone(args);
223
+ let candidate = structuredClone(args);
221
224
  const repairsApplied = [];
222
225
  const repairs = [];
223
226
  for (const issue of issues) {
@@ -227,7 +230,9 @@ export function repairToolArguments(toolName, schema, args, errors, checkWholeAr
227
230
  for (const mode of currentIssue.modes) {
228
231
  if (mode === "nullRequiredBounce")
229
232
  continue;
230
- if (applyTransform(candidate, currentIssue, mode)) {
233
+ const nextCandidate = applyTransform(candidate, currentIssue, mode);
234
+ if (nextCandidate) {
235
+ candidate = nextCandidate;
231
236
  repairsApplied.push(mode);
232
237
  repairs.push({ name: mode, path: formatRepairPath(currentIssue.path) });
233
238
  break;
@@ -1 +1 @@
1
- {"version":3,"file":"repairer.js","sourceRoot":"","sources":["../../../src/utils/tool-repair/repairer.ts"],"names":[],"mappings":"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","sourcesContent":["import { Compile } from \"typebox/compile\";\nimport type { Tool } from \"../../types.ts\";\nimport {\n\tanalyzeToolArgumentErrors,\n\tformatRepairPath,\n\tgetEnumValues,\n\tgetSchemaTypes,\n\tgetValueAtPath,\n\tisJsonSchemaObject,\n\tisRecord,\n\ttype JsonSchemaObject,\n\ttype ToolRepairIssue,\n\ttype ValidationErrorLike,\n} from \"./analyzer.ts\";\nimport type { ToolRepairModeName } from \"./registry.ts\";\n\nexport interface AppliedToolRepair {\n\tname: ToolRepairModeName;\n\tpath: string;\n}\n\nconst schemaValidatorCache = new WeakMap<object, ReturnType<typeof Compile>>();\nconst bashCommandWrapperKeys = new Set([\"cmd\", \"command\", \"script\"]);\n\nexport interface ToolRepairResult {\n\targs: Record<string, unknown>;\n\trepairsApplied: ToolRepairModeName[];\n\trepairs: AppliedToolRepair[];\n}\n\nfunction getSchemaValidator(schema: JsonSchemaObject): ReturnType<typeof Compile> | undefined {\n\ttry {\n\t\tconst key = schema as object;\n\t\tconst cached = schemaValidatorCache.get(key);\n\t\tif (cached) return cached;\n\t\tconst validator = Compile(schema as Tool[\"parameters\"]);\n\t\tschemaValidatorCache.set(key, validator);\n\t\treturn validator;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction schemaChecks(schema: JsonSchemaObject, value: unknown): boolean {\n\treturn getSchemaValidator(schema)?.Check(value) === true;\n}\n\nfunction setValueAtPath(target: Record<string, unknown>, path: readonly string[], value: unknown): boolean {\n\tif (path.length === 0) return false;\n\tlet cursor: unknown = target;\n\tfor (let index = 0; index < path.length - 1; index++) {\n\t\tconst segment = path[index];\n\t\tif (Array.isArray(cursor)) {\n\t\t\tconst arrayIndex = Number(segment);\n\t\t\tif (!Number.isInteger(arrayIndex)) return false;\n\t\t\tcursor = cursor[arrayIndex];\n\t\t} else if (isRecord(cursor)) {\n\t\t\tcursor = cursor[segment];\n\t\t} else {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tconst finalSegment = path[path.length - 1];\n\tif (Array.isArray(cursor)) {\n\t\tconst arrayIndex = Number(finalSegment);\n\t\tif (!Number.isInteger(arrayIndex)) return false;\n\t\tcursor[arrayIndex] = value;\n\t\treturn true;\n\t}\n\tif (isRecord(cursor)) {\n\t\tcursor[finalSegment] = value;\n\t\treturn true;\n\t}\n\treturn false;\n}\n\nfunction deleteValueAtPath(target: Record<string, unknown>, path: readonly string[]): boolean {\n\tif (path.length === 0) return false;\n\tlet cursor: unknown = target;\n\tfor (let index = 0; index < path.length - 1; index++) {\n\t\tconst segment = path[index];\n\t\tif (Array.isArray(cursor)) {\n\t\t\tconst arrayIndex = Number(segment);\n\t\t\tif (!Number.isInteger(arrayIndex)) return false;\n\t\t\tcursor = cursor[arrayIndex];\n\t\t} else if (isRecord(cursor)) {\n\t\t\tcursor = cursor[segment];\n\t\t} else {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tconst finalSegment = path[path.length - 1];\n\tif (Array.isArray(cursor)) {\n\t\tconst arrayIndex = Number(finalSegment);\n\t\tif (!Number.isInteger(arrayIndex)) return false;\n\t\tcursor.splice(arrayIndex, 1);\n\t\treturn true;\n\t}\n\tif (isRecord(cursor)) {\n\t\tdelete cursor[finalSegment];\n\t\treturn true;\n\t}\n\treturn false;\n}\n\nfunction normalizeEnumValue(value: string): string {\n\treturn value.trim().replace(/\\s+/g, \" \").toLowerCase();\n}\n\nfunction findNormalizedEnumValue(schema: JsonSchemaObject, value: string): string | undefined {\n\tconst normalized = normalizeEnumValue(value);\n\tconst matches = getEnumValues(schema).filter((candidate) => normalizeEnumValue(candidate) === normalized);\n\treturn matches.length === 1 ? matches[0] : undefined;\n}\n\nfunction parseJsonContainer(value: string, schema: JsonSchemaObject): unknown | undefined {\n\tconst trimmed = value.trim();\n\tif (!trimmed.startsWith(\"[\") && !trimmed.startsWith(\"{\")) return undefined;\n\ttry {\n\t\tconst parsed: unknown = JSON.parse(trimmed);\n\t\tconst expectedTypes = getSchemaTypes(schema);\n\t\tif (expectedTypes.includes(\"array\") && !Array.isArray(parsed)) return undefined;\n\t\tif (expectedTypes.includes(\"object\") && (!isRecord(parsed) || Array.isArray(parsed))) return undefined;\n\t\treturn parsed;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction parseNumber(value: string, schema: JsonSchemaObject): number | undefined {\n\tif (value.trim() === \"\") return undefined;\n\tconst numberValue = Number(value);\n\tif (!Number.isFinite(numberValue)) return undefined;\n\treturn getSchemaTypes(schema).includes(\"integer\") && !Number.isInteger(numberValue) ? undefined : numberValue;\n}\n\nfunction coerceStringifiedNumberArray(value: unknown, schema: JsonSchemaObject): unknown[] | undefined {\n\tif (!Array.isArray(value) || !isJsonSchemaObject(schema.items)) return undefined;\n\tconst itemTypes = getSchemaTypes(schema.items);\n\tif (!itemTypes.some((type) => type === \"number\" || type === \"integer\")) return undefined;\n\tconst numbers: number[] = [];\n\tfor (const item of value) {\n\t\tif (typeof item !== \"string\") return undefined;\n\t\tconst parsed = parseNumber(item, schema.items);\n\t\tif (parsed === undefined) return undefined;\n\t\tnumbers.push(parsed);\n\t}\n\treturn numbers;\n}\n\nfunction unwrapBashCommand(value: unknown): string | undefined {\n\tif (!isRecord(value) || Object.keys(value).length !== 1) return undefined;\n\tconst [key] = Object.keys(value);\n\tif (!bashCommandWrapperKeys.has(key)) return undefined;\n\tconst command = value[key];\n\treturn typeof command === \"string\" ? command : undefined;\n}\n\nfunction transformValue(\n\tissue: ToolRepairIssue,\n\tmode: ToolRepairModeName,\n): { type: \"set\"; value: unknown } | { type: \"delete\" } | undefined {\n\tswitch (mode) {\n\t\tcase \"jsonStringParse\": {\n\t\t\treturn typeof issue.value === \"string\"\n\t\t\t\t? { type: \"set\", value: parseJsonContainer(issue.value, issue.schema) }\n\t\t\t\t: undefined;\n\t\t}\n\t\tcase \"singleObjectWrap\":\n\t\t\treturn isRecord(issue.value) ? { type: \"set\", value: [issue.value] } : undefined;\n\t\tcase \"bareScalarWrap\":\n\t\t\treturn [\"string\", \"number\", \"boolean\"].includes(typeof issue.value)\n\t\t\t\t? { type: \"set\", value: [issue.value] }\n\t\t\t\t: undefined;\n\t\tcase \"emptyObjectPlaceholder\":\n\t\t\treturn !issue.required && isRecord(issue.value) && Object.keys(issue.value).length === 0\n\t\t\t\t? { type: \"delete\" }\n\t\t\t\t: undefined;\n\t\tcase \"numberFromString\": {\n\t\t\tconst parsed = typeof issue.value === \"string\" ? parseNumber(issue.value, issue.schema) : undefined;\n\t\t\treturn parsed === undefined ? undefined : { type: \"set\", value: parsed };\n\t\t}\n\t\tcase \"boolFromString\":\n\t\t\tif (issue.value === \"true\") return { type: \"set\", value: true };\n\t\t\tif (issue.value === \"false\") return { type: \"set\", value: false };\n\t\t\treturn undefined;\n\t\tcase \"enumCaseNormalize\": {\n\t\t\tconst enumValue =\n\t\t\t\ttypeof issue.value === \"string\" ? findNormalizedEnumValue(issue.schema, issue.value) : undefined;\n\t\t\treturn enumValue === undefined ? undefined : { type: \"set\", value: enumValue };\n\t\t}\n\t\tcase \"singleElementUnwrap\":\n\t\t\treturn Array.isArray(issue.value) && issue.value.length === 1\n\t\t\t\t? { type: \"set\", value: issue.value[0] }\n\t\t\t\t: undefined;\n\t\tcase \"stringifiedNumberInArray\": {\n\t\t\tconst coerced = coerceStringifiedNumberArray(issue.value, issue.schema);\n\t\t\treturn coerced === undefined ? undefined : { type: \"set\", value: coerced };\n\t\t}\n\t\tcase \"nullOptionalDrop\":\n\t\t\treturn !issue.required && issue.value === null ? { type: \"delete\" } : undefined;\n\t\tcase \"nullRequiredBounce\":\n\t\t\treturn undefined;\n\t\tcase \"bashCommandArgvJoin\":\n\t\t\treturn Array.isArray(issue.value) && issue.value.every((item) => typeof item === \"string\")\n\t\t\t\t? { type: \"set\", value: issue.value.join(\" \") }\n\t\t\t\t: undefined;\n\t\tcase \"bashCommandUnwrap\": {\n\t\t\tconst command = unwrapBashCommand(issue.value);\n\t\t\treturn command === undefined ? undefined : { type: \"set\", value: command };\n\t\t}\n\t}\n}\n\nfunction applyTransform(candidate: Record<string, unknown>, issue: ToolRepairIssue, mode: ToolRepairModeName): boolean {\n\tconst transform = transformValue(issue, mode);\n\tif (!transform) return false;\n\tif (transform.type === \"delete\") {\n\t\treturn deleteValueAtPath(candidate, issue.path);\n\t}\n\tif (transform.value === undefined) return false;\n\tif (!schemaChecks(issue.schema, transform.value)) return false;\n\treturn setValueAtPath(candidate, issue.path, transform.value);\n}\n\nfunction refreshIssueValue(candidate: Record<string, unknown>, issue: ToolRepairIssue): ToolRepairIssue {\n\treturn { ...issue, value: getValueAtPath(candidate, issue.path) };\n}\n\nexport function repairToolArguments(\n\ttoolName: string,\n\tschema: Tool[\"parameters\"],\n\targs: Record<string, unknown>,\n\terrors: readonly ValidationErrorLike[],\n\tcheckWholeArgs: (candidate: Record<string, unknown>) => boolean,\n): ToolRepairResult | undefined {\n\tconst issues = analyzeToolArgumentErrors(toolName, schema, args, errors);\n\tif (issues.length === 0) return undefined;\n\n\tconst candidate = structuredClone(args);\n\tconst repairsApplied: ToolRepairModeName[] = [];\n\tconst repairs: AppliedToolRepair[] = [];\n\n\tfor (const issue of issues) {\n\t\tif (issue.modes.includes(\"nullRequiredBounce\")) continue;\n\t\tconst currentIssue = refreshIssueValue(candidate, issue);\n\t\tfor (const mode of currentIssue.modes) {\n\t\t\tif (mode === \"nullRequiredBounce\") continue;\n\t\t\tif (applyTransform(candidate, currentIssue, mode)) {\n\t\t\t\trepairsApplied.push(mode);\n\t\t\t\trepairs.push({ name: mode, path: formatRepairPath(currentIssue.path) });\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (repairsApplied.length === 0) return undefined;\n\tif (!checkWholeArgs(candidate)) return undefined;\n\treturn { args: candidate, repairsApplied, repairs };\n}\n\nexport function formatRepairSummary(repairsApplied: readonly ToolRepairModeName[]): string {\n\treturn repairsApplied.length === 0 ? \"none\" : repairsApplied.join(\", \");\n}\n\nexport function getRepairPathText(path: readonly string[]): string {\n\treturn formatRepairPath(path);\n}\n"]}
1
+ {"version":3,"file":"repairer.js","sourceRoot":"","sources":["../../../src/utils/tool-repair/repairer.ts"],"names":[],"mappings":"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","sourcesContent":["import { Compile } from \"typebox/compile\";\nimport type { Tool } from \"../../types.ts\";\nimport {\n\tanalyzeToolArgumentErrors,\n\tformatRepairPath,\n\tgetEnumValues,\n\tgetSchemaTypes,\n\tgetValueAtPath,\n\tisJsonSchemaObject,\n\tisRecord,\n\ttype JsonSchemaObject,\n\ttype ToolRepairIssue,\n\ttype ValidationErrorLike,\n} from \"./analyzer.ts\";\nimport type { ToolRepairModeName } from \"./registry.ts\";\n\nexport interface AppliedToolRepair {\n\tname: ToolRepairModeName;\n\tpath: string;\n}\n\nconst schemaValidatorCache = new WeakMap<object, ReturnType<typeof Compile>>();\nconst bashCommandWrapperKeys = new Set([\"cmd\", \"command\", \"script\"]);\n\nexport interface ToolRepairResult {\n\targs: Record<string, unknown>;\n\trepairsApplied: ToolRepairModeName[];\n\trepairs: AppliedToolRepair[];\n}\n\nfunction getSchemaValidator(schema: JsonSchemaObject): ReturnType<typeof Compile> | undefined {\n\ttry {\n\t\tconst key = schema as object;\n\t\tconst cached = schemaValidatorCache.get(key);\n\t\tif (cached) return cached;\n\t\tconst validator = Compile(schema as Tool[\"parameters\"]);\n\t\tschemaValidatorCache.set(key, validator);\n\t\treturn validator;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction schemaChecks(schema: JsonSchemaObject, value: unknown): boolean {\n\treturn getSchemaValidator(schema)?.Check(value) === true;\n}\n\nfunction setValueAtPath(target: Record<string, unknown>, path: readonly string[], value: unknown): boolean {\n\tif (path.length === 0) return false;\n\tlet cursor: unknown = target;\n\tfor (let index = 0; index < path.length - 1; index++) {\n\t\tconst segment = path[index];\n\t\tif (Array.isArray(cursor)) {\n\t\t\tconst arrayIndex = Number(segment);\n\t\t\tif (!Number.isInteger(arrayIndex)) return false;\n\t\t\tcursor = cursor[arrayIndex];\n\t\t} else if (isRecord(cursor)) {\n\t\t\tcursor = cursor[segment];\n\t\t} else {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tconst finalSegment = path[path.length - 1];\n\tif (Array.isArray(cursor)) {\n\t\tconst arrayIndex = Number(finalSegment);\n\t\tif (!Number.isInteger(arrayIndex)) return false;\n\t\tcursor[arrayIndex] = value;\n\t\treturn true;\n\t}\n\tif (isRecord(cursor)) {\n\t\tcursor[finalSegment] = value;\n\t\treturn true;\n\t}\n\treturn false;\n}\n\nfunction deleteValueAtPath(target: Record<string, unknown>, path: readonly string[]): boolean {\n\tif (path.length === 0) return false;\n\tlet cursor: unknown = target;\n\tfor (let index = 0; index < path.length - 1; index++) {\n\t\tconst segment = path[index];\n\t\tif (Array.isArray(cursor)) {\n\t\t\tconst arrayIndex = Number(segment);\n\t\t\tif (!Number.isInteger(arrayIndex)) return false;\n\t\t\tcursor = cursor[arrayIndex];\n\t\t} else if (isRecord(cursor)) {\n\t\t\tcursor = cursor[segment];\n\t\t} else {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tconst finalSegment = path[path.length - 1];\n\tif (Array.isArray(cursor)) {\n\t\tconst arrayIndex = Number(finalSegment);\n\t\tif (!Number.isInteger(arrayIndex)) return false;\n\t\tcursor.splice(arrayIndex, 1);\n\t\treturn true;\n\t}\n\tif (isRecord(cursor)) {\n\t\tdelete cursor[finalSegment];\n\t\treturn true;\n\t}\n\treturn false;\n}\n\nfunction normalizeEnumValue(value: string): string {\n\treturn value.trim().replace(/\\s+/g, \" \").toLowerCase();\n}\n\nfunction findNormalizedEnumValue(schema: JsonSchemaObject, value: string): string | undefined {\n\tconst normalized = normalizeEnumValue(value);\n\tconst matches = getEnumValues(schema).filter((candidate) => normalizeEnumValue(candidate) === normalized);\n\treturn matches.length === 1 ? matches[0] : undefined;\n}\n\nfunction parseJsonContainer(value: string, schema: JsonSchemaObject): unknown | undefined {\n\tconst trimmed = value.trim();\n\tif (!trimmed.startsWith(\"[\") && !trimmed.startsWith(\"{\")) return undefined;\n\ttry {\n\t\tconst parsed: unknown = JSON.parse(trimmed);\n\t\tconst expectedTypes = getSchemaTypes(schema);\n\t\tif (expectedTypes.includes(\"array\") && !Array.isArray(parsed)) return undefined;\n\t\tif (expectedTypes.includes(\"object\") && (!isRecord(parsed) || Array.isArray(parsed))) return undefined;\n\t\treturn parsed;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction parseNumber(value: string, schema: JsonSchemaObject): number | undefined {\n\tif (value.trim() === \"\") return undefined;\n\tconst numberValue = Number(value);\n\tif (!Number.isFinite(numberValue)) return undefined;\n\treturn getSchemaTypes(schema).includes(\"integer\") && !Number.isInteger(numberValue) ? undefined : numberValue;\n}\n\nfunction coerceStringifiedNumberArray(value: unknown, schema: JsonSchemaObject): unknown[] | undefined {\n\tif (!Array.isArray(value) || !isJsonSchemaObject(schema.items)) return undefined;\n\tconst itemTypes = getSchemaTypes(schema.items);\n\tif (!itemTypes.some((type) => type === \"number\" || type === \"integer\")) return undefined;\n\tconst numbers: number[] = [];\n\tfor (const item of value) {\n\t\tif (typeof item !== \"string\") return undefined;\n\t\tconst parsed = parseNumber(item, schema.items);\n\t\tif (parsed === undefined) return undefined;\n\t\tnumbers.push(parsed);\n\t}\n\treturn numbers;\n}\n\nfunction unwrapBashCommand(value: unknown): string | undefined {\n\tif (!isRecord(value) || Object.keys(value).length !== 1) return undefined;\n\tconst [key] = Object.keys(value);\n\tif (!bashCommandWrapperKeys.has(key)) return undefined;\n\tconst command = value[key];\n\treturn typeof command === \"string\" ? command : undefined;\n}\n\nfunction transformValue(\n\tissue: ToolRepairIssue,\n\tmode: ToolRepairModeName,\n): { type: \"set\"; value: unknown } | { type: \"delete\" } | undefined {\n\tswitch (mode) {\n\t\tcase \"jsonStringParse\": {\n\t\t\treturn typeof issue.value === \"string\"\n\t\t\t\t? { type: \"set\", value: parseJsonContainer(issue.value, issue.schema) }\n\t\t\t\t: undefined;\n\t\t}\n\t\tcase \"singleObjectWrap\":\n\t\t\treturn isRecord(issue.value) ? { type: \"set\", value: [issue.value] } : undefined;\n\t\tcase \"bareScalarWrap\":\n\t\t\treturn [\"string\", \"number\", \"boolean\"].includes(typeof issue.value)\n\t\t\t\t? { type: \"set\", value: [issue.value] }\n\t\t\t\t: undefined;\n\t\tcase \"emptyObjectPlaceholder\":\n\t\t\treturn !issue.required && isRecord(issue.value) && Object.keys(issue.value).length === 0\n\t\t\t\t? { type: \"delete\" }\n\t\t\t\t: undefined;\n\t\tcase \"numberFromString\": {\n\t\t\tconst parsed = typeof issue.value === \"string\" ? parseNumber(issue.value, issue.schema) : undefined;\n\t\t\treturn parsed === undefined ? undefined : { type: \"set\", value: parsed };\n\t\t}\n\t\tcase \"boolFromString\":\n\t\t\tif (issue.value === \"true\") return { type: \"set\", value: true };\n\t\t\tif (issue.value === \"false\") return { type: \"set\", value: false };\n\t\t\treturn undefined;\n\t\tcase \"enumCaseNormalize\": {\n\t\t\tconst enumValue =\n\t\t\t\ttypeof issue.value === \"string\" ? findNormalizedEnumValue(issue.schema, issue.value) : undefined;\n\t\t\treturn enumValue === undefined ? undefined : { type: \"set\", value: enumValue };\n\t\t}\n\t\tcase \"singleElementUnwrap\":\n\t\t\treturn Array.isArray(issue.value) && issue.value.length === 1\n\t\t\t\t? { type: \"set\", value: issue.value[0] }\n\t\t\t\t: undefined;\n\t\tcase \"stringifiedNumberInArray\": {\n\t\t\tconst coerced = coerceStringifiedNumberArray(issue.value, issue.schema);\n\t\t\treturn coerced === undefined ? undefined : { type: \"set\", value: coerced };\n\t\t}\n\t\tcase \"nullOptionalDrop\":\n\t\t\treturn !issue.required && issue.value === null ? { type: \"delete\" } : undefined;\n\t\tcase \"nullRequiredBounce\":\n\t\t\treturn undefined;\n\t\tcase \"bashCommandArgvJoin\":\n\t\t\treturn Array.isArray(issue.value) && issue.value.every((item) => typeof item === \"string\")\n\t\t\t\t? { type: \"set\", value: issue.value.join(\" \") }\n\t\t\t\t: undefined;\n\t\tcase \"bashCommandUnwrap\": {\n\t\t\tconst command = unwrapBashCommand(issue.value);\n\t\t\treturn command === undefined ? undefined : { type: \"set\", value: command };\n\t\t}\n\t}\n}\n\nfunction applyTransform(\n\tcandidate: Record<string, unknown>,\n\tissue: ToolRepairIssue,\n\tmode: ToolRepairModeName,\n): Record<string, unknown> | undefined {\n\tconst transform = transformValue(issue, mode);\n\tif (!transform) return undefined;\n\tif (transform.type === \"delete\") {\n\t\treturn deleteValueAtPath(candidate, issue.path) ? candidate : undefined;\n\t}\n\tif (transform.value === undefined) return undefined;\n\tif (!schemaChecks(issue.schema, transform.value)) return undefined;\n\tif (issue.path.length === 0) {\n\t\treturn isRecord(transform.value) ? transform.value : undefined;\n\t}\n\treturn setValueAtPath(candidate, issue.path, transform.value) ? candidate : undefined;\n}\n\nfunction refreshIssueValue(candidate: Record<string, unknown>, issue: ToolRepairIssue): ToolRepairIssue {\n\treturn { ...issue, value: getValueAtPath(candidate, issue.path) };\n}\n\nexport function repairToolArguments(\n\ttoolName: string,\n\tschema: Tool[\"parameters\"],\n\targs: Record<string, unknown>,\n\terrors: readonly ValidationErrorLike[],\n\tcheckWholeArgs: (candidate: Record<string, unknown>) => boolean,\n): ToolRepairResult | undefined {\n\tconst issues = analyzeToolArgumentErrors(toolName, schema, args, errors);\n\tif (issues.length === 0) return undefined;\n\n\tlet candidate = structuredClone(args);\n\tconst repairsApplied: ToolRepairModeName[] = [];\n\tconst repairs: AppliedToolRepair[] = [];\n\n\tfor (const issue of issues) {\n\t\tif (issue.modes.includes(\"nullRequiredBounce\")) continue;\n\t\tconst currentIssue = refreshIssueValue(candidate, issue);\n\t\tfor (const mode of currentIssue.modes) {\n\t\t\tif (mode === \"nullRequiredBounce\") continue;\n\t\t\tconst nextCandidate = applyTransform(candidate, currentIssue, mode);\n\t\t\tif (nextCandidate) {\n\t\t\t\tcandidate = nextCandidate;\n\t\t\t\trepairsApplied.push(mode);\n\t\t\t\trepairs.push({ name: mode, path: formatRepairPath(currentIssue.path) });\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (repairsApplied.length === 0) return undefined;\n\tif (!checkWholeArgs(candidate)) return undefined;\n\treturn { args: candidate, repairsApplied, repairs };\n}\n\nexport function formatRepairSummary(repairsApplied: readonly ToolRepairModeName[]): string {\n\treturn repairsApplied.length === 0 ? \"none\" : repairsApplied.join(\", \");\n}\n\nexport function getRepairPathText(path: readonly string[]): string {\n\treturn formatRepairPath(path);\n}\n"]}
@@ -1,7 +1,10 @@
1
1
  import type { Tool, ToolCall } from "../../types.ts";
2
+ export type TextToolProtocolParseFailure = "overlap" | "mixed-prose" | "unrecognized";
2
3
  export interface ParsedTextToolCalls {
3
4
  calls: ToolCall[];
4
5
  text: string;
6
+ attempted: boolean;
7
+ failure?: TextToolProtocolParseFailure;
5
8
  }
6
9
  export type TextToolProtocolVariant = "tool-tag" | "tool-call" | "fenced-json";
7
10
  export interface TextToolProtocolOptions {
@@ -1 +1 @@
1
- {"version":3,"file":"text-protocol.d.ts","sourceRoot":"","sources":["../../../src/utils/tool-repair/text-protocol.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAErD,MAAM,WAAW,mBAAmB;IACnC,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACb;AAED,MAAM,MAAM,uBAAuB,GAAG,UAAU,GAAG,WAAW,GAAG,aAAa,CAAC;AAE/E,MAAM,WAAW,uBAAuB;IACvC,OAAO,CAAC,EAAE,uBAAuB,CAAC;CAClC;AAkKD,wBAAgB,gCAAgC,CAC/C,MAAM,EAAE,OAAO,GAAG,uBAAuB,GAAG,SAAS,GACnD,uBAAuB,GAAG,SAAS,CAIrC;AAQD,wBAAgB,8BAA8B,CAAC,KAAK,EAAE,SAAS,IAAI,EAAE,EAAE,OAAO,CAAC,EAAE,uBAAuB,GAAG,MAAM,CAehH;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,IAAI,EAAE,GAAG,mBAAmB,CAWjG","sourcesContent":["import type { Tool, ToolCall } from \"../../types.ts\";\n\nexport interface ParsedTextToolCalls {\n\tcalls: ToolCall[];\n\ttext: string;\n}\n\nexport type TextToolProtocolVariant = \"tool-tag\" | \"tool-call\" | \"fenced-json\";\n\nexport interface TextToolProtocolOptions {\n\tvariant?: TextToolProtocolVariant;\n}\n\ntype EnvelopeKind = \"tool\" | \"tool_call\" | \"fenced_json\";\n\ninterface EnvelopeMatch {\n\tkind: EnvelopeKind;\n\tstart: number;\n\tend: number;\n\tname?: string;\n\tbody: string;\n}\n\nconst MAX_SCHEMA_CHARS = 600;\nconst DEFAULT_TEXT_TOOL_PROTOCOL_VARIANT: TextToolProtocolVariant = \"tool-tag\";\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction compactJson(value: unknown, maxChars = MAX_SCHEMA_CHARS): string {\n\tconst json = JSON.stringify(value);\n\tif (json.length <= maxChars) return json;\n\treturn `${json.slice(0, maxChars - 1)}…`;\n}\n\nfunction escapeAttribute(value: string): string {\n\treturn value.replace(/&/g, \"&amp;\").replace(/\"/g, \"&quot;\").replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\");\n}\n\nfunction unescapeAttribute(value: string): string {\n\treturn value\n\t\t.replace(/&quot;/g, '\"')\n\t\t.replace(/&lt;/g, \"<\")\n\t\t.replace(/&gt;/g, \">\")\n\t\t.replace(/&amp;/g, \"&\");\n}\n\nfunction knownToolNames(tools: readonly Tool[]): Set<string> {\n\treturn new Set(tools.map((tool) => tool.name));\n}\n\nfunction findToolEnvelopes(text: string): EnvelopeMatch[] {\n\tconst matches: EnvelopeMatch[] = [];\n\tconst toolEnvelope = /<tool\\s+name=\"([^\"]+)\">([\\s\\S]*?)<\\/tool>/g;\n\tfor (const match of text.matchAll(toolEnvelope)) {\n\t\tmatches.push({\n\t\t\tkind: \"tool\",\n\t\t\tstart: match.index,\n\t\t\tend: match.index + match[0].length,\n\t\t\tname: unescapeAttribute(match[1] ?? \"\"),\n\t\t\tbody: match[2] ?? \"\",\n\t\t});\n\t}\n\n\tconst toolCallEnvelope = /<tool_call>([\\s\\S]*?)<\\/tool_call>/g;\n\tfor (const match of text.matchAll(toolCallEnvelope)) {\n\t\tmatches.push({\n\t\t\tkind: \"tool_call\",\n\t\t\tstart: match.index,\n\t\t\tend: match.index + match[0].length,\n\t\t\tbody: match[1] ?? \"\",\n\t\t});\n\t}\n\n\tconst trimmed = text.trim();\n\tconst fence = /^```(?:json|tool|tool_call)?\\s*\\n?([\\s\\S]*?)\\n?```$/i.exec(trimmed);\n\tif (fence?.[1]) {\n\t\tconst start = text.indexOf(trimmed);\n\t\tmatches.push({ kind: \"fenced_json\", start, end: start + trimmed.length, body: fence[1] });\n\t}\n\n\treturn matches.sort((a, b) => a.start - b.start);\n}\n\nfunction hasOverlap(matches: readonly EnvelopeMatch[]): boolean {\n\tlet previousEnd = -1;\n\tfor (const match of matches) {\n\t\tif (match.start < previousEnd) return true;\n\t\tpreviousEnd = match.end;\n\t}\n\treturn false;\n}\n\nfunction remainingText(text: string, matches: readonly EnvelopeMatch[]): string | undefined {\n\tlet cursor = 0;\n\tconst pieces: string[] = [];\n\tfor (const match of matches) {\n\t\tpieces.push(text.slice(cursor, match.start));\n\t\tcursor = match.end;\n\t}\n\tpieces.push(text.slice(cursor));\n\tconst remainder = pieces.join(\"\");\n\treturn remainder.trim().length === 0 ? remainder : undefined;\n}\n\nfunction coerceArguments(value: unknown): {\n\targuments: Record<string, unknown>;\n\trawArguments?: Record<string, unknown>;\n} {\n\tif (isRecord(value)) return { arguments: value };\n\treturn { arguments: {}, rawArguments: { value } };\n}\n\nfunction parseJsonObject(raw: string): Record<string, unknown> | undefined {\n\ttry {\n\t\tconst parsed = JSON.parse(raw);\n\t\treturn isRecord(parsed) ? parsed : undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction extractNameFromMalformedJson(raw: string, names: ReadonlySet<string>): string | undefined {\n\tfor (const name of names) {\n\t\tif (raw.includes(`\"${name}\"`)) return name;\n\t}\n\treturn undefined;\n}\n\nfunction parseEnvelope(match: EnvelopeMatch, names: ReadonlySet<string>, index: number): ToolCall | undefined {\n\tif (match.kind === \"tool\") {\n\t\tif (!match.name || !names.has(match.name)) return undefined;\n\t\tconst parsed = parseJsonObject(match.body);\n\t\tconst args = parsed ? { arguments: parsed } : { arguments: {}, rawArguments: { text: match.body.trim() } };\n\t\treturn {\n\t\t\ttype: \"toolCall\",\n\t\t\tid: `text-tool-${index}`,\n\t\t\tname: match.name,\n\t\t\targuments: args.arguments,\n\t\t\trawArguments: args.rawArguments,\n\t\t\tsource: \"text-protocol\",\n\t\t};\n\t}\n\n\tconst parsed = parseJsonObject(match.body);\n\tif (!parsed) {\n\t\tconst name = extractNameFromMalformedJson(match.body, names);\n\t\tif (!name) return undefined;\n\t\treturn {\n\t\t\ttype: \"toolCall\",\n\t\t\tid: `text-tool-${index}`,\n\t\t\tname,\n\t\t\targuments: {},\n\t\t\trawArguments: { text: match.body.trim() },\n\t\t\tsource: \"text-protocol\",\n\t\t};\n\t}\n\n\tconst nameValue = parsed.name ?? parsed.tool;\n\tif (typeof nameValue !== \"string\" || !names.has(nameValue)) return undefined;\n\tconst argsValue = parsed.arguments ?? parsed.args ?? {};\n\tconst args = coerceArguments(argsValue);\n\treturn {\n\t\ttype: \"toolCall\",\n\t\tid: `text-tool-${index}`,\n\t\tname: nameValue,\n\t\targuments: args.arguments,\n\t\trawArguments: args.rawArguments,\n\t\tsource: \"text-protocol\",\n\t};\n}\n\nexport function normalizeTextToolProtocolOptions(\n\toption: boolean | TextToolProtocolOptions | undefined,\n): TextToolProtocolOptions | undefined {\n\tif (!option) return undefined;\n\tif (option === true) return { variant: DEFAULT_TEXT_TOOL_PROTOCOL_VARIANT };\n\treturn { variant: option.variant ?? DEFAULT_TEXT_TOOL_PROTOCOL_VARIANT };\n}\n\nfunction formatVariantEnvelope(variant: TextToolProtocolVariant, toolName: string, argsJson: string): string {\n\tif (variant === \"tool-call\") return `<tool_call>{\"name\":\"${toolName}\",\"arguments\":${argsJson}}</tool_call>`;\n\tif (variant === \"fenced-json\") return `\\`\\`\\`tool_call\\n{\"name\":\"${toolName}\",\"arguments\":${argsJson}}\\n\\`\\`\\``;\n\treturn `<tool name=\"${escapeAttribute(toolName)}\">${argsJson}</tool>`;\n}\n\nexport function generateTextToolProtocolPrimer(tools: readonly Tool[], options?: TextToolProtocolOptions): string {\n\tif (tools.length === 0) return \"\";\n\tconst variant = options?.variant ?? DEFAULT_TEXT_TOOL_PROTOCOL_VARIANT;\n\tconst lines = [\n\t\t\"Text tool-call protocol is enabled.\",\n\t\t\"When calling tools, output only one or more envelopes and no prose:\",\n\t\tformatVariantEnvelope(variant, \"TOOL_NAME\", '{\"argument\":\"value\"}'),\n\t\t\"Available tools:\",\n\t];\n\tfor (const tool of tools) {\n\t\tlines.push(`- ${escapeAttribute(tool.name)}: ${tool.description}; args schema ${compactJson(tool.parameters)}`);\n\t}\n\tconst exampleTool = tools[0];\n\tlines.push(\"Examples:\", formatVariantEnvelope(variant, exampleTool.name, \"{}\"));\n\treturn lines.join(\"\\n\");\n}\n\nexport function parseTextToolCalls(text: string, knownTools: readonly Tool[]): ParsedTextToolCalls {\n\tif (knownTools.length === 0) return { calls: [], text };\n\tconst matches = findToolEnvelopes(text);\n\tif (matches.length === 0 || hasOverlap(matches)) return { calls: [], text };\n\tconst remainder = remainingText(text, matches);\n\tif (remainder === undefined) return { calls: [], text };\n\tconst names = knownToolNames(knownTools);\n\tconst calls = matches\n\t\t.map((match, index) => parseEnvelope(match, names, index + 1))\n\t\t.filter((call): call is ToolCall => call !== undefined);\n\treturn calls.length > 0 ? { calls, text: remainder.trim() } : { calls: [], text };\n}\n"]}
1
+ {"version":3,"file":"text-protocol.d.ts","sourceRoot":"","sources":["../../../src/utils/tool-repair/text-protocol.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAErD,MAAM,MAAM,4BAA4B,GAAG,SAAS,GAAG,aAAa,GAAG,cAAc,CAAC;AAEtF,MAAM,WAAW,mBAAmB;IACnC,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,4BAA4B,CAAC;CACvC;AAED,MAAM,MAAM,uBAAuB,GAAG,UAAU,GAAG,WAAW,GAAG,aAAa,CAAC;AAE/E,MAAM,WAAW,uBAAuB;IACvC,OAAO,CAAC,EAAE,uBAAuB,CAAC;CAClC;AAgLD,wBAAgB,gCAAgC,CAC/C,MAAM,EAAE,OAAO,GAAG,uBAAuB,GAAG,SAAS,GACnD,uBAAuB,GAAG,SAAS,CAIrC;AAQD,wBAAgB,8BAA8B,CAAC,KAAK,EAAE,SAAS,IAAI,EAAE,EAAE,OAAO,CAAC,EAAE,uBAAuB,GAAG,MAAM,CAehH;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,IAAI,EAAE,GAAG,mBAAmB,CAajG","sourcesContent":["import type { Tool, ToolCall } from \"../../types.ts\";\n\nexport type TextToolProtocolParseFailure = \"overlap\" | \"mixed-prose\" | \"unrecognized\";\n\nexport interface ParsedTextToolCalls {\n\tcalls: ToolCall[];\n\ttext: string;\n\tattempted: boolean;\n\tfailure?: TextToolProtocolParseFailure;\n}\n\nexport type TextToolProtocolVariant = \"tool-tag\" | \"tool-call\" | \"fenced-json\";\n\nexport interface TextToolProtocolOptions {\n\tvariant?: TextToolProtocolVariant;\n}\n\ntype EnvelopeKind = \"pi_call\" | \"tool_call\" | \"fenced_json\";\n\ninterface EnvelopeMatch {\n\tkind: EnvelopeKind;\n\tstart: number;\n\tend: number;\n\tname?: string;\n\tbody: string;\n}\n\nconst MAX_SCHEMA_CHARS = 600;\nconst DEFAULT_TEXT_TOOL_PROTOCOL_VARIANT: TextToolProtocolVariant = \"tool-tag\";\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction compactJson(value: unknown, maxChars = MAX_SCHEMA_CHARS): string {\n\tconst json = JSON.stringify(value);\n\tif (json.length <= maxChars) return json;\n\treturn `${json.slice(0, maxChars - 1)}…`;\n}\n\nfunction escapeAttribute(value: string): string {\n\treturn value.replace(/&/g, \"&amp;\").replace(/\"/g, \"&quot;\").replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\");\n}\n\nfunction unescapeAttribute(value: string): string {\n\treturn value\n\t\t.replace(/&quot;/g, '\"')\n\t\t.replace(/&lt;/g, \"<\")\n\t\t.replace(/&gt;/g, \">\")\n\t\t.replace(/&amp;/g, \"&\");\n}\n\nfunction knownToolNames(tools: readonly Tool[]): Set<string> {\n\treturn new Set(tools.map((tool) => tool.name));\n}\n\nfunction findToolEnvelopes(text: string): EnvelopeMatch[] {\n\tconst matches: EnvelopeMatch[] = [];\n\tconst piCallEnvelope = /<pi:call\\s+name=\"([^\"]+)\"\\s*>([\\s\\S]*?)<\\/pi:call>/g;\n\tfor (const match of text.matchAll(piCallEnvelope)) {\n\t\tmatches.push({\n\t\t\tkind: \"pi_call\",\n\t\t\tstart: match.index,\n\t\t\tend: match.index + match[0].length,\n\t\t\tname: unescapeAttribute(match[1] ?? \"\"),\n\t\t\tbody: match[2] ?? \"\",\n\t\t});\n\t}\n\n\tconst toolCallEnvelope = /<tool_call>([\\s\\S]*?)<\\/tool_call>/g;\n\tfor (const match of text.matchAll(toolCallEnvelope)) {\n\t\tmatches.push({\n\t\t\tkind: \"tool_call\",\n\t\t\tstart: match.index,\n\t\t\tend: match.index + match[0].length,\n\t\t\tbody: match[1] ?? \"\",\n\t\t});\n\t}\n\n\tconst fence = /```(?:tool|tool_call)\\s*\\n([\\s\\S]*?)\\n?```/gi;\n\tfor (const match of text.matchAll(fence)) {\n\t\tmatches.push({\n\t\t\tkind: \"fenced_json\",\n\t\t\tstart: match.index,\n\t\t\tend: match.index + match[0].length,\n\t\t\tbody: match[1] ?? \"\",\n\t\t});\n\t}\n\n\treturn matches.sort((a, b) => a.start - b.start);\n}\n\nfunction hasOverlap(matches: readonly EnvelopeMatch[]): boolean {\n\tlet previousEnd = -1;\n\tfor (const match of matches) {\n\t\tif (match.start < previousEnd) return true;\n\t\tpreviousEnd = match.end;\n\t}\n\treturn false;\n}\n\nfunction remainingText(text: string, matches: readonly EnvelopeMatch[]): string {\n\tlet cursor = 0;\n\tconst pieces: string[] = [];\n\tfor (const match of matches) {\n\t\tpieces.push(text.slice(cursor, match.start));\n\t\tcursor = match.end;\n\t}\n\tpieces.push(text.slice(cursor));\n\treturn pieces.join(\"\");\n}\n\nfunction coerceArguments(value: unknown): {\n\targuments: Record<string, unknown>;\n\trawArguments?: Record<string, unknown>;\n} {\n\tif (isRecord(value)) return { arguments: value };\n\treturn { arguments: value as Record<string, unknown>, rawArguments: { value } };\n}\n\nfunction parseJsonValue(raw: string): { ok: true; value: unknown } | { ok: false } {\n\ttry {\n\t\treturn { ok: true, value: JSON.parse(raw) as unknown };\n\t} catch {\n\t\treturn { ok: false };\n\t}\n}\n\nfunction parseJsonObject(raw: string): Record<string, unknown> | undefined {\n\tconst parsed = parseJsonValue(raw);\n\treturn parsed.ok && isRecord(parsed.value) ? parsed.value : undefined;\n}\n\nfunction textToolErrorMessage(name: string, names: readonly string[]): string | undefined {\n\tif (names.includes(name)) return undefined;\n\treturn `Unknown tool \"${name}\". Valid tools: ${names.join(\", \")}.`;\n}\n\nfunction extractNameFromMalformedJson(raw: string): string | undefined {\n\tconst match = /\"(?:name|tool)\"\\s*:\\s*\"([^\"]+)\"/.exec(raw);\n\treturn match?.[1];\n}\n\nfunction parsePiCallEnvelope(match: EnvelopeMatch, names: readonly string[], index: number): ToolCall | undefined {\n\tif (!match.name) return undefined;\n\tconst parsed = parseJsonValue(match.body);\n\tconst args = parsed.ok ? coerceArguments(parsed.value) : coerceArguments(match.body.trim());\n\treturn {\n\t\ttype: \"toolCall\",\n\t\tid: `text-tool-${index}`,\n\t\tname: match.name,\n\t\targuments: args.arguments,\n\t\trawArguments: parsed.ok ? args.rawArguments : { text: match.body.trim() },\n\t\tsource: \"text-protocol\",\n\t\terrorMessage: textToolErrorMessage(match.name, names),\n\t};\n}\n\nfunction parseEnvelope(match: EnvelopeMatch, names: readonly string[], index: number): ToolCall | undefined {\n\tif (match.kind === \"pi_call\") return parsePiCallEnvelope(match, names, index);\n\n\tconst parsed = parseJsonObject(match.body);\n\tif (!parsed) {\n\t\tconst name = extractNameFromMalformedJson(match.body);\n\t\tif (!name) return undefined;\n\t\treturn {\n\t\t\ttype: \"toolCall\",\n\t\t\tid: `text-tool-${index}`,\n\t\t\tname,\n\t\t\targuments: match.body.trim() as unknown as Record<string, unknown>,\n\t\t\trawArguments: { text: match.body.trim() },\n\t\t\tsource: \"text-protocol\",\n\t\t\terrorMessage: textToolErrorMessage(name, names),\n\t\t};\n\t}\n\n\tconst nameValue = parsed.name ?? parsed.tool;\n\tif (typeof nameValue !== \"string\") return undefined;\n\tconst argsValue = parsed.arguments ?? parsed.args ?? {};\n\tconst args = coerceArguments(argsValue);\n\treturn {\n\t\ttype: \"toolCall\",\n\t\tid: `text-tool-${index}`,\n\t\tname: nameValue,\n\t\targuments: args.arguments,\n\t\trawArguments: args.rawArguments,\n\t\tsource: \"text-protocol\",\n\t\terrorMessage: textToolErrorMessage(nameValue, names),\n\t};\n}\n\nexport function normalizeTextToolProtocolOptions(\n\toption: boolean | TextToolProtocolOptions | undefined,\n): TextToolProtocolOptions | undefined {\n\tif (!option) return undefined;\n\tif (option === true) return { variant: DEFAULT_TEXT_TOOL_PROTOCOL_VARIANT };\n\treturn { variant: option.variant ?? DEFAULT_TEXT_TOOL_PROTOCOL_VARIANT };\n}\n\nfunction formatVariantEnvelope(variant: TextToolProtocolVariant, toolName: string, argsJson: string): string {\n\tif (variant === \"tool-call\") return `<tool_call>{\"name\":\"${toolName}\",\"arguments\":${argsJson}}</tool_call>`;\n\tif (variant === \"fenced-json\") return `\\`\\`\\`tool_call\\n{\"name\":\"${toolName}\",\"arguments\":${argsJson}}\\n\\`\\`\\``;\n\treturn `<pi:call name=\"${escapeAttribute(toolName)}\">${argsJson}</pi:call>`;\n}\n\nexport function generateTextToolProtocolPrimer(tools: readonly Tool[], options?: TextToolProtocolOptions): string {\n\tif (tools.length === 0) return \"\";\n\tconst variant = options?.variant ?? DEFAULT_TEXT_TOOL_PROTOCOL_VARIANT;\n\tconst lines = [\n\t\t\"Text tool-call protocol is enabled.\",\n\t\t\"When calling tools, output only one or more envelopes and no prose:\",\n\t\tformatVariantEnvelope(variant, \"TOOL_NAME\", '{\"argument\":\"value\"}'),\n\t\t\"Available tools:\",\n\t];\n\tfor (const tool of tools) {\n\t\tlines.push(`- ${escapeAttribute(tool.name)}: ${tool.description}; args schema ${compactJson(tool.parameters)}`);\n\t}\n\tconst exampleTool = tools[0];\n\tlines.push(\"Examples:\", formatVariantEnvelope(variant, exampleTool.name, \"{}\"));\n\treturn lines.join(\"\\n\");\n}\n\nexport function parseTextToolCalls(text: string, knownTools: readonly Tool[]): ParsedTextToolCalls {\n\tif (knownTools.length === 0) return { calls: [], text, attempted: false };\n\tconst matches = findToolEnvelopes(text);\n\tif (matches.length === 0) return { calls: [], text, attempted: false };\n\tif (hasOverlap(matches)) return { calls: [], text, attempted: true, failure: \"overlap\" };\n\tconst remainder = remainingText(text, matches);\n\tconst names = [...knownToolNames(knownTools)];\n\tconst calls = matches\n\t\t.map((match, index) => parseEnvelope(match, names, index + 1))\n\t\t.filter((call): call is ToolCall => call !== undefined);\n\treturn calls.length > 0\n\t\t? { calls, text: remainder.trim(), attempted: true }\n\t\t: { calls: [], text, attempted: true, failure: \"unrecognized\" };\n}\n"]}
@@ -24,10 +24,10 @@ function knownToolNames(tools) {
24
24
  }
25
25
  function findToolEnvelopes(text) {
26
26
  const matches = [];
27
- const toolEnvelope = /<tool\s+name="([^"]+)">([\s\S]*?)<\/tool>/g;
28
- for (const match of text.matchAll(toolEnvelope)) {
27
+ const piCallEnvelope = /<pi:call\s+name="([^"]+)"\s*>([\s\S]*?)<\/pi:call>/g;
28
+ for (const match of text.matchAll(piCallEnvelope)) {
29
29
  matches.push({
30
- kind: "tool",
30
+ kind: "pi_call",
31
31
  start: match.index,
32
32
  end: match.index + match[0].length,
33
33
  name: unescapeAttribute(match[1] ?? ""),
@@ -43,11 +43,14 @@ function findToolEnvelopes(text) {
43
43
  body: match[1] ?? "",
44
44
  });
45
45
  }
46
- const trimmed = text.trim();
47
- const fence = /^```(?:json|tool|tool_call)?\s*\n?([\s\S]*?)\n?```$/i.exec(trimmed);
48
- if (fence?.[1]) {
49
- const start = text.indexOf(trimmed);
50
- matches.push({ kind: "fenced_json", start, end: start + trimmed.length, body: fence[1] });
46
+ const fence = /```(?:tool|tool_call)\s*\n([\s\S]*?)\n?```/gi;
47
+ for (const match of text.matchAll(fence)) {
48
+ matches.push({
49
+ kind: "fenced_json",
50
+ start: match.index,
51
+ end: match.index + match[0].length,
52
+ body: match[1] ?? "",
53
+ });
51
54
  }
52
55
  return matches.sort((a, b) => a.start - b.start);
53
56
  }
@@ -68,61 +71,69 @@ function remainingText(text, matches) {
68
71
  cursor = match.end;
69
72
  }
70
73
  pieces.push(text.slice(cursor));
71
- const remainder = pieces.join("");
72
- return remainder.trim().length === 0 ? remainder : undefined;
74
+ return pieces.join("");
73
75
  }
74
76
  function coerceArguments(value) {
75
77
  if (isRecord(value))
76
78
  return { arguments: value };
77
- return { arguments: {}, rawArguments: { value } };
79
+ return { arguments: value, rawArguments: { value } };
78
80
  }
79
- function parseJsonObject(raw) {
81
+ function parseJsonValue(raw) {
80
82
  try {
81
- const parsed = JSON.parse(raw);
82
- return isRecord(parsed) ? parsed : undefined;
83
+ return { ok: true, value: JSON.parse(raw) };
83
84
  }
84
85
  catch {
85
- return undefined;
86
+ return { ok: false };
86
87
  }
87
88
  }
88
- function extractNameFromMalformedJson(raw, names) {
89
- for (const name of names) {
90
- if (raw.includes(`"${name}"`))
91
- return name;
92
- }
93
- return undefined;
89
+ function parseJsonObject(raw) {
90
+ const parsed = parseJsonValue(raw);
91
+ return parsed.ok && isRecord(parsed.value) ? parsed.value : undefined;
92
+ }
93
+ function textToolErrorMessage(name, names) {
94
+ if (names.includes(name))
95
+ return undefined;
96
+ return `Unknown tool "${name}". Valid tools: ${names.join(", ")}.`;
97
+ }
98
+ function extractNameFromMalformedJson(raw) {
99
+ const match = /"(?:name|tool)"\s*:\s*"([^"]+)"/.exec(raw);
100
+ return match?.[1];
101
+ }
102
+ function parsePiCallEnvelope(match, names, index) {
103
+ if (!match.name)
104
+ return undefined;
105
+ const parsed = parseJsonValue(match.body);
106
+ const args = parsed.ok ? coerceArguments(parsed.value) : coerceArguments(match.body.trim());
107
+ return {
108
+ type: "toolCall",
109
+ id: `text-tool-${index}`,
110
+ name: match.name,
111
+ arguments: args.arguments,
112
+ rawArguments: parsed.ok ? args.rawArguments : { text: match.body.trim() },
113
+ source: "text-protocol",
114
+ errorMessage: textToolErrorMessage(match.name, names),
115
+ };
94
116
  }
95
117
  function parseEnvelope(match, names, index) {
96
- if (match.kind === "tool") {
97
- if (!match.name || !names.has(match.name))
98
- return undefined;
99
- const parsed = parseJsonObject(match.body);
100
- const args = parsed ? { arguments: parsed } : { arguments: {}, rawArguments: { text: match.body.trim() } };
101
- return {
102
- type: "toolCall",
103
- id: `text-tool-${index}`,
104
- name: match.name,
105
- arguments: args.arguments,
106
- rawArguments: args.rawArguments,
107
- source: "text-protocol",
108
- };
109
- }
118
+ if (match.kind === "pi_call")
119
+ return parsePiCallEnvelope(match, names, index);
110
120
  const parsed = parseJsonObject(match.body);
111
121
  if (!parsed) {
112
- const name = extractNameFromMalformedJson(match.body, names);
122
+ const name = extractNameFromMalformedJson(match.body);
113
123
  if (!name)
114
124
  return undefined;
115
125
  return {
116
126
  type: "toolCall",
117
127
  id: `text-tool-${index}`,
118
128
  name,
119
- arguments: {},
129
+ arguments: match.body.trim(),
120
130
  rawArguments: { text: match.body.trim() },
121
131
  source: "text-protocol",
132
+ errorMessage: textToolErrorMessage(name, names),
122
133
  };
123
134
  }
124
135
  const nameValue = parsed.name ?? parsed.tool;
125
- if (typeof nameValue !== "string" || !names.has(nameValue))
136
+ if (typeof nameValue !== "string")
126
137
  return undefined;
127
138
  const argsValue = parsed.arguments ?? parsed.args ?? {};
128
139
  const args = coerceArguments(argsValue);
@@ -133,6 +144,7 @@ function parseEnvelope(match, names, index) {
133
144
  arguments: args.arguments,
134
145
  rawArguments: args.rawArguments,
135
146
  source: "text-protocol",
147
+ errorMessage: textToolErrorMessage(nameValue, names),
136
148
  };
137
149
  }
138
150
  export function normalizeTextToolProtocolOptions(option) {
@@ -147,7 +159,7 @@ function formatVariantEnvelope(variant, toolName, argsJson) {
147
159
  return `<tool_call>{"name":"${toolName}","arguments":${argsJson}}</tool_call>`;
148
160
  if (variant === "fenced-json")
149
161
  return `\`\`\`tool_call\n{"name":"${toolName}","arguments":${argsJson}}\n\`\`\``;
150
- return `<tool name="${escapeAttribute(toolName)}">${argsJson}</tool>`;
162
+ return `<pi:call name="${escapeAttribute(toolName)}">${argsJson}</pi:call>`;
151
163
  }
152
164
  export function generateTextToolProtocolPrimer(tools, options) {
153
165
  if (tools.length === 0)
@@ -168,17 +180,19 @@ export function generateTextToolProtocolPrimer(tools, options) {
168
180
  }
169
181
  export function parseTextToolCalls(text, knownTools) {
170
182
  if (knownTools.length === 0)
171
- return { calls: [], text };
183
+ return { calls: [], text, attempted: false };
172
184
  const matches = findToolEnvelopes(text);
173
- if (matches.length === 0 || hasOverlap(matches))
174
- return { calls: [], text };
185
+ if (matches.length === 0)
186
+ return { calls: [], text, attempted: false };
187
+ if (hasOverlap(matches))
188
+ return { calls: [], text, attempted: true, failure: "overlap" };
175
189
  const remainder = remainingText(text, matches);
176
- if (remainder === undefined)
177
- return { calls: [], text };
178
- const names = knownToolNames(knownTools);
190
+ const names = [...knownToolNames(knownTools)];
179
191
  const calls = matches
180
192
  .map((match, index) => parseEnvelope(match, names, index + 1))
181
193
  .filter((call) => call !== undefined);
182
- return calls.length > 0 ? { calls, text: remainder.trim() } : { calls: [], text };
194
+ return calls.length > 0
195
+ ? { calls, text: remainder.trim(), attempted: true }
196
+ : { calls: [], text, attempted: true, failure: "unrecognized" };
183
197
  }
184
198
  //# sourceMappingURL=text-protocol.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"text-protocol.js","sourceRoot":"","sources":["../../../src/utils/tool-repair/text-protocol.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Tool, ToolCall } from \"../../types.ts\";\n\nexport interface ParsedTextToolCalls {\n\tcalls: ToolCall[];\n\ttext: string;\n}\n\nexport type TextToolProtocolVariant = \"tool-tag\" | \"tool-call\" | \"fenced-json\";\n\nexport interface TextToolProtocolOptions {\n\tvariant?: TextToolProtocolVariant;\n}\n\ntype EnvelopeKind = \"tool\" | \"tool_call\" | \"fenced_json\";\n\ninterface EnvelopeMatch {\n\tkind: EnvelopeKind;\n\tstart: number;\n\tend: number;\n\tname?: string;\n\tbody: string;\n}\n\nconst MAX_SCHEMA_CHARS = 600;\nconst DEFAULT_TEXT_TOOL_PROTOCOL_VARIANT: TextToolProtocolVariant = \"tool-tag\";\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction compactJson(value: unknown, maxChars = MAX_SCHEMA_CHARS): string {\n\tconst json = JSON.stringify(value);\n\tif (json.length <= maxChars) return json;\n\treturn `${json.slice(0, maxChars - 1)}…`;\n}\n\nfunction escapeAttribute(value: string): string {\n\treturn value.replace(/&/g, \"&amp;\").replace(/\"/g, \"&quot;\").replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\");\n}\n\nfunction unescapeAttribute(value: string): string {\n\treturn value\n\t\t.replace(/&quot;/g, '\"')\n\t\t.replace(/&lt;/g, \"<\")\n\t\t.replace(/&gt;/g, \">\")\n\t\t.replace(/&amp;/g, \"&\");\n}\n\nfunction knownToolNames(tools: readonly Tool[]): Set<string> {\n\treturn new Set(tools.map((tool) => tool.name));\n}\n\nfunction findToolEnvelopes(text: string): EnvelopeMatch[] {\n\tconst matches: EnvelopeMatch[] = [];\n\tconst toolEnvelope = /<tool\\s+name=\"([^\"]+)\">([\\s\\S]*?)<\\/tool>/g;\n\tfor (const match of text.matchAll(toolEnvelope)) {\n\t\tmatches.push({\n\t\t\tkind: \"tool\",\n\t\t\tstart: match.index,\n\t\t\tend: match.index + match[0].length,\n\t\t\tname: unescapeAttribute(match[1] ?? \"\"),\n\t\t\tbody: match[2] ?? \"\",\n\t\t});\n\t}\n\n\tconst toolCallEnvelope = /<tool_call>([\\s\\S]*?)<\\/tool_call>/g;\n\tfor (const match of text.matchAll(toolCallEnvelope)) {\n\t\tmatches.push({\n\t\t\tkind: \"tool_call\",\n\t\t\tstart: match.index,\n\t\t\tend: match.index + match[0].length,\n\t\t\tbody: match[1] ?? \"\",\n\t\t});\n\t}\n\n\tconst trimmed = text.trim();\n\tconst fence = /^```(?:json|tool|tool_call)?\\s*\\n?([\\s\\S]*?)\\n?```$/i.exec(trimmed);\n\tif (fence?.[1]) {\n\t\tconst start = text.indexOf(trimmed);\n\t\tmatches.push({ kind: \"fenced_json\", start, end: start + trimmed.length, body: fence[1] });\n\t}\n\n\treturn matches.sort((a, b) => a.start - b.start);\n}\n\nfunction hasOverlap(matches: readonly EnvelopeMatch[]): boolean {\n\tlet previousEnd = -1;\n\tfor (const match of matches) {\n\t\tif (match.start < previousEnd) return true;\n\t\tpreviousEnd = match.end;\n\t}\n\treturn false;\n}\n\nfunction remainingText(text: string, matches: readonly EnvelopeMatch[]): string | undefined {\n\tlet cursor = 0;\n\tconst pieces: string[] = [];\n\tfor (const match of matches) {\n\t\tpieces.push(text.slice(cursor, match.start));\n\t\tcursor = match.end;\n\t}\n\tpieces.push(text.slice(cursor));\n\tconst remainder = pieces.join(\"\");\n\treturn remainder.trim().length === 0 ? remainder : undefined;\n}\n\nfunction coerceArguments(value: unknown): {\n\targuments: Record<string, unknown>;\n\trawArguments?: Record<string, unknown>;\n} {\n\tif (isRecord(value)) return { arguments: value };\n\treturn { arguments: {}, rawArguments: { value } };\n}\n\nfunction parseJsonObject(raw: string): Record<string, unknown> | undefined {\n\ttry {\n\t\tconst parsed = JSON.parse(raw);\n\t\treturn isRecord(parsed) ? parsed : undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction extractNameFromMalformedJson(raw: string, names: ReadonlySet<string>): string | undefined {\n\tfor (const name of names) {\n\t\tif (raw.includes(`\"${name}\"`)) return name;\n\t}\n\treturn undefined;\n}\n\nfunction parseEnvelope(match: EnvelopeMatch, names: ReadonlySet<string>, index: number): ToolCall | undefined {\n\tif (match.kind === \"tool\") {\n\t\tif (!match.name || !names.has(match.name)) return undefined;\n\t\tconst parsed = parseJsonObject(match.body);\n\t\tconst args = parsed ? { arguments: parsed } : { arguments: {}, rawArguments: { text: match.body.trim() } };\n\t\treturn {\n\t\t\ttype: \"toolCall\",\n\t\t\tid: `text-tool-${index}`,\n\t\t\tname: match.name,\n\t\t\targuments: args.arguments,\n\t\t\trawArguments: args.rawArguments,\n\t\t\tsource: \"text-protocol\",\n\t\t};\n\t}\n\n\tconst parsed = parseJsonObject(match.body);\n\tif (!parsed) {\n\t\tconst name = extractNameFromMalformedJson(match.body, names);\n\t\tif (!name) return undefined;\n\t\treturn {\n\t\t\ttype: \"toolCall\",\n\t\t\tid: `text-tool-${index}`,\n\t\t\tname,\n\t\t\targuments: {},\n\t\t\trawArguments: { text: match.body.trim() },\n\t\t\tsource: \"text-protocol\",\n\t\t};\n\t}\n\n\tconst nameValue = parsed.name ?? parsed.tool;\n\tif (typeof nameValue !== \"string\" || !names.has(nameValue)) return undefined;\n\tconst argsValue = parsed.arguments ?? parsed.args ?? {};\n\tconst args = coerceArguments(argsValue);\n\treturn {\n\t\ttype: \"toolCall\",\n\t\tid: `text-tool-${index}`,\n\t\tname: nameValue,\n\t\targuments: args.arguments,\n\t\trawArguments: args.rawArguments,\n\t\tsource: \"text-protocol\",\n\t};\n}\n\nexport function normalizeTextToolProtocolOptions(\n\toption: boolean | TextToolProtocolOptions | undefined,\n): TextToolProtocolOptions | undefined {\n\tif (!option) return undefined;\n\tif (option === true) return { variant: DEFAULT_TEXT_TOOL_PROTOCOL_VARIANT };\n\treturn { variant: option.variant ?? DEFAULT_TEXT_TOOL_PROTOCOL_VARIANT };\n}\n\nfunction formatVariantEnvelope(variant: TextToolProtocolVariant, toolName: string, argsJson: string): string {\n\tif (variant === \"tool-call\") return `<tool_call>{\"name\":\"${toolName}\",\"arguments\":${argsJson}}</tool_call>`;\n\tif (variant === \"fenced-json\") return `\\`\\`\\`tool_call\\n{\"name\":\"${toolName}\",\"arguments\":${argsJson}}\\n\\`\\`\\``;\n\treturn `<tool name=\"${escapeAttribute(toolName)}\">${argsJson}</tool>`;\n}\n\nexport function generateTextToolProtocolPrimer(tools: readonly Tool[], options?: TextToolProtocolOptions): string {\n\tif (tools.length === 0) return \"\";\n\tconst variant = options?.variant ?? DEFAULT_TEXT_TOOL_PROTOCOL_VARIANT;\n\tconst lines = [\n\t\t\"Text tool-call protocol is enabled.\",\n\t\t\"When calling tools, output only one or more envelopes and no prose:\",\n\t\tformatVariantEnvelope(variant, \"TOOL_NAME\", '{\"argument\":\"value\"}'),\n\t\t\"Available tools:\",\n\t];\n\tfor (const tool of tools) {\n\t\tlines.push(`- ${escapeAttribute(tool.name)}: ${tool.description}; args schema ${compactJson(tool.parameters)}`);\n\t}\n\tconst exampleTool = tools[0];\n\tlines.push(\"Examples:\", formatVariantEnvelope(variant, exampleTool.name, \"{}\"));\n\treturn lines.join(\"\\n\");\n}\n\nexport function parseTextToolCalls(text: string, knownTools: readonly Tool[]): ParsedTextToolCalls {\n\tif (knownTools.length === 0) return { calls: [], text };\n\tconst matches = findToolEnvelopes(text);\n\tif (matches.length === 0 || hasOverlap(matches)) return { calls: [], text };\n\tconst remainder = remainingText(text, matches);\n\tif (remainder === undefined) return { calls: [], text };\n\tconst names = knownToolNames(knownTools);\n\tconst calls = matches\n\t\t.map((match, index) => parseEnvelope(match, names, index + 1))\n\t\t.filter((call): call is ToolCall => call !== undefined);\n\treturn calls.length > 0 ? { calls, text: remainder.trim() } : { calls: [], text };\n}\n"]}
1
+ {"version":3,"file":"text-protocol.js","sourceRoot":"","sources":["../../../src/utils/tool-repair/text-protocol.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Tool, ToolCall } from \"../../types.ts\";\n\nexport type TextToolProtocolParseFailure = \"overlap\" | \"mixed-prose\" | \"unrecognized\";\n\nexport interface ParsedTextToolCalls {\n\tcalls: ToolCall[];\n\ttext: string;\n\tattempted: boolean;\n\tfailure?: TextToolProtocolParseFailure;\n}\n\nexport type TextToolProtocolVariant = \"tool-tag\" | \"tool-call\" | \"fenced-json\";\n\nexport interface TextToolProtocolOptions {\n\tvariant?: TextToolProtocolVariant;\n}\n\ntype EnvelopeKind = \"pi_call\" | \"tool_call\" | \"fenced_json\";\n\ninterface EnvelopeMatch {\n\tkind: EnvelopeKind;\n\tstart: number;\n\tend: number;\n\tname?: string;\n\tbody: string;\n}\n\nconst MAX_SCHEMA_CHARS = 600;\nconst DEFAULT_TEXT_TOOL_PROTOCOL_VARIANT: TextToolProtocolVariant = \"tool-tag\";\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction compactJson(value: unknown, maxChars = MAX_SCHEMA_CHARS): string {\n\tconst json = JSON.stringify(value);\n\tif (json.length <= maxChars) return json;\n\treturn `${json.slice(0, maxChars - 1)}…`;\n}\n\nfunction escapeAttribute(value: string): string {\n\treturn value.replace(/&/g, \"&amp;\").replace(/\"/g, \"&quot;\").replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\");\n}\n\nfunction unescapeAttribute(value: string): string {\n\treturn value\n\t\t.replace(/&quot;/g, '\"')\n\t\t.replace(/&lt;/g, \"<\")\n\t\t.replace(/&gt;/g, \">\")\n\t\t.replace(/&amp;/g, \"&\");\n}\n\nfunction knownToolNames(tools: readonly Tool[]): Set<string> {\n\treturn new Set(tools.map((tool) => tool.name));\n}\n\nfunction findToolEnvelopes(text: string): EnvelopeMatch[] {\n\tconst matches: EnvelopeMatch[] = [];\n\tconst piCallEnvelope = /<pi:call\\s+name=\"([^\"]+)\"\\s*>([\\s\\S]*?)<\\/pi:call>/g;\n\tfor (const match of text.matchAll(piCallEnvelope)) {\n\t\tmatches.push({\n\t\t\tkind: \"pi_call\",\n\t\t\tstart: match.index,\n\t\t\tend: match.index + match[0].length,\n\t\t\tname: unescapeAttribute(match[1] ?? \"\"),\n\t\t\tbody: match[2] ?? \"\",\n\t\t});\n\t}\n\n\tconst toolCallEnvelope = /<tool_call>([\\s\\S]*?)<\\/tool_call>/g;\n\tfor (const match of text.matchAll(toolCallEnvelope)) {\n\t\tmatches.push({\n\t\t\tkind: \"tool_call\",\n\t\t\tstart: match.index,\n\t\t\tend: match.index + match[0].length,\n\t\t\tbody: match[1] ?? \"\",\n\t\t});\n\t}\n\n\tconst fence = /```(?:tool|tool_call)\\s*\\n([\\s\\S]*?)\\n?```/gi;\n\tfor (const match of text.matchAll(fence)) {\n\t\tmatches.push({\n\t\t\tkind: \"fenced_json\",\n\t\t\tstart: match.index,\n\t\t\tend: match.index + match[0].length,\n\t\t\tbody: match[1] ?? \"\",\n\t\t});\n\t}\n\n\treturn matches.sort((a, b) => a.start - b.start);\n}\n\nfunction hasOverlap(matches: readonly EnvelopeMatch[]): boolean {\n\tlet previousEnd = -1;\n\tfor (const match of matches) {\n\t\tif (match.start < previousEnd) return true;\n\t\tpreviousEnd = match.end;\n\t}\n\treturn false;\n}\n\nfunction remainingText(text: string, matches: readonly EnvelopeMatch[]): string {\n\tlet cursor = 0;\n\tconst pieces: string[] = [];\n\tfor (const match of matches) {\n\t\tpieces.push(text.slice(cursor, match.start));\n\t\tcursor = match.end;\n\t}\n\tpieces.push(text.slice(cursor));\n\treturn pieces.join(\"\");\n}\n\nfunction coerceArguments(value: unknown): {\n\targuments: Record<string, unknown>;\n\trawArguments?: Record<string, unknown>;\n} {\n\tif (isRecord(value)) return { arguments: value };\n\treturn { arguments: value as Record<string, unknown>, rawArguments: { value } };\n}\n\nfunction parseJsonValue(raw: string): { ok: true; value: unknown } | { ok: false } {\n\ttry {\n\t\treturn { ok: true, value: JSON.parse(raw) as unknown };\n\t} catch {\n\t\treturn { ok: false };\n\t}\n}\n\nfunction parseJsonObject(raw: string): Record<string, unknown> | undefined {\n\tconst parsed = parseJsonValue(raw);\n\treturn parsed.ok && isRecord(parsed.value) ? parsed.value : undefined;\n}\n\nfunction textToolErrorMessage(name: string, names: readonly string[]): string | undefined {\n\tif (names.includes(name)) return undefined;\n\treturn `Unknown tool \"${name}\". Valid tools: ${names.join(\", \")}.`;\n}\n\nfunction extractNameFromMalformedJson(raw: string): string | undefined {\n\tconst match = /\"(?:name|tool)\"\\s*:\\s*\"([^\"]+)\"/.exec(raw);\n\treturn match?.[1];\n}\n\nfunction parsePiCallEnvelope(match: EnvelopeMatch, names: readonly string[], index: number): ToolCall | undefined {\n\tif (!match.name) return undefined;\n\tconst parsed = parseJsonValue(match.body);\n\tconst args = parsed.ok ? coerceArguments(parsed.value) : coerceArguments(match.body.trim());\n\treturn {\n\t\ttype: \"toolCall\",\n\t\tid: `text-tool-${index}`,\n\t\tname: match.name,\n\t\targuments: args.arguments,\n\t\trawArguments: parsed.ok ? args.rawArguments : { text: match.body.trim() },\n\t\tsource: \"text-protocol\",\n\t\terrorMessage: textToolErrorMessage(match.name, names),\n\t};\n}\n\nfunction parseEnvelope(match: EnvelopeMatch, names: readonly string[], index: number): ToolCall | undefined {\n\tif (match.kind === \"pi_call\") return parsePiCallEnvelope(match, names, index);\n\n\tconst parsed = parseJsonObject(match.body);\n\tif (!parsed) {\n\t\tconst name = extractNameFromMalformedJson(match.body);\n\t\tif (!name) return undefined;\n\t\treturn {\n\t\t\ttype: \"toolCall\",\n\t\t\tid: `text-tool-${index}`,\n\t\t\tname,\n\t\t\targuments: match.body.trim() as unknown as Record<string, unknown>,\n\t\t\trawArguments: { text: match.body.trim() },\n\t\t\tsource: \"text-protocol\",\n\t\t\terrorMessage: textToolErrorMessage(name, names),\n\t\t};\n\t}\n\n\tconst nameValue = parsed.name ?? parsed.tool;\n\tif (typeof nameValue !== \"string\") return undefined;\n\tconst argsValue = parsed.arguments ?? parsed.args ?? {};\n\tconst args = coerceArguments(argsValue);\n\treturn {\n\t\ttype: \"toolCall\",\n\t\tid: `text-tool-${index}`,\n\t\tname: nameValue,\n\t\targuments: args.arguments,\n\t\trawArguments: args.rawArguments,\n\t\tsource: \"text-protocol\",\n\t\terrorMessage: textToolErrorMessage(nameValue, names),\n\t};\n}\n\nexport function normalizeTextToolProtocolOptions(\n\toption: boolean | TextToolProtocolOptions | undefined,\n): TextToolProtocolOptions | undefined {\n\tif (!option) return undefined;\n\tif (option === true) return { variant: DEFAULT_TEXT_TOOL_PROTOCOL_VARIANT };\n\treturn { variant: option.variant ?? DEFAULT_TEXT_TOOL_PROTOCOL_VARIANT };\n}\n\nfunction formatVariantEnvelope(variant: TextToolProtocolVariant, toolName: string, argsJson: string): string {\n\tif (variant === \"tool-call\") return `<tool_call>{\"name\":\"${toolName}\",\"arguments\":${argsJson}}</tool_call>`;\n\tif (variant === \"fenced-json\") return `\\`\\`\\`tool_call\\n{\"name\":\"${toolName}\",\"arguments\":${argsJson}}\\n\\`\\`\\``;\n\treturn `<pi:call name=\"${escapeAttribute(toolName)}\">${argsJson}</pi:call>`;\n}\n\nexport function generateTextToolProtocolPrimer(tools: readonly Tool[], options?: TextToolProtocolOptions): string {\n\tif (tools.length === 0) return \"\";\n\tconst variant = options?.variant ?? DEFAULT_TEXT_TOOL_PROTOCOL_VARIANT;\n\tconst lines = [\n\t\t\"Text tool-call protocol is enabled.\",\n\t\t\"When calling tools, output only one or more envelopes and no prose:\",\n\t\tformatVariantEnvelope(variant, \"TOOL_NAME\", '{\"argument\":\"value\"}'),\n\t\t\"Available tools:\",\n\t];\n\tfor (const tool of tools) {\n\t\tlines.push(`- ${escapeAttribute(tool.name)}: ${tool.description}; args schema ${compactJson(tool.parameters)}`);\n\t}\n\tconst exampleTool = tools[0];\n\tlines.push(\"Examples:\", formatVariantEnvelope(variant, exampleTool.name, \"{}\"));\n\treturn lines.join(\"\\n\");\n}\n\nexport function parseTextToolCalls(text: string, knownTools: readonly Tool[]): ParsedTextToolCalls {\n\tif (knownTools.length === 0) return { calls: [], text, attempted: false };\n\tconst matches = findToolEnvelopes(text);\n\tif (matches.length === 0) return { calls: [], text, attempted: false };\n\tif (hasOverlap(matches)) return { calls: [], text, attempted: true, failure: \"overlap\" };\n\tconst remainder = remainingText(text, matches);\n\tconst names = [...knownToolNames(knownTools)];\n\tconst calls = matches\n\t\t.map((match, index) => parseEnvelope(match, names, index + 1))\n\t\t.filter((call): call is ToolCall => call !== undefined);\n\treturn calls.length > 0\n\t\t? { calls, text: remainder.trim(), attempted: true }\n\t\t: { calls: [], text, attempted: true, failure: \"unrecognized\" };\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@caupulican/pi-ai",
3
- "version": "0.81.12",
3
+ "version": "0.81.13",
4
4
  "description": "Unified LLM API with automatic model discovery and provider configuration",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",