@gaunt-sloth/core 2.0.0-alpha.9 → 2.0.0-beta.0
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/.gsloth.review.md +2 -0
- package/README.md +71 -20
- package/dist/config/colour.d.ts +38 -0
- package/dist/config/colour.js +36 -0
- package/dist/config/colour.js.map +1 -0
- package/dist/config/configDiscovery.d.ts +79 -0
- package/dist/config/configDiscovery.js +80 -0
- package/dist/config/configDiscovery.js.map +1 -0
- package/dist/config/defaults.d.ts +20 -20
- package/dist/config/defaults.js +10 -8
- package/dist/config/defaults.js.map +1 -1
- package/dist/config/filesystem-tools.d.ts +41 -0
- package/dist/config/filesystem-tools.js +56 -0
- package/dist/config/filesystem-tools.js.map +1 -0
- package/dist/config/loader.d.ts +171 -19
- package/dist/config/loader.js +1054 -144
- package/dist/config/loader.js.map +1 -1
- package/dist/config/mouse.d.ts +50 -0
- package/dist/config/mouse.js +44 -0
- package/dist/config/mouse.js.map +1 -0
- package/dist/config/profiles.d.ts +68 -0
- package/dist/config/profiles.js +93 -0
- package/dist/config/profiles.js.map +1 -0
- package/dist/config/providerKeys.d.ts +69 -0
- package/dist/config/providerKeys.js +69 -0
- package/dist/config/providerKeys.js.map +1 -0
- package/dist/config/schema.d.ts +2671 -138
- package/dist/config/schema.js +1361 -85
- package/dist/config/schema.js.map +1 -1
- package/dist/config/shell-policy.d.ts +899 -111
- package/dist/config/shell-policy.js +800 -70
- package/dist/config/shell-policy.js.map +1 -1
- package/dist/config/tool-descriptions.d.ts +211 -0
- package/dist/config/tool-descriptions.js +272 -0
- package/dist/config/tool-descriptions.js.map +1 -0
- package/dist/config/types.d.ts +352 -41
- package/dist/config/types.js +1 -0
- package/dist/config/types.js.map +1 -1
- package/dist/config.d.ts +35 -1
- package/dist/config.js +16 -1
- package/dist/config.js.map +1 -1
- package/dist/constants.d.ts +28 -1
- package/dist/constants.js +28 -1
- package/dist/constants.js.map +1 -1
- package/dist/core/GthAbstractAgent.d.ts +166 -11
- package/dist/core/GthAbstractAgent.js +484 -45
- package/dist/core/GthAbstractAgent.js.map +1 -1
- package/dist/core/GthAgentRunner.d.ts +543 -57
- package/dist/core/GthAgentRunner.js +1494 -140
- package/dist/core/GthAgentRunner.js.map +1 -1
- package/dist/core/GthLangChainAgent.d.ts +117 -2
- package/dist/core/GthLangChainAgent.js +602 -29
- package/dist/core/GthLangChainAgent.js.map +1 -1
- package/dist/core/approvals/annotations.d.ts +122 -0
- package/dist/core/approvals/annotations.js +137 -0
- package/dist/core/approvals/annotations.js.map +1 -0
- package/dist/core/approvals/grants.d.ts +216 -0
- package/dist/core/approvals/grants.js +469 -0
- package/dist/core/approvals/grants.js.map +1 -0
- package/dist/core/approvals/matcher.d.ts +202 -0
- package/dist/core/approvals/matcher.js +267 -0
- package/dist/core/approvals/matcher.js.map +1 -0
- package/dist/core/approvals/mcpSubjects.d.ts +40 -0
- package/dist/core/approvals/mcpSubjects.js +99 -0
- package/dist/core/approvals/mcpSubjects.js.map +1 -0
- package/dist/core/approvals/promptHeader.d.ts +28 -0
- package/dist/core/approvals/promptHeader.js +62 -0
- package/dist/core/approvals/promptHeader.js.map +1 -0
- package/dist/core/approvals/toolAnnotationSources.d.ts +105 -0
- package/dist/core/approvals/toolAnnotationSources.js +277 -0
- package/dist/core/approvals/toolAnnotationSources.js.map +1 -0
- package/dist/core/approvals/toolHost.d.ts +46 -0
- package/dist/core/approvals/toolHost.js +108 -0
- package/dist/core/approvals/toolHost.js.map +1 -0
- package/dist/core/debugCapture.d.ts +74 -0
- package/dist/core/debugCapture.js +100 -0
- package/dist/core/debugCapture.js.map +1 -0
- package/dist/core/gthLeanAgentFactory.d.ts +4 -4
- package/dist/core/gthLeanAgentFactory.js +4 -4
- package/dist/core/launchBanner.d.ts +127 -0
- package/dist/core/launchBanner.js +414 -0
- package/dist/core/launchBanner.js.map +1 -0
- package/dist/core/modelLabel.d.ts +19 -0
- package/dist/core/modelLabel.js +26 -0
- package/dist/core/modelLabel.js.map +1 -0
- package/dist/core/plainToolIndication.d.ts +15 -0
- package/dist/core/plainToolIndication.js +174 -0
- package/dist/core/plainToolIndication.js.map +1 -0
- package/dist/core/reasoningBlocks.d.ts +65 -0
- package/dist/core/reasoningBlocks.js +103 -0
- package/dist/core/reasoningBlocks.js.map +1 -0
- package/dist/core/refusal.d.ts +53 -0
- package/dist/core/refusal.js +133 -0
- package/dist/core/refusal.js.map +1 -0
- package/dist/core/runHeader.d.ts +38 -0
- package/dist/core/runHeader.js +42 -0
- package/dist/core/runHeader.js.map +1 -0
- package/dist/core/runStats.d.ts +14 -3
- package/dist/core/runStats.js +48 -3
- package/dist/core/runStats.js.map +1 -1
- package/dist/core/shell/ShellCommandFailedError.d.ts +3 -4
- package/dist/core/shell/ShellCommandFailedError.js +3 -4
- package/dist/core/shell/ShellCommandFailedError.js.map +1 -1
- package/dist/core/shell/abstention.d.ts +88 -0
- package/dist/core/shell/abstention.js +184 -0
- package/dist/core/shell/abstention.js.map +1 -0
- package/dist/core/shell/approvalCapture.d.ts +271 -0
- package/dist/core/shell/approvalCapture.js +108 -0
- package/dist/core/shell/approvalCapture.js.map +1 -0
- package/dist/core/shell/approvalStop.d.ts +123 -0
- package/dist/core/shell/approvalStop.js +269 -0
- package/dist/core/shell/approvalStop.js.map +1 -0
- package/dist/core/shell/arity.d.ts +6 -0
- package/dist/core/shell/arity.js +20 -6
- package/dist/core/shell/arity.js.map +1 -1
- package/dist/core/shell/denylist.d.ts +11 -0
- package/dist/core/shell/denylist.js +37 -0
- package/dist/core/shell/denylist.js.map +1 -0
- package/dist/core/shell/escalationSeverity.d.ts +141 -0
- package/dist/core/shell/escalationSeverity.js +89 -0
- package/dist/core/shell/escalationSeverity.js.map +1 -0
- package/dist/core/shell/framing.d.ts +190 -0
- package/dist/core/shell/framing.js +633 -0
- package/dist/core/shell/framing.js.map +1 -0
- package/dist/core/shell/hardline.d.ts +103 -0
- package/dist/core/shell/hardline.js +780 -0
- package/dist/core/shell/hardline.js.map +1 -0
- package/dist/core/shell/negotiation.d.ts +328 -0
- package/dist/core/shell/negotiation.js +488 -0
- package/dist/core/shell/negotiation.js.map +1 -0
- package/dist/core/shell/normalize.d.ts +44 -4
- package/dist/core/shell/normalize.js +61 -7
- package/dist/core/shell/normalize.js.map +1 -1
- package/dist/core/shell/openWorld.d.ts +263 -0
- package/dist/core/shell/openWorld.js +1188 -0
- package/dist/core/shell/openWorld.js.map +1 -0
- package/dist/core/shell/rater.d.ts +873 -0
- package/dist/core/shell/rater.js +1454 -0
- package/dist/core/shell/rater.js.map +1 -0
- package/dist/core/shell/raterModel.d.ts +41 -0
- package/dist/core/shell/raterModel.js +51 -0
- package/dist/core/shell/raterModel.js.map +1 -0
- package/dist/core/shell/raterVocabulary.d.ts +121 -0
- package/dist/core/shell/raterVocabulary.js +116 -0
- package/dist/core/shell/raterVocabulary.js.map +1 -0
- package/dist/core/shell/rejection.d.ts +69 -0
- package/dist/core/shell/rejection.js +38 -0
- package/dist/core/shell/rejection.js.map +1 -0
- package/dist/core/toolCallRepair/grammar.d.ts +41 -0
- package/dist/core/toolCallRepair/grammar.js +116 -0
- package/dist/core/toolCallRepair/grammar.js.map +1 -0
- package/dist/core/toolCallRepair/index.d.ts +2 -0
- package/dist/core/toolCallRepair/index.js +7 -0
- package/dist/core/toolCallRepair/index.js.map +1 -0
- package/dist/core/toolCallRepair/payload.d.ts +36 -0
- package/dist/core/toolCallRepair/payload.js +341 -0
- package/dist/core/toolCallRepair/payload.js.map +1 -0
- package/dist/core/toolCallRepair/promote.d.ts +45 -0
- package/dist/core/toolCallRepair/promote.js +90 -0
- package/dist/core/toolCallRepair/promote.js.map +1 -0
- package/dist/core/toolDisplay.d.ts +123 -0
- package/dist/core/toolDisplay.js +451 -0
- package/dist/core/toolDisplay.js.map +1 -0
- package/dist/core/toolOutputChannel.d.ts +95 -0
- package/dist/core/toolOutputChannel.js +165 -0
- package/dist/core/toolOutputChannel.js.map +1 -0
- package/dist/core/types.d.ts +349 -16
- package/dist/core/types.js.map +1 -1
- package/dist/history/historyFormat.d.ts +12 -3
- package/dist/history/historyFormat.js +50 -8
- package/dist/history/historyFormat.js.map +1 -1
- package/dist/history/historyStore.d.ts +77 -0
- package/dist/history/historyStore.js +173 -6
- package/dist/history/historyStore.js.map +1 -1
- package/dist/history/recordSession.d.ts +10 -1
- package/dist/history/recordSession.js +27 -0
- package/dist/history/recordSession.js.map +1 -1
- package/dist/providers/anthropic.js +12 -0
- package/dist/providers/anthropic.js.map +1 -1
- package/dist/providers/configurationPassthrough.d.ts +107 -0
- package/dist/providers/configurationPassthrough.js +148 -0
- package/dist/providers/configurationPassthrough.js.map +1 -0
- package/dist/providers/geminiSchemaSanitizer.d.ts +55 -0
- package/dist/providers/geminiSchemaSanitizer.js +347 -0
- package/dist/providers/geminiSchemaSanitizer.js.map +1 -0
- package/dist/providers/geminiThinking.d.ts +60 -0
- package/dist/providers/geminiThinking.js +92 -0
- package/dist/providers/geminiThinking.js.map +1 -0
- package/dist/providers/google-genai.js +18 -1
- package/dist/providers/google-genai.js.map +1 -1
- package/dist/providers/groq.js +12 -0
- package/dist/providers/groq.js.map +1 -1
- package/dist/providers/huggingface.d.ts +25 -0
- package/dist/providers/huggingface.js +69 -0
- package/dist/providers/huggingface.js.map +1 -0
- package/dist/providers/modelCatalog.d.ts +109 -0
- package/dist/providers/modelCatalog.js +245 -0
- package/dist/providers/modelCatalog.js.map +1 -0
- package/dist/providers/modelDiscovery.d.ts +99 -5
- package/dist/providers/modelDiscovery.js +191 -35
- package/dist/providers/modelDiscovery.js.map +1 -1
- package/dist/providers/ollama.d.ts +18 -4
- package/dist/providers/ollama.js +67 -37
- package/dist/providers/ollama.js.map +1 -1
- package/dist/providers/openai.js +34 -0
- package/dist/providers/openai.js.map +1 -1
- package/dist/providers/openrouter.d.ts +26 -4
- package/dist/providers/openrouter.js +83 -26
- package/dist/providers/openrouter.js.map +1 -1
- package/dist/providers/vertexai.js +19 -1
- package/dist/providers/vertexai.js.map +1 -1
- package/dist/providers/xai.js +20 -0
- package/dist/providers/xai.js.map +1 -1
- package/dist/runtime/askStructured.d.ts +105 -0
- package/dist/runtime/askStructured.js +120 -0
- package/dist/runtime/askStructured.js.map +1 -0
- package/dist/runtime/conversation.d.ts +64 -0
- package/dist/runtime/conversation.js +171 -0
- package/dist/runtime/conversation.js.map +1 -0
- package/dist/runtime/singleShot.d.ts +37 -6
- package/dist/runtime/singleShot.js +113 -67
- package/dist/runtime/singleShot.js.map +1 -1
- package/dist/runtime/structuredOutput.d.ts +104 -0
- package/dist/runtime/structuredOutput.js +393 -0
- package/dist/runtime/structuredOutput.js.map +1 -0
- package/dist/utils/ProgressIndicator.d.ts +21 -0
- package/dist/utils/ProgressIndicator.js +30 -3
- package/dist/utils/ProgressIndicator.js.map +1 -1
- package/dist/utils/aiignoreUtils.js.map +1 -1
- package/dist/utils/binaryOutputUtils.js.map +1 -1
- package/dist/utils/consoleUtils.d.ts +95 -0
- package/dist/utils/consoleUtils.js +112 -2
- package/dist/utils/consoleUtils.js.map +1 -1
- package/dist/utils/crashHandler.d.ts +87 -0
- package/dist/utils/crashHandler.js +128 -0
- package/dist/utils/crashHandler.js.map +1 -0
- package/dist/utils/debugDump.d.ts +134 -0
- package/dist/utils/debugDump.js +381 -0
- package/dist/utils/debugDump.js.map +1 -0
- package/dist/utils/debugUtils.d.ts +13 -4
- package/dist/utils/debugUtils.js +36 -13
- package/dist/utils/debugUtils.js.map +1 -1
- package/dist/utils/displayWidth.d.ts +53 -0
- package/dist/utils/displayWidth.js +195 -0
- package/dist/utils/displayWidth.js.map +1 -0
- package/dist/utils/fileUtils.js.map +1 -1
- package/dist/utils/globalConfigUtils.d.ts +14 -2
- package/dist/utils/globalConfigUtils.js +22 -4
- package/dist/utils/globalConfigUtils.js.map +1 -1
- package/dist/utils/llmUtils.d.ts +39 -8
- package/dist/utils/llmUtils.js +76 -8
- package/dist/utils/llmUtils.js.map +1 -1
- package/dist/utils/redactSecrets.d.ts +63 -0
- package/dist/utils/redactSecrets.js +286 -0
- package/dist/utils/redactSecrets.js.map +1 -0
- package/dist/utils/systemPromptNotes.d.ts +222 -0
- package/dist/utils/systemPromptNotes.js +338 -0
- package/dist/utils/systemPromptNotes.js.map +1 -0
- package/dist/utils/systemUtils.d.ts +18 -1
- package/dist/utils/systemUtils.js +38 -3
- package/dist/utils/systemUtils.js.map +1 -1
- package/dist/utils/toolMatching.d.ts +30 -0
- package/dist/utils/toolMatching.js +44 -0
- package/dist/utils/toolMatching.js.map +1 -0
- package/dist/utils/untrustedText.d.ts +86 -0
- package/dist/utils/untrustedText.js +101 -0
- package/dist/utils/untrustedText.js.map +1 -0
- package/package.json +21 -7
- package/schema/gsloth-config.schema.json +1921 -326
- package/dist/core/shell/allowlist.d.ts +0 -75
- package/dist/core/shell/allowlist.js +0 -187
- package/dist/core/shell/allowlist.js.map +0 -1
- package/dist/core/shell/judge.d.ts +0 -161
- package/dist/core/shell/judge.js +0 -261
- package/dist/core/shell/judge.js.map +0 -1
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
// EXT-35 — plain-text tool-call repair grammar.
|
|
2
|
+
//
|
|
3
|
+
// Ported (TypeScript, gaunt-sloth house style) from the openclaw
|
|
4
|
+
// `@openclaw/tool-call-repair` reference (`packages/tool-call-repair/src/grammar.ts`).
|
|
5
|
+
// Only the low-level scanners the standalone-block parser in `./payload.ts` needs are
|
|
6
|
+
// carried over; the reference's streaming/normalizer/strip helpers are intentionally omitted.
|
|
7
|
+
//
|
|
8
|
+
// These functions recognise the fixed protocol markers small/local models emit when they
|
|
9
|
+
// serialise a tool call as assistant TEXT instead of a native tool_call. They do no allow-list
|
|
10
|
+
// or size gating themselves — that lives in `./payload.ts` / `./promote.ts`.
|
|
11
|
+
/** Legacy marker some models emit after a serialized JSON tool request. */
|
|
12
|
+
export const END_TOOL_REQUEST = '[END_TOOL_REQUEST]';
|
|
13
|
+
/** Harmony stream marker that introduces the target channel before a tool call. */
|
|
14
|
+
export const HARMONY_CHANNEL_MARKER = '<|channel|>';
|
|
15
|
+
/** Harmony stream marker that may separate the header from the JSON payload. */
|
|
16
|
+
export const HARMONY_MESSAGE_MARKER = '<|message|>';
|
|
17
|
+
/** Harmony stream marker that may close a serialized tool-call payload. */
|
|
18
|
+
export const HARMONY_CALL_MARKER = '<|call|>';
|
|
19
|
+
/**
|
|
20
|
+
* Harmony marker real gpt-oss emits in place of the reference grammar's literal `code` token —
|
|
21
|
+
* e.g. `<|constrain|>json` declares the tool-call payload format. (EXT-43.)
|
|
22
|
+
*/
|
|
23
|
+
export const HARMONY_CONSTRAIN_MARKER = '<|constrain|>';
|
|
24
|
+
/** Tool names in bracket/plain-text repairs intentionally match provider-safe ids only. */
|
|
25
|
+
export function isPlainTextToolNameChar(char) {
|
|
26
|
+
return Boolean(char && /[A-Za-z0-9_-]/.test(char));
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Harmony tool names may be NAMESPACED with dots (real gpt-oss emits `to=functions.get_weather`),
|
|
30
|
+
* so the Harmony header scanner accepts `.` on top of the provider-safe id chars. This is a
|
|
31
|
+
* Harmony-only widening (EXT-43): the bracket/XML-ish dialects keep {@link isPlainTextToolNameChar}
|
|
32
|
+
* unchanged so their prose-safety is untouched. The final dot-segment is the tool name matched
|
|
33
|
+
* against the allow-list (see {@link finalDotSegment}).
|
|
34
|
+
*/
|
|
35
|
+
export function isHarmonyToolNameChar(char) {
|
|
36
|
+
return Boolean(char && /[A-Za-z0-9_.-]/.test(char));
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* The tool name for a (possibly namespaced) Harmony target: the final dot-segment.
|
|
40
|
+
* `functions.get_weather` → `get_weather`; `functions.tools.get_weather` → `get_weather`; a dotless
|
|
41
|
+
* `get_weather` → itself. Returns `''` for a trailing-dot / empty final segment (rejected upstream).
|
|
42
|
+
*/
|
|
43
|
+
export function finalDotSegment(name) {
|
|
44
|
+
const lastDot = name.lastIndexOf('.');
|
|
45
|
+
return lastDot === -1 ? name : name.slice(lastDot + 1);
|
|
46
|
+
}
|
|
47
|
+
/** Skips spaces and tabs only, preserving line boundaries for grammar decisions. */
|
|
48
|
+
export function skipHorizontalWhitespace(text, start) {
|
|
49
|
+
let index = start;
|
|
50
|
+
while (index < text.length && (text[index] === ' ' || text[index] === '\t')) {
|
|
51
|
+
index += 1;
|
|
52
|
+
}
|
|
53
|
+
return index;
|
|
54
|
+
}
|
|
55
|
+
/** Skips all JavaScript whitespace when line structure is no longer meaningful. */
|
|
56
|
+
export function skipWhitespace(text, start) {
|
|
57
|
+
let index = start;
|
|
58
|
+
while (index < text.length && /\s/.test(text[index] ?? '')) {
|
|
59
|
+
index += 1;
|
|
60
|
+
}
|
|
61
|
+
return index;
|
|
62
|
+
}
|
|
63
|
+
/** Consumes either Unix or Windows line endings and returns the first offset after them. */
|
|
64
|
+
export function consumeLineBreak(text, start) {
|
|
65
|
+
if (text[start] === '\r') {
|
|
66
|
+
return text[start + 1] === '\n' ? start + 2 : start + 1;
|
|
67
|
+
}
|
|
68
|
+
if (text[start] === '\n') {
|
|
69
|
+
return start + 1;
|
|
70
|
+
}
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Finds the exclusive end offset of a balanced JSON object starting at `start`. Returns null if
|
|
75
|
+
* the object never closes, or (when `maxPayloadBytes` is set) as soon as the scan runs past the
|
|
76
|
+
* cap — the payload-size gate that keeps a runaway blob from being treated as a tool call.
|
|
77
|
+
*/
|
|
78
|
+
export function findJsonObjectEnd(text, start, maxPayloadBytes) {
|
|
79
|
+
let depth = 0;
|
|
80
|
+
let inString = false;
|
|
81
|
+
let escaped = false;
|
|
82
|
+
for (let index = start; index < text.length; index += 1) {
|
|
83
|
+
if (maxPayloadBytes !== undefined && index + 1 - start > maxPayloadBytes) {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
const char = text[index];
|
|
87
|
+
if (inString) {
|
|
88
|
+
if (escaped) {
|
|
89
|
+
escaped = false;
|
|
90
|
+
}
|
|
91
|
+
else if (char === '\\') {
|
|
92
|
+
escaped = true;
|
|
93
|
+
}
|
|
94
|
+
else if (char === '"') {
|
|
95
|
+
inString = false;
|
|
96
|
+
}
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
if (char === '"') {
|
|
100
|
+
inString = true;
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
if (char === '{') {
|
|
104
|
+
depth += 1;
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
if (char === '}') {
|
|
108
|
+
depth -= 1;
|
|
109
|
+
if (depth === 0) {
|
|
110
|
+
return index + 1;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=grammar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grammar.js","sourceRoot":"","sources":["../../../src/core/toolCallRepair/grammar.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export { parseStandalonePlainTextToolCallBlocks, type PlainTextToolCallBlock, type PlainTextToolCallParseOptions, } from './payload.js';
|
|
2
|
+
export { textToNativeToolCalls, promoteTextEmittedToolCallMessage, MAX_TEXT_EMITTED_TOOL_CALL_PAYLOAD_BYTES, type TextToolCallRepairOptions, } from './promote.js';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// EXT-35 — plain-text tool-call repair: promote a text-emitted tool call to a native tool_call.
|
|
2
|
+
// Ported/adapted from the openclaw `@openclaw/tool-call-repair` reference. See the sibling files
|
|
3
|
+
// for the per-dialect grammar (`grammar.ts`), the standalone-block parser (`payload.ts`), and the
|
|
4
|
+
// LangChain-message promotion + gates (`promote.ts`).
|
|
5
|
+
export { parseStandalonePlainTextToolCallBlocks, } from './payload.js';
|
|
6
|
+
export { textToNativeToolCalls, promoteTextEmittedToolCallMessage, MAX_TEXT_EMITTED_TOOL_CALL_PAYLOAD_BYTES, } from './promote.js';
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/toolCallRepair/index.ts"],"names":[],"mappings":"AAAA,gGAAgG;AAChG,iGAAiG;AACjG,kGAAkG;AAClG,sDAAsD;AACtD,OAAO,EACL,sCAAsC,GAGvC,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,qBAAqB,EACrB,iCAAiC,EACjC,wCAAwC,GAEzC,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/** Parsed standalone plain-text tool call block with source offsets for repair. */
|
|
2
|
+
export type PlainTextToolCallBlock = {
|
|
3
|
+
/** Parsed JSON arguments object. */
|
|
4
|
+
arguments: Record<string, unknown>;
|
|
5
|
+
/** Exclusive end offset of the parsed block. */
|
|
6
|
+
end: number;
|
|
7
|
+
/** Tool name parsed from bracket, Harmony, or XML-ish syntax. */
|
|
8
|
+
name: string;
|
|
9
|
+
/** Original text slice that produced this block. */
|
|
10
|
+
raw: string;
|
|
11
|
+
/** Inclusive start offset of the parsed block. */
|
|
12
|
+
start: number;
|
|
13
|
+
};
|
|
14
|
+
/** Parser limits and allow-list options for plain-text tool-call repair. */
|
|
15
|
+
export type PlainTextToolCallParseOptions = {
|
|
16
|
+
/** Optional allow-list of tool names that may be repaired. */
|
|
17
|
+
allowedToolNames?: Iterable<string>;
|
|
18
|
+
/** Maximum serialized payload size accepted for one repaired call. */
|
|
19
|
+
maxPayloadBytes?: number;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* The single source of truth for the plain-text tool-call payload cap (256 KB). A serialized call
|
|
23
|
+
* larger than this is never treated as a tool call. Re-exported from `./promote.js` (and the module
|
|
24
|
+
* index) as `MAX_TEXT_EMITTED_TOOL_CALL_PAYLOAD_BYTES` — the public name — so there is ONE constant,
|
|
25
|
+
* not two duplicated literals. (EXT-43 unified the former `DEFAULT_MAX_PLAIN_TEXT_TOOL_PAYLOAD_BYTES`
|
|
26
|
+
* here with `promote.ts`'s copy.)
|
|
27
|
+
*/
|
|
28
|
+
export declare const MAX_TEXT_EMITTED_TOOL_CALL_PAYLOAD_BYTES = 256000;
|
|
29
|
+
/**
|
|
30
|
+
* Parse the WHOLE input into standalone plain-text tool-call blocks, or return null if any part of
|
|
31
|
+
* it is not such a block. This all-or-nothing walk is the standalone-only gate: prose that merely
|
|
32
|
+
* mentions a tool name, contains brackets, or embeds a call inside a sentence never parses (the
|
|
33
|
+
* first non-block character aborts the parse). Allow-list + payload-cap gating are applied per
|
|
34
|
+
* block via {@link PlainTextToolCallParseOptions}.
|
|
35
|
+
*/
|
|
36
|
+
export declare function parseStandalonePlainTextToolCallBlocks(text: string, options?: PlainTextToolCallParseOptions): PlainTextToolCallBlock[] | null;
|
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
// EXT-35 — plain-text tool-call repair payload parser.
|
|
2
|
+
//
|
|
3
|
+
// Ported (TypeScript, gaunt-sloth house style) from the openclaw
|
|
4
|
+
// `@openclaw/tool-call-repair` reference (`packages/tool-call-repair/src/payload.ts`).
|
|
5
|
+
// Carries the three text-emitted tool-call dialects small/local models produce:
|
|
6
|
+
// • bracket: `[tool:name]{...json...}` / `[name]\n{...json...}[/name]`
|
|
7
|
+
// • XML-ish: `<function=name><parameter=key>value</parameter></function>`
|
|
8
|
+
// • Harmony: `<|channel|>commentary to=name code<|message|>{...json...}<|call|>`
|
|
9
|
+
// — plus the real gpt-oss variant (EXT-43) with a NAMESPACED name and a `<|constrain|>` marker:
|
|
10
|
+
// `<|channel|>commentary to=functions.get_weather<|constrain|>json<|message|>{...}<|call|>`
|
|
11
|
+
//
|
|
12
|
+
// {@link parseStandalonePlainTextToolCallBlocks} is STANDALONE-only by construction: it walks the
|
|
13
|
+
// WHOLE input and returns null the moment it hits text that is not a tool-call block, so prose that
|
|
14
|
+
// merely mentions a tool or contains brackets never parses as a call. Allow-list + payload-size
|
|
15
|
+
// gating are threaded through {@link PlainTextToolCallParseOptions}. The reference's streaming
|
|
16
|
+
// normalizer and user-visible strip helpers are intentionally omitted (not needed for promotion).
|
|
17
|
+
import { consumeLineBreak, END_TOOL_REQUEST, finalDotSegment, findJsonObjectEnd, HARMONY_CALL_MARKER, HARMONY_CHANNEL_MARKER, HARMONY_CONSTRAIN_MARKER, HARMONY_MESSAGE_MARKER, isHarmonyToolNameChar, isPlainTextToolNameChar, skipHorizontalWhitespace, skipWhitespace, } from './grammar.js';
|
|
18
|
+
/**
|
|
19
|
+
* The single source of truth for the plain-text tool-call payload cap (256 KB). A serialized call
|
|
20
|
+
* larger than this is never treated as a tool call. Re-exported from `./promote.js` (and the module
|
|
21
|
+
* index) as `MAX_TEXT_EMITTED_TOOL_CALL_PAYLOAD_BYTES` — the public name — so there is ONE constant,
|
|
22
|
+
* not two duplicated literals. (EXT-43 unified the former `DEFAULT_MAX_PLAIN_TEXT_TOOL_PAYLOAD_BYTES`
|
|
23
|
+
* here with `promote.ts`'s copy.)
|
|
24
|
+
*/
|
|
25
|
+
export const MAX_TEXT_EMITTED_TOOL_CALL_PAYLOAD_BYTES = 256_000;
|
|
26
|
+
const utf8Encoder = new TextEncoder();
|
|
27
|
+
function utf8ByteLengthWithinLimit(text, start, end, maxBytes) {
|
|
28
|
+
if (end - start > maxBytes) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
const byteLength = utf8Encoder.encode(text.slice(start, end)).byteLength;
|
|
32
|
+
return byteLength <= maxBytes ? byteLength : null;
|
|
33
|
+
}
|
|
34
|
+
function parseBracketOpening(text, start) {
|
|
35
|
+
if (text[start] !== '[') {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
let cursor = start + 1;
|
|
39
|
+
if (text.startsWith('tool:', cursor)) {
|
|
40
|
+
cursor += 'tool:'.length;
|
|
41
|
+
const nameStart = cursor;
|
|
42
|
+
while (isPlainTextToolNameChar(text[cursor])) {
|
|
43
|
+
cursor += 1;
|
|
44
|
+
}
|
|
45
|
+
if (cursor === nameStart || text[cursor] !== ']') {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
allowsOptionalXmlishClose: true,
|
|
50
|
+
end: cursor + 1,
|
|
51
|
+
name: text.slice(nameStart, cursor),
|
|
52
|
+
requiresClosing: false,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
const nameStart = cursor;
|
|
56
|
+
while (isPlainTextToolNameChar(text[cursor])) {
|
|
57
|
+
cursor += 1;
|
|
58
|
+
}
|
|
59
|
+
if (cursor === nameStart || text[cursor] !== ']') {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
const name = text.slice(nameStart, cursor);
|
|
63
|
+
cursor += 1;
|
|
64
|
+
cursor = skipHorizontalWhitespace(text, cursor);
|
|
65
|
+
const afterLineBreak = consumeLineBreak(text, cursor);
|
|
66
|
+
if (afterLineBreak === null) {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
return { end: afterLineBreak, name, requiresClosing: true };
|
|
70
|
+
}
|
|
71
|
+
function parseHarmonyOpening(text, start) {
|
|
72
|
+
let cursor = start;
|
|
73
|
+
if (text.startsWith(HARMONY_CHANNEL_MARKER, cursor)) {
|
|
74
|
+
cursor += HARMONY_CHANNEL_MARKER.length;
|
|
75
|
+
}
|
|
76
|
+
const channelStart = cursor;
|
|
77
|
+
while (/[A-Za-z_]/.test(text[cursor] ?? '')) {
|
|
78
|
+
cursor += 1;
|
|
79
|
+
}
|
|
80
|
+
const channel = text.slice(channelStart, cursor);
|
|
81
|
+
if (channel !== 'commentary' && channel !== 'analysis' && channel !== 'final') {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
cursor = skipHorizontalWhitespace(text, cursor);
|
|
85
|
+
if (!text.startsWith('to=', cursor)) {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
cursor += 3;
|
|
89
|
+
// Tool name. EXT-43: accept the real gpt-oss NAMESPACED form (`to=functions.get_weather`) by
|
|
90
|
+
// scanning dot-inclusive chars, then take the FINAL dot-segment as the allow-listed tool name.
|
|
91
|
+
// The reference dotless form (`to=get_weather`) is the single-segment degenerate case.
|
|
92
|
+
const nameStart = cursor;
|
|
93
|
+
while (isHarmonyToolNameChar(text[cursor])) {
|
|
94
|
+
cursor += 1;
|
|
95
|
+
}
|
|
96
|
+
if (cursor === nameStart) {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
const name = finalDotSegment(text.slice(nameStart, cursor));
|
|
100
|
+
if (!name) {
|
|
101
|
+
// Trailing-dot / empty final segment (e.g. `to=functions.`) is not a valid tool name.
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
cursor = skipHorizontalWhitespace(text, cursor);
|
|
105
|
+
// Payload-format marker between the header and the JSON. The reference grammar requires the
|
|
106
|
+
// literal `code` token; real gpt-oss instead emits `<|constrain|>json` (EXT-43). Accept EITHER —
|
|
107
|
+
// but a marker is still REQUIRED, so the widening does not relax prose-safety (a bare
|
|
108
|
+
// `commentary to=x {…}` never promotes).
|
|
109
|
+
if (text.startsWith('code', cursor)) {
|
|
110
|
+
cursor += 4;
|
|
111
|
+
}
|
|
112
|
+
else if (text.startsWith(HARMONY_CONSTRAIN_MARKER, cursor)) {
|
|
113
|
+
cursor += HARMONY_CONSTRAIN_MARKER.length;
|
|
114
|
+
// Optional constraint-format token that follows the marker (e.g. `json`).
|
|
115
|
+
cursor = skipHorizontalWhitespace(text, cursor);
|
|
116
|
+
while (isPlainTextToolNameChar(text[cursor])) {
|
|
117
|
+
cursor += 1;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
cursor = skipWhitespace(text, cursor);
|
|
124
|
+
if (text.startsWith(HARMONY_MESSAGE_MARKER, cursor)) {
|
|
125
|
+
cursor = skipWhitespace(text, cursor + HARMONY_MESSAGE_MARKER.length);
|
|
126
|
+
}
|
|
127
|
+
return { end: cursor, name, requiresClosing: false };
|
|
128
|
+
}
|
|
129
|
+
function parseXmlishFunctionOpening(text, start) {
|
|
130
|
+
const match = /^<function=([A-Za-z0-9_.:-]{1,120})>\s*/i.exec(text.slice(start));
|
|
131
|
+
if (!match?.[1]) {
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
return { end: start + match[0].length, name: match[1], requiresClosing: false };
|
|
135
|
+
}
|
|
136
|
+
function parseOpening(text, start) {
|
|
137
|
+
return parseBracketOpening(text, start) ?? parseHarmonyOpening(text, start);
|
|
138
|
+
}
|
|
139
|
+
function consumeJsonObject(text, start, maxPayloadBytes) {
|
|
140
|
+
const cursor = skipWhitespace(text, start);
|
|
141
|
+
if (text[cursor] !== '{') {
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
const end = findJsonObjectEnd(text, cursor, maxPayloadBytes);
|
|
145
|
+
if (end === null || utf8ByteLengthWithinLimit(text, cursor, end, maxPayloadBytes) === null) {
|
|
146
|
+
return null;
|
|
147
|
+
}
|
|
148
|
+
const rawJson = text.slice(cursor, end);
|
|
149
|
+
try {
|
|
150
|
+
const parsed = JSON.parse(rawJson);
|
|
151
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
152
|
+
return null;
|
|
153
|
+
}
|
|
154
|
+
return { end, value: parsed };
|
|
155
|
+
}
|
|
156
|
+
catch {
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
function parseClosing(text, start, name) {
|
|
161
|
+
const cursor = skipWhitespace(text, start);
|
|
162
|
+
if (text.startsWith(END_TOOL_REQUEST, cursor)) {
|
|
163
|
+
return cursor + END_TOOL_REQUEST.length;
|
|
164
|
+
}
|
|
165
|
+
const namedClosing = `[/${name}]`;
|
|
166
|
+
if (text.startsWith(namedClosing, cursor)) {
|
|
167
|
+
return cursor + namedClosing.length;
|
|
168
|
+
}
|
|
169
|
+
return null;
|
|
170
|
+
}
|
|
171
|
+
function parseOptionalHarmonyClosing(text, start) {
|
|
172
|
+
const cursor = skipWhitespace(text, start);
|
|
173
|
+
if (text.startsWith(HARMONY_CALL_MARKER, cursor)) {
|
|
174
|
+
return cursor + HARMONY_CALL_MARKER.length;
|
|
175
|
+
}
|
|
176
|
+
return start;
|
|
177
|
+
}
|
|
178
|
+
function parsePlainTextToolCallBlockAt(text, start, options) {
|
|
179
|
+
const opening = parseOpening(text, start);
|
|
180
|
+
if (!opening) {
|
|
181
|
+
return null;
|
|
182
|
+
}
|
|
183
|
+
const allowedToolNames = options?.allowedToolNames
|
|
184
|
+
? new Set(options.allowedToolNames)
|
|
185
|
+
: undefined;
|
|
186
|
+
if (allowedToolNames && !allowedToolNames.has(opening.name)) {
|
|
187
|
+
return null;
|
|
188
|
+
}
|
|
189
|
+
const payload = consumeJsonObject(text, opening.end, options?.maxPayloadBytes ?? MAX_TEXT_EMITTED_TOOL_CALL_PAYLOAD_BYTES);
|
|
190
|
+
if (!payload) {
|
|
191
|
+
return null;
|
|
192
|
+
}
|
|
193
|
+
const closingEnd = opening.requiresClosing
|
|
194
|
+
? parseClosing(text, payload.end, opening.name)
|
|
195
|
+
: parseOptionalHarmonyClosing(text, payload.end);
|
|
196
|
+
if (closingEnd === null) {
|
|
197
|
+
return null;
|
|
198
|
+
}
|
|
199
|
+
return {
|
|
200
|
+
arguments: payload.value,
|
|
201
|
+
end: closingEnd,
|
|
202
|
+
name: opening.name,
|
|
203
|
+
raw: text.slice(start, closingEnd),
|
|
204
|
+
start,
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
function findXmlishParameterBlock(text, start) {
|
|
208
|
+
const cursor = skipWhitespace(text, start);
|
|
209
|
+
const openMatch = /^<parameter=([A-Za-z0-9_.:-]{1,120})>/i.exec(text.slice(cursor));
|
|
210
|
+
if (!openMatch?.[1]) {
|
|
211
|
+
return null;
|
|
212
|
+
}
|
|
213
|
+
const payloadStart = cursor + openMatch[0].length;
|
|
214
|
+
const closeMatch = /<\/parameter>/i.exec(text.slice(payloadStart));
|
|
215
|
+
if (!closeMatch) {
|
|
216
|
+
return null;
|
|
217
|
+
}
|
|
218
|
+
const closeStart = payloadStart + closeMatch.index;
|
|
219
|
+
const closeEnd = closeStart + closeMatch[0].length;
|
|
220
|
+
return {
|
|
221
|
+
closeStart,
|
|
222
|
+
end: closeEnd,
|
|
223
|
+
name: openMatch[1],
|
|
224
|
+
payloadStart,
|
|
225
|
+
start: cursor,
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
function extractXmlishParameterValue(text, start, end) {
|
|
229
|
+
let payloadStart = start;
|
|
230
|
+
let payloadEnd = end;
|
|
231
|
+
const afterOpeningLineBreak = consumeLineBreak(text, payloadStart);
|
|
232
|
+
if (afterOpeningLineBreak !== null) {
|
|
233
|
+
payloadStart = afterOpeningLineBreak;
|
|
234
|
+
if (payloadEnd > payloadStart && text[payloadEnd - 1] === '\n') {
|
|
235
|
+
payloadEnd -= 1;
|
|
236
|
+
if (payloadEnd > payloadStart && text[payloadEnd - 1] === '\r') {
|
|
237
|
+
payloadEnd -= 1;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
else if (payloadEnd > payloadStart && text[payloadEnd - 1] === '\r') {
|
|
241
|
+
payloadEnd -= 1;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
return text.slice(payloadStart, payloadEnd);
|
|
245
|
+
}
|
|
246
|
+
function consumeXmlishParameterBlock(text, start, maxPayloadBytes) {
|
|
247
|
+
const bounds = findXmlishParameterBlock(text, start);
|
|
248
|
+
if (!bounds) {
|
|
249
|
+
return null;
|
|
250
|
+
}
|
|
251
|
+
const byteLength = utf8ByteLengthWithinLimit(text, start, bounds.end, maxPayloadBytes);
|
|
252
|
+
if (byteLength === null) {
|
|
253
|
+
return null;
|
|
254
|
+
}
|
|
255
|
+
return {
|
|
256
|
+
byteLength,
|
|
257
|
+
end: bounds.end,
|
|
258
|
+
name: bounds.name,
|
|
259
|
+
value: extractXmlishParameterValue(text, bounds.payloadStart, bounds.closeStart),
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
function consumeXmlishFunctionClose(text, start) {
|
|
263
|
+
const cursor = skipWhitespace(text, start);
|
|
264
|
+
return text.slice(cursor).toLowerCase().startsWith('</function>')
|
|
265
|
+
? cursor + '</function>'.length
|
|
266
|
+
: null;
|
|
267
|
+
}
|
|
268
|
+
function consumeOptionalXmlishFunctionClose(text, start) {
|
|
269
|
+
return consumeXmlishFunctionClose(text, start) ?? start;
|
|
270
|
+
}
|
|
271
|
+
function parseXmlishOpening(text, start) {
|
|
272
|
+
return parseBracketOpening(text, start) ?? parseXmlishFunctionOpening(text, start);
|
|
273
|
+
}
|
|
274
|
+
function parseXmlishPlainTextToolCallBlockAt(text, start, options) {
|
|
275
|
+
const opening = parseXmlishOpening(text, start);
|
|
276
|
+
if (!opening) {
|
|
277
|
+
return null;
|
|
278
|
+
}
|
|
279
|
+
const allowedToolNames = options?.allowedToolNames
|
|
280
|
+
? new Set(options.allowedToolNames)
|
|
281
|
+
: undefined;
|
|
282
|
+
if (allowedToolNames && !allowedToolNames.has(opening.name)) {
|
|
283
|
+
return null;
|
|
284
|
+
}
|
|
285
|
+
const maxPayloadBytes = options?.maxPayloadBytes ?? MAX_TEXT_EMITTED_TOOL_CALL_PAYLOAD_BYTES;
|
|
286
|
+
const args = {};
|
|
287
|
+
let cursor = opening.end;
|
|
288
|
+
let parameterCount = 0;
|
|
289
|
+
let payloadBytes = 0;
|
|
290
|
+
while (true) {
|
|
291
|
+
const parameter = consumeXmlishParameterBlock(text, cursor, maxPayloadBytes);
|
|
292
|
+
if (!parameter) {
|
|
293
|
+
break;
|
|
294
|
+
}
|
|
295
|
+
payloadBytes += parameter.byteLength;
|
|
296
|
+
if (payloadBytes > maxPayloadBytes) {
|
|
297
|
+
return null;
|
|
298
|
+
}
|
|
299
|
+
args[parameter.name] = parameter.value;
|
|
300
|
+
parameterCount += 1;
|
|
301
|
+
cursor = parameter.end;
|
|
302
|
+
}
|
|
303
|
+
if (parameterCount === 0) {
|
|
304
|
+
return null;
|
|
305
|
+
}
|
|
306
|
+
const end = opening.allowsOptionalXmlishClose
|
|
307
|
+
? consumeOptionalXmlishFunctionClose(text, cursor)
|
|
308
|
+
: consumeXmlishFunctionClose(text, cursor);
|
|
309
|
+
if (end === null) {
|
|
310
|
+
return null;
|
|
311
|
+
}
|
|
312
|
+
return {
|
|
313
|
+
arguments: args,
|
|
314
|
+
end,
|
|
315
|
+
name: opening.name,
|
|
316
|
+
raw: text.slice(start, end),
|
|
317
|
+
start,
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Parse the WHOLE input into standalone plain-text tool-call blocks, or return null if any part of
|
|
322
|
+
* it is not such a block. This all-or-nothing walk is the standalone-only gate: prose that merely
|
|
323
|
+
* mentions a tool name, contains brackets, or embeds a call inside a sentence never parses (the
|
|
324
|
+
* first non-block character aborts the parse). Allow-list + payload-cap gating are applied per
|
|
325
|
+
* block via {@link PlainTextToolCallParseOptions}.
|
|
326
|
+
*/
|
|
327
|
+
export function parseStandalonePlainTextToolCallBlocks(text, options) {
|
|
328
|
+
const blocks = [];
|
|
329
|
+
let cursor = skipWhitespace(text, 0);
|
|
330
|
+
while (cursor < text.length) {
|
|
331
|
+
const block = parsePlainTextToolCallBlockAt(text, cursor, options) ??
|
|
332
|
+
parseXmlishPlainTextToolCallBlockAt(text, cursor, options);
|
|
333
|
+
if (!block) {
|
|
334
|
+
return null;
|
|
335
|
+
}
|
|
336
|
+
blocks.push(block);
|
|
337
|
+
cursor = skipWhitespace(text, block.end);
|
|
338
|
+
}
|
|
339
|
+
return blocks.length > 0 ? blocks : null;
|
|
340
|
+
}
|
|
341
|
+
//# sourceMappingURL=payload.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"payload.js","sourceRoot":"","sources":["../../../src/core/toolCallRepair/payload.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { AIMessage } from '@langchain/core/messages';
|
|
2
|
+
/**
|
|
3
|
+
* A sane default cap on a single repaired call's serialized payload. A text blob larger than this
|
|
4
|
+
* is never treated as a tool call. Overridable per call so a test can assert the cap with a small
|
|
5
|
+
* value; production leaves it at the default. The single source of truth lives in `./payload.js`
|
|
6
|
+
* and is re-exported here under its public name (EXT-43 unified the former duplicated literal).
|
|
7
|
+
*/
|
|
8
|
+
export { MAX_TEXT_EMITTED_TOOL_CALL_PAYLOAD_BYTES } from './payload.js';
|
|
9
|
+
/** LangChain native tool-call shape (structurally a `ToolCall` from `@langchain/core/messages`). */
|
|
10
|
+
type NativeToolCall = {
|
|
11
|
+
id: string;
|
|
12
|
+
name: string;
|
|
13
|
+
args: Record<string, unknown>;
|
|
14
|
+
type: 'tool_call';
|
|
15
|
+
};
|
|
16
|
+
/** Gates for {@link textToNativeToolCalls} / {@link promoteTextEmittedToolCallMessage}. */
|
|
17
|
+
export interface TextToolCallRepairOptions {
|
|
18
|
+
/**
|
|
19
|
+
* The names of the tools bound to this run (the allow-list). Only a text-emitted call whose name
|
|
20
|
+
* is one of these promotes; an unknown name is left as text. An EMPTY set promotes nothing — the
|
|
21
|
+
* prose-safe default (no toolset ⇒ nothing is a call).
|
|
22
|
+
*/
|
|
23
|
+
allowedToolNames: Iterable<string>;
|
|
24
|
+
/** Payload-size cap; defaults to {@link MAX_TEXT_EMITTED_TOOL_CALL_PAYLOAD_BYTES}. */
|
|
25
|
+
maxPayloadBytes?: number;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Parse assistant `text` as one-or-more STANDALONE text-emitted tool calls and return them as
|
|
29
|
+
* native LangChain tool_calls, or `undefined` when the text is not a standalone call, names a tool
|
|
30
|
+
* outside the allow-list, or exceeds the payload cap. Fresh `id`s are minted per call (the model
|
|
31
|
+
* emitted none). Empty allow-list ⇒ `undefined` (never promote).
|
|
32
|
+
*/
|
|
33
|
+
export declare function textToNativeToolCalls(text: string | undefined, options: TextToolCallRepairOptions): NativeToolCall[] | undefined;
|
|
34
|
+
/**
|
|
35
|
+
* Repair one assistant {@link AIMessage}: if it has NO native tool_calls but its content is a
|
|
36
|
+
* standalone text-emitted call (allow-listed, within the payload cap), return a NEW AIMessage that
|
|
37
|
+
* carries the promoted native tool_calls; otherwise return `undefined` (the caller keeps the
|
|
38
|
+
* original, so the native happy path is untouched).
|
|
39
|
+
*
|
|
40
|
+
* The returned message PRESERVES the original `id`. That is load-bearing: LangGraph's message-state
|
|
41
|
+
* reducer merges by id, so a same-id message REPLACES the original in graph state (rather than
|
|
42
|
+
* appending a duplicate/dangling assistant message). Content is cleared to '' since the raw
|
|
43
|
+
* text-call is now represented natively as tool_calls.
|
|
44
|
+
*/
|
|
45
|
+
export declare function promoteTextEmittedToolCallMessage(message: AIMessage, options: TextToolCallRepairOptions): AIMessage | undefined;
|