@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.
- package/dist/models.generated.d.ts +17 -0
- package/dist/models.generated.d.ts.map +1 -1
- package/dist/models.generated.js +21 -4
- package/dist/models.generated.js.map +1 -1
- package/dist/stream.d.ts.map +1 -1
- package/dist/stream.js +34 -5
- package/dist/stream.js.map +1 -1
- package/dist/types.d.ts +12 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utils/tool-repair/repairer.d.ts.map +1 -1
- package/dist/utils/tool-repair/repairer.js +12 -7
- package/dist/utils/tool-repair/repairer.js.map +1 -1
- package/dist/utils/tool-repair/text-protocol.d.ts +3 -0
- package/dist/utils/tool-repair/text-protocol.d.ts.map +1 -1
- package/dist/utils/tool-repair/text-protocol.js +60 -46
- package/dist/utils/tool-repair/text-protocol.js.map +1 -1
- package/package.json +1 -1
|
@@ -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
|
|
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
|
|
208
|
+
return undefined;
|
|
209
209
|
if (!schemaChecks(issue.schema, transform.value))
|
|
210
|
-
return
|
|
211
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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;
|
|
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, \"&\").replace(/\"/g, \""\").replace(/</g, \"<\").replace(/>/g, \">\");\n}\n\nfunction unescapeAttribute(value: string): string {\n\treturn value\n\t\t.replace(/"/g, '\"')\n\t\t.replace(/</g, \"<\")\n\t\t.replace(/>/g, \">\")\n\t\t.replace(/&/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
|
|
28
|
-
for (const match of text.matchAll(
|
|
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: "
|
|
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
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
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
|
-
|
|
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:
|
|
79
|
+
return { arguments: value, rawArguments: { value } };
|
|
78
80
|
}
|
|
79
|
-
function
|
|
81
|
+
function parseJsonValue(raw) {
|
|
80
82
|
try {
|
|
81
|
-
|
|
82
|
-
return isRecord(parsed) ? parsed : undefined;
|
|
83
|
+
return { ok: true, value: JSON.parse(raw) };
|
|
83
84
|
}
|
|
84
85
|
catch {
|
|
85
|
-
return
|
|
86
|
+
return { ok: false };
|
|
86
87
|
}
|
|
87
88
|
}
|
|
88
|
-
function
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
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 === "
|
|
97
|
-
|
|
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
|
|
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"
|
|
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 `<
|
|
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
|
|
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
|
-
|
|
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
|
|
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, \"&\").replace(/\"/g, \""\").replace(/</g, \"<\").replace(/>/g, \">\");\n}\n\nfunction unescapeAttribute(value: string): string {\n\treturn value\n\t\t.replace(/"/g, '\"')\n\t\t.replace(/</g, \"<\")\n\t\t.replace(/>/g, \">\")\n\t\t.replace(/&/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, \"&\").replace(/\"/g, \""\").replace(/</g, \"<\").replace(/>/g, \">\");\n}\n\nfunction unescapeAttribute(value: string): string {\n\treturn value\n\t\t.replace(/"/g, '\"')\n\t\t.replace(/</g, \"<\")\n\t\t.replace(/>/g, \">\")\n\t\t.replace(/&/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"]}
|