cmdr-agent 2.4.0 → 2.5.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/dist/package.json +1 -1
- package/dist/src/cli/progress.d.ts +58 -0
- package/dist/src/cli/progress.d.ts.map +1 -0
- package/dist/src/cli/progress.js +179 -0
- package/dist/src/cli/progress.js.map +1 -0
- package/dist/src/cli/spinner.d.ts +2 -0
- package/dist/src/cli/spinner.d.ts.map +1 -1
- package/dist/src/cli/spinner.js +18 -0
- package/dist/src/cli/spinner.js.map +1 -1
- package/dist/src/core/agent-runner.d.ts +12 -0
- package/dist/src/core/agent-runner.d.ts.map +1 -1
- package/dist/src/core/agent-runner.js +176 -5
- package/dist/src/core/agent-runner.js.map +1 -1
- package/dist/src/core/event-bus.d.ts +12 -0
- package/dist/src/core/event-bus.d.ts.map +1 -1
- package/dist/src/core/event-bus.js.map +1 -1
- package/dist/src/core/types.d.ts +17 -0
- package/dist/src/core/types.d.ts.map +1 -1
- package/dist/src/core/types.js +8 -1
- package/dist/src/core/types.js.map +1 -1
- package/dist/src/llm/anthropic.d.ts +1 -0
- package/dist/src/llm/anthropic.d.ts.map +1 -1
- package/dist/src/llm/anthropic.js +20 -1
- package/dist/src/llm/anthropic.js.map +1 -1
- package/dist/src/llm/ollama.d.ts +2 -12
- package/dist/src/llm/ollama.d.ts.map +1 -1
- package/dist/src/llm/ollama.js +46 -250
- package/dist/src/llm/ollama.js.map +1 -1
- package/dist/src/llm/openai.d.ts +1 -0
- package/dist/src/llm/openai.d.ts.map +1 -1
- package/dist/src/llm/openai.js +21 -7
- package/dist/src/llm/openai.js.map +1 -1
- package/dist/src/llm/repair/retry-policy.d.ts +48 -0
- package/dist/src/llm/repair/retry-policy.d.ts.map +1 -0
- package/dist/src/llm/repair/retry-policy.js +85 -0
- package/dist/src/llm/repair/retry-policy.js.map +1 -0
- package/dist/src/llm/repair/tool-repair.d.ts +39 -0
- package/dist/src/llm/repair/tool-repair.d.ts.map +1 -0
- package/dist/src/llm/repair/tool-repair.js +313 -0
- package/dist/src/llm/repair/tool-repair.js.map +1 -0
- package/dist/src/llm/shared/text-cleanup.d.ts +16 -0
- package/dist/src/llm/shared/text-cleanup.d.ts.map +1 -0
- package/dist/src/llm/shared/text-cleanup.js +120 -0
- package/dist/src/llm/shared/text-cleanup.js.map +1 -0
- package/dist/src/llm/shared/tool-parsing.d.ts +70 -0
- package/dist/src/llm/shared/tool-parsing.d.ts.map +1 -0
- package/dist/src/llm/shared/tool-parsing.js +355 -0
- package/dist/src/llm/shared/tool-parsing.js.map +1 -0
- package/dist/src/llm/validation/tool-call-schema.d.ts +83 -0
- package/dist/src/llm/validation/tool-call-schema.d.ts.map +1 -0
- package/dist/src/llm/validation/tool-call-schema.js +145 -0
- package/dist/src/llm/validation/tool-call-schema.js.map +1 -0
- package/dist/src/tools/built-in/bash.d.ts +5 -1
- package/dist/src/tools/built-in/bash.d.ts.map +1 -1
- package/dist/src/tools/built-in/bash.js +34 -46
- package/dist/src/tools/built-in/bash.js.map +1 -1
- package/dist/src/tools/executor.d.ts +7 -1
- package/dist/src/tools/executor.d.ts.map +1 -1
- package/dist/src/tools/executor.js +20 -5
- package/dist/src/tools/executor.js.map +1 -1
- package/dist/src/tools/shell/shell-executor.d.ts +71 -0
- package/dist/src/tools/shell/shell-executor.d.ts.map +1 -0
- package/dist/src/tools/shell/shell-executor.js +238 -0
- package/dist/src/tools/shell/shell-executor.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified tool call parser for all LLM adapters.
|
|
3
|
+
*
|
|
4
|
+
* Consolidates the tool parsing logic that was duplicated across
|
|
5
|
+
* ollama.ts, openai.ts, and anthropic.ts into a single, well-tested module.
|
|
6
|
+
*
|
|
7
|
+
* Supports:
|
|
8
|
+
* - Native API tool calls (Ollama, OpenAI, Anthropic)
|
|
9
|
+
* - Text-based JSON format: ```tool_call\n{JSON}\n```
|
|
10
|
+
* - XML function format: <function=name><parameter=key>value</parameter></function>
|
|
11
|
+
* - Invoke format: <invoke name="..."><parameter name="...">value</parameter></invoke>
|
|
12
|
+
* - MiniMax wrapper: <minimax:tool_call>...</minimax:tool_call>
|
|
13
|
+
*
|
|
14
|
+
* Each strategy runs in order and returns on first match (waterfall).
|
|
15
|
+
*/
|
|
16
|
+
import type { ContentBlock } from '../../core/types.js';
|
|
17
|
+
export interface ToolParseConfig {
|
|
18
|
+
/** Enable JSON ```tool_call``` format parsing. Default: true */
|
|
19
|
+
jsonToolFormat?: boolean;
|
|
20
|
+
/** Enable XML <function=name> format parsing. Default: true */
|
|
21
|
+
xmlToolFormat?: boolean;
|
|
22
|
+
/** Enable <invoke> tag format parsing. Default: true */
|
|
23
|
+
invokeFormat?: boolean;
|
|
24
|
+
}
|
|
25
|
+
export interface NativeToolCall {
|
|
26
|
+
function: {
|
|
27
|
+
name: string;
|
|
28
|
+
arguments: Record<string, unknown> | string;
|
|
29
|
+
};
|
|
30
|
+
id?: string;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Three-stage tool resolution waterfall.
|
|
34
|
+
* This is the main entry point for all adapters.
|
|
35
|
+
*
|
|
36
|
+
* 1. Native tool_calls from API (highest confidence)
|
|
37
|
+
* 2. Text-based JSON format
|
|
38
|
+
* 3. Text-based XML format
|
|
39
|
+
*
|
|
40
|
+
* Returns an array of ContentBlocks (text + tool_use mixed).
|
|
41
|
+
*/
|
|
42
|
+
export declare function resolveToolCalls(nativeToolCalls: NativeToolCall[] | null | undefined, textContent: string, config?: ToolParseConfig, hasTools?: boolean): ContentBlock[];
|
|
43
|
+
/**
|
|
44
|
+
* Parse tool calls from text output using multiple strategies.
|
|
45
|
+
* Returns ContentBlock[] with interleaved text and tool_use blocks.
|
|
46
|
+
*/
|
|
47
|
+
export declare function parseTextToolCalls(text: string, config?: ToolParseConfig): ContentBlock[];
|
|
48
|
+
/**
|
|
49
|
+
* Parse multiple JSON objects from a block that may contain:
|
|
50
|
+
* - A single JSON object
|
|
51
|
+
* - A JSON array
|
|
52
|
+
* - One object per line
|
|
53
|
+
* - Comma-separated objects
|
|
54
|
+
*/
|
|
55
|
+
export declare function parseMultipleJsonObjects(block: string): Array<{
|
|
56
|
+
name: string;
|
|
57
|
+
arguments: Record<string, unknown>;
|
|
58
|
+
}>;
|
|
59
|
+
/**
|
|
60
|
+
* Build the tool-call instruction suffix to inject into the system prompt
|
|
61
|
+
* for models that don't support native tool calling.
|
|
62
|
+
*/
|
|
63
|
+
export declare function buildToolPromptSuffix(tools: readonly {
|
|
64
|
+
name: string;
|
|
65
|
+
description: string;
|
|
66
|
+
inputSchema: Record<string, unknown>;
|
|
67
|
+
}[], options?: {
|
|
68
|
+
strict?: boolean;
|
|
69
|
+
}): string;
|
|
70
|
+
//# sourceMappingURL=tool-parsing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-parsing.d.ts","sourceRoot":"","sources":["../../../../src/llm/shared/tool-parsing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,YAAY,EAA2B,MAAM,qBAAqB,CAAA;AAQhF,MAAM,WAAW,eAAe;IAC9B,gEAAgE;IAChE,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,+DAA+D;IAC/D,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,wDAAwD;IACxD,YAAY,CAAC,EAAE,OAAO,CAAA;CACvB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAA;QACZ,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAA;KAC5C,CAAA;IACD,EAAE,CAAC,EAAE,MAAM,CAAA;CACZ;AAuBD;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAC9B,eAAe,EAAE,cAAc,EAAE,GAAG,IAAI,GAAG,SAAS,EACpD,WAAW,EAAE,MAAM,EACnB,MAAM,CAAC,EAAE,eAAe,EACxB,QAAQ,CAAC,EAAE,OAAO,GACjB,YAAY,EAAE,CA6ChB;AAMD;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,eAAe,GACvB,YAAY,EAAE,CAgChB;AA8JD;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,MAAM,GACZ,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,CAAC,CA+C7D;AAkBD;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,SAAS;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,EAAE,EAC7F,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,GAC7B,MAAM,CA0BR"}
|
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified tool call parser for all LLM adapters.
|
|
3
|
+
*
|
|
4
|
+
* Consolidates the tool parsing logic that was duplicated across
|
|
5
|
+
* ollama.ts, openai.ts, and anthropic.ts into a single, well-tested module.
|
|
6
|
+
*
|
|
7
|
+
* Supports:
|
|
8
|
+
* - Native API tool calls (Ollama, OpenAI, Anthropic)
|
|
9
|
+
* - Text-based JSON format: ```tool_call\n{JSON}\n```
|
|
10
|
+
* - XML function format: <function=name><parameter=key>value</parameter></function>
|
|
11
|
+
* - Invoke format: <invoke name="..."><parameter name="...">value</parameter></invoke>
|
|
12
|
+
* - MiniMax wrapper: <minimax:tool_call>...</minimax:tool_call>
|
|
13
|
+
*
|
|
14
|
+
* Each strategy runs in order and returns on first match (waterfall).
|
|
15
|
+
*/
|
|
16
|
+
import { validateToolCallShape } from '../validation/tool-call-schema.js';
|
|
17
|
+
import { cleanLLMOutput } from './text-cleanup.js';
|
|
18
|
+
const DEFAULT_CONFIG = {
|
|
19
|
+
jsonToolFormat: true,
|
|
20
|
+
xmlToolFormat: true,
|
|
21
|
+
invokeFormat: true,
|
|
22
|
+
};
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
// ID generation
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
let _idCounter = 0;
|
|
27
|
+
function generateToolId() {
|
|
28
|
+
_idCounter++;
|
|
29
|
+
return `tool_${Date.now()}_${_idCounter.toString(36)}_${Math.random().toString(36).slice(2, 6)}`;
|
|
30
|
+
}
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
// Unified resolution: native → text waterfall
|
|
33
|
+
// ---------------------------------------------------------------------------
|
|
34
|
+
/**
|
|
35
|
+
* Three-stage tool resolution waterfall.
|
|
36
|
+
* This is the main entry point for all adapters.
|
|
37
|
+
*
|
|
38
|
+
* 1. Native tool_calls from API (highest confidence)
|
|
39
|
+
* 2. Text-based JSON format
|
|
40
|
+
* 3. Text-based XML format
|
|
41
|
+
*
|
|
42
|
+
* Returns an array of ContentBlocks (text + tool_use mixed).
|
|
43
|
+
*/
|
|
44
|
+
export function resolveToolCalls(nativeToolCalls, textContent, config, hasTools) {
|
|
45
|
+
const cfg = { ...DEFAULT_CONFIG, ...config };
|
|
46
|
+
// Stage 1: Native tool_calls from API response
|
|
47
|
+
if (nativeToolCalls && nativeToolCalls.length > 0) {
|
|
48
|
+
const content = [];
|
|
49
|
+
if (textContent) {
|
|
50
|
+
content.push({ type: 'text', text: textContent });
|
|
51
|
+
}
|
|
52
|
+
for (const tc of nativeToolCalls) {
|
|
53
|
+
const args = typeof tc.function.arguments === 'string'
|
|
54
|
+
? safeParseJson(tc.function.arguments)
|
|
55
|
+
: tc.function.arguments;
|
|
56
|
+
const validation = validateToolCallShape({
|
|
57
|
+
name: tc.function.name,
|
|
58
|
+
arguments: args,
|
|
59
|
+
});
|
|
60
|
+
if (validation.ok) {
|
|
61
|
+
content.push({
|
|
62
|
+
type: 'tool_use',
|
|
63
|
+
id: tc.id ?? generateToolId(),
|
|
64
|
+
name: validation.toolCall.name,
|
|
65
|
+
input: validation.toolCall.arguments,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return content;
|
|
70
|
+
}
|
|
71
|
+
// Stage 0: Pre-parse cleanup for text-based parsing
|
|
72
|
+
const cleanedText = hasTools && textContent ? cleanLLMOutput(textContent) : textContent;
|
|
73
|
+
// Stage 2+3: Parse text-based tool calls only if tools are available
|
|
74
|
+
if (hasTools && cleanedText) {
|
|
75
|
+
const parsed = parseTextToolCalls(cleanedText, cfg);
|
|
76
|
+
if (parsed.length > 0)
|
|
77
|
+
return parsed;
|
|
78
|
+
}
|
|
79
|
+
// No tool calls — return as pure text (use original, uncleaned text for display)
|
|
80
|
+
if (textContent) {
|
|
81
|
+
return [{ type: 'text', text: textContent }];
|
|
82
|
+
}
|
|
83
|
+
return [];
|
|
84
|
+
}
|
|
85
|
+
// ---------------------------------------------------------------------------
|
|
86
|
+
// Text-based tool call extraction (all strategies)
|
|
87
|
+
// ---------------------------------------------------------------------------
|
|
88
|
+
/**
|
|
89
|
+
* Parse tool calls from text output using multiple strategies.
|
|
90
|
+
* Returns ContentBlock[] with interleaved text and tool_use blocks.
|
|
91
|
+
*/
|
|
92
|
+
export function parseTextToolCalls(text, config) {
|
|
93
|
+
const cfg = { ...DEFAULT_CONFIG, ...config };
|
|
94
|
+
// Strategy 1: ```tool_call JSON format
|
|
95
|
+
if (cfg.jsonToolFormat) {
|
|
96
|
+
const result = parseJsonToolCalls(text);
|
|
97
|
+
if (result.length > 0 && result.some(b => b.type === 'tool_use')) {
|
|
98
|
+
return result;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
// Strategy 2: <function=name> XML format
|
|
102
|
+
if (cfg.xmlToolFormat) {
|
|
103
|
+
const result = parseXmlFunctionCalls(text);
|
|
104
|
+
if (result.length > 0 && result.some(b => b.type === 'tool_use')) {
|
|
105
|
+
return result;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
// Strategy 3: <invoke name="..."> format (MiniMax, etc.)
|
|
109
|
+
if (cfg.invokeFormat) {
|
|
110
|
+
const result = parseInvokeCalls(text);
|
|
111
|
+
if (result.length > 0 && result.some(b => b.type === 'tool_use')) {
|
|
112
|
+
return result;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
// No tool calls found
|
|
116
|
+
if (text) {
|
|
117
|
+
return [{ type: 'text', text }];
|
|
118
|
+
}
|
|
119
|
+
return [];
|
|
120
|
+
}
|
|
121
|
+
// ---------------------------------------------------------------------------
|
|
122
|
+
// Strategy 1: JSON ```tool_call``` format
|
|
123
|
+
// ---------------------------------------------------------------------------
|
|
124
|
+
function parseJsonToolCalls(text) {
|
|
125
|
+
const content = [];
|
|
126
|
+
const toolCallRegex = /```tool_call\s*\n([\s\S]*?)\n```/g;
|
|
127
|
+
let lastIndex = 0;
|
|
128
|
+
let match;
|
|
129
|
+
let foundToolCalls = false;
|
|
130
|
+
while ((match = toolCallRegex.exec(text)) !== null) {
|
|
131
|
+
foundToolCalls = true;
|
|
132
|
+
// Add preceding text
|
|
133
|
+
if (match.index > lastIndex) {
|
|
134
|
+
const before = text.slice(lastIndex, match.index).trim();
|
|
135
|
+
if (before)
|
|
136
|
+
content.push({ type: 'text', text: before });
|
|
137
|
+
}
|
|
138
|
+
const blockContent = match[1].trim();
|
|
139
|
+
const parsedObjects = parseMultipleJsonObjects(blockContent);
|
|
140
|
+
if (parsedObjects.length > 0) {
|
|
141
|
+
for (const parsed of parsedObjects) {
|
|
142
|
+
const validation = validateToolCallShape(parsed);
|
|
143
|
+
if (validation.ok) {
|
|
144
|
+
content.push({
|
|
145
|
+
type: 'tool_use',
|
|
146
|
+
id: generateToolId(),
|
|
147
|
+
name: validation.toolCall.name,
|
|
148
|
+
input: validation.toolCall.arguments,
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
// Could not parse — keep as text
|
|
155
|
+
content.push({ type: 'text', text: match[0] });
|
|
156
|
+
}
|
|
157
|
+
lastIndex = match.index + match[0].length;
|
|
158
|
+
}
|
|
159
|
+
if (foundToolCalls && lastIndex < text.length) {
|
|
160
|
+
const remainder = text.slice(lastIndex).trim();
|
|
161
|
+
if (remainder)
|
|
162
|
+
content.push({ type: 'text', text: remainder });
|
|
163
|
+
}
|
|
164
|
+
return foundToolCalls ? content : [];
|
|
165
|
+
}
|
|
166
|
+
// ---------------------------------------------------------------------------
|
|
167
|
+
// Strategy 2: XML <function=name> format
|
|
168
|
+
// ---------------------------------------------------------------------------
|
|
169
|
+
function parseXmlFunctionCalls(text) {
|
|
170
|
+
const content = [];
|
|
171
|
+
const xmlToolRegex = /<function=(\w+)>([\s\S]*?)<\/function>/g;
|
|
172
|
+
const paramRegex = /<parameter=(\w+)>([\s\S]*?)<\/parameter>/g;
|
|
173
|
+
let lastIndex = 0;
|
|
174
|
+
let match;
|
|
175
|
+
let foundToolCalls = false;
|
|
176
|
+
while ((match = xmlToolRegex.exec(text)) !== null) {
|
|
177
|
+
foundToolCalls = true;
|
|
178
|
+
if (match.index > lastIndex) {
|
|
179
|
+
const before = text.slice(lastIndex, match.index).trim();
|
|
180
|
+
if (before)
|
|
181
|
+
content.push({ type: 'text', text: before });
|
|
182
|
+
}
|
|
183
|
+
const toolName = match[1];
|
|
184
|
+
const paramsBlock = match[2];
|
|
185
|
+
const input = {};
|
|
186
|
+
let paramMatch;
|
|
187
|
+
while ((paramMatch = paramRegex.exec(paramsBlock)) !== null) {
|
|
188
|
+
input[paramMatch[1]] = paramMatch[2].trim();
|
|
189
|
+
}
|
|
190
|
+
paramRegex.lastIndex = 0;
|
|
191
|
+
content.push({
|
|
192
|
+
type: 'tool_use',
|
|
193
|
+
id: generateToolId(),
|
|
194
|
+
name: toolName,
|
|
195
|
+
input,
|
|
196
|
+
});
|
|
197
|
+
lastIndex = match.index + match[0].length;
|
|
198
|
+
}
|
|
199
|
+
if (foundToolCalls && lastIndex < text.length) {
|
|
200
|
+
const remainder = text.slice(lastIndex).trim();
|
|
201
|
+
if (remainder)
|
|
202
|
+
content.push({ type: 'text', text: remainder });
|
|
203
|
+
}
|
|
204
|
+
return foundToolCalls ? content : [];
|
|
205
|
+
}
|
|
206
|
+
// ---------------------------------------------------------------------------
|
|
207
|
+
// Strategy 3: <invoke name="..."> format (MiniMax/Kimi style)
|
|
208
|
+
// ---------------------------------------------------------------------------
|
|
209
|
+
function parseInvokeCalls(text) {
|
|
210
|
+
const content = [];
|
|
211
|
+
const invokeRegex = /<invoke\s+name="([^"]+)">((?:.|\n)*?)<\/invoke>/g;
|
|
212
|
+
const invokeParamRegex = /<parameter\s+name="([^"]+)">((?:.|\n)*?)<\/parameter>/g;
|
|
213
|
+
let lastIndex = 0;
|
|
214
|
+
let match;
|
|
215
|
+
let foundToolCalls = false;
|
|
216
|
+
while ((match = invokeRegex.exec(text)) !== null) {
|
|
217
|
+
foundToolCalls = true;
|
|
218
|
+
if (match.index > lastIndex) {
|
|
219
|
+
const before = text.slice(lastIndex, match.index).trim();
|
|
220
|
+
// Strip wrapper tags like <minimax:tool_call>
|
|
221
|
+
const cleaned = before.replace(/<\/?[\w:]+>/g, '').trim();
|
|
222
|
+
if (cleaned)
|
|
223
|
+
content.push({ type: 'text', text: cleaned });
|
|
224
|
+
}
|
|
225
|
+
const toolName = match[1];
|
|
226
|
+
const paramsBlock = match[2];
|
|
227
|
+
const input = {};
|
|
228
|
+
let paramMatch;
|
|
229
|
+
while ((paramMatch = invokeParamRegex.exec(paramsBlock)) !== null) {
|
|
230
|
+
input[paramMatch[1]] = paramMatch[2].trim();
|
|
231
|
+
}
|
|
232
|
+
invokeParamRegex.lastIndex = 0;
|
|
233
|
+
content.push({
|
|
234
|
+
type: 'tool_use',
|
|
235
|
+
id: generateToolId(),
|
|
236
|
+
name: toolName,
|
|
237
|
+
input,
|
|
238
|
+
});
|
|
239
|
+
lastIndex = match.index + match[0].length;
|
|
240
|
+
}
|
|
241
|
+
if (foundToolCalls) {
|
|
242
|
+
if (lastIndex < text.length) {
|
|
243
|
+
const remainder = text.slice(lastIndex).replace(/<\/?[\w:]+>/g, '').trim();
|
|
244
|
+
if (remainder)
|
|
245
|
+
content.push({ type: 'text', text: remainder });
|
|
246
|
+
}
|
|
247
|
+
return content;
|
|
248
|
+
}
|
|
249
|
+
return [];
|
|
250
|
+
}
|
|
251
|
+
// ---------------------------------------------------------------------------
|
|
252
|
+
// JSON parsing utilities
|
|
253
|
+
// ---------------------------------------------------------------------------
|
|
254
|
+
/**
|
|
255
|
+
* Parse multiple JSON objects from a block that may contain:
|
|
256
|
+
* - A single JSON object
|
|
257
|
+
* - A JSON array
|
|
258
|
+
* - One object per line
|
|
259
|
+
* - Comma-separated objects
|
|
260
|
+
*/
|
|
261
|
+
export function parseMultipleJsonObjects(block) {
|
|
262
|
+
const results = [];
|
|
263
|
+
// Try 1: Single JSON object or array
|
|
264
|
+
try {
|
|
265
|
+
const parsed = JSON.parse(block);
|
|
266
|
+
if (parsed && typeof parsed === 'object') {
|
|
267
|
+
if (parsed.name && parsed.arguments) {
|
|
268
|
+
results.push(parsed);
|
|
269
|
+
return results;
|
|
270
|
+
}
|
|
271
|
+
if (Array.isArray(parsed)) {
|
|
272
|
+
for (const item of parsed) {
|
|
273
|
+
if (item?.name && item?.arguments)
|
|
274
|
+
results.push(item);
|
|
275
|
+
}
|
|
276
|
+
if (results.length > 0)
|
|
277
|
+
return results;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
catch {
|
|
282
|
+
// Not valid single JSON — try multi-line
|
|
283
|
+
}
|
|
284
|
+
// Try 2: One JSON object per line
|
|
285
|
+
const lines = block.split('\n');
|
|
286
|
+
for (const line of lines) {
|
|
287
|
+
const trimmed = line.trim();
|
|
288
|
+
if (!trimmed || !trimmed.startsWith('{'))
|
|
289
|
+
continue;
|
|
290
|
+
try {
|
|
291
|
+
const parsed = JSON.parse(trimmed);
|
|
292
|
+
if (parsed?.name && parsed?.arguments) {
|
|
293
|
+
results.push(parsed);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
catch {
|
|
297
|
+
// Try stripping trailing comma
|
|
298
|
+
const noComma = trimmed.replace(/,\s*$/, '');
|
|
299
|
+
try {
|
|
300
|
+
const parsed = JSON.parse(noComma);
|
|
301
|
+
if (parsed?.name && parsed?.arguments) {
|
|
302
|
+
results.push(parsed);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
catch {
|
|
306
|
+
// Skip unparseable
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
return results;
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* Safely parse a JSON string, returning an empty object on failure.
|
|
314
|
+
*/
|
|
315
|
+
function safeParseJson(str) {
|
|
316
|
+
try {
|
|
317
|
+
const parsed = JSON.parse(str);
|
|
318
|
+
return typeof parsed === 'object' && parsed !== null ? parsed : {};
|
|
319
|
+
}
|
|
320
|
+
catch {
|
|
321
|
+
return {};
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
// ---------------------------------------------------------------------------
|
|
325
|
+
// Tool prompt builder (for models without native tool support)
|
|
326
|
+
// ---------------------------------------------------------------------------
|
|
327
|
+
/**
|
|
328
|
+
* Build the tool-call instruction suffix to inject into the system prompt
|
|
329
|
+
* for models that don't support native tool calling.
|
|
330
|
+
*/
|
|
331
|
+
export function buildToolPromptSuffix(tools, options) {
|
|
332
|
+
const toolDescs = tools.map(t => `- ${t.name}: ${t.description}\n Input: ${JSON.stringify(t.inputSchema)}`).join('\n');
|
|
333
|
+
return `\n\nYou have access to the following tools. To use a tool, respond with a JSON block:
|
|
334
|
+
|
|
335
|
+
\`\`\`tool_call
|
|
336
|
+
{"name": "tool_name", "arguments": {"arg1": "value1"}}
|
|
337
|
+
\`\`\`
|
|
338
|
+
|
|
339
|
+
To call MULTIPLE tools, use one JSON object per line inside a single \`\`\`tool_call block:
|
|
340
|
+
|
|
341
|
+
\`\`\`tool_call
|
|
342
|
+
{"name": "tool1", "arguments": {"arg": "val"}}
|
|
343
|
+
{"name": "tool2", "arguments": {"arg": "val"}}
|
|
344
|
+
\`\`\`
|
|
345
|
+
|
|
346
|
+
Available tools:
|
|
347
|
+
${toolDescs}
|
|
348
|
+
|
|
349
|
+
IMPORTANT: Use ONLY the \`\`\`tool_call JSON format shown above. Do NOT use XML, <invoke>, <function>, or any other format for tool calls.
|
|
350
|
+
Always use tools when you need to interact with the filesystem or run commands.
|
|
351
|
+
After receiving a tool result, continue your analysis.${options?.strict ? `
|
|
352
|
+
|
|
353
|
+
CRITICAL: When calling tools, output ONLY the tool call format. Do not include explanatory text, reasoning, or commentary before or after tool calls. Tool calls must use the exact argument types specified in the schema (numbers as numbers, booleans as booleans, not strings).` : ''}`;
|
|
354
|
+
}
|
|
355
|
+
//# sourceMappingURL=tool-parsing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-parsing.js","sourceRoot":"","sources":["../../../../src/llm/shared/tool-parsing.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool call validation layer using Zod schemas.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors Claude Code's approach: every tool call is validated through its
|
|
5
|
+
* registered Zod schema before execution. Malformed calls are rejected
|
|
6
|
+
* early with clear error messages to the model, enabling retry with
|
|
7
|
+
* corrected format.
|
|
8
|
+
*/
|
|
9
|
+
import { z, type ZodSchema } from 'zod';
|
|
10
|
+
import type { ToolUseBlock } from '../../core/types.js';
|
|
11
|
+
/**
|
|
12
|
+
* Schema for a single parsed tool call object.
|
|
13
|
+
* All parsed tool calls (from native API, JSON text, XML text) must conform to this.
|
|
14
|
+
*/
|
|
15
|
+
export declare const ToolCallSchema: z.ZodObject<{
|
|
16
|
+
name: z.ZodString;
|
|
17
|
+
arguments: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
18
|
+
}, "strip", z.ZodTypeAny, {
|
|
19
|
+
name: string;
|
|
20
|
+
arguments: Record<string, unknown>;
|
|
21
|
+
}, {
|
|
22
|
+
name: string;
|
|
23
|
+
arguments?: Record<string, unknown> | undefined;
|
|
24
|
+
}>;
|
|
25
|
+
export type ParsedToolCall = z.infer<typeof ToolCallSchema>;
|
|
26
|
+
/**
|
|
27
|
+
* Validate a raw parsed tool call against the canonical schema.
|
|
28
|
+
* Returns a normalized tool call or validation errors.
|
|
29
|
+
*/
|
|
30
|
+
export declare function validateToolCallShape(raw: unknown): {
|
|
31
|
+
ok: true;
|
|
32
|
+
toolCall: ParsedToolCall;
|
|
33
|
+
} | {
|
|
34
|
+
ok: false;
|
|
35
|
+
errors: string[];
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Validate a tool call's arguments against the tool's registered Zod input schema.
|
|
39
|
+
* Returns { ok: true, parsed } or { ok: false, message } with a corrective hint.
|
|
40
|
+
*/
|
|
41
|
+
export declare function validateToolInput(toolName: string, args: Record<string, unknown>, inputSchema: ZodSchema): {
|
|
42
|
+
ok: true;
|
|
43
|
+
parsed: unknown;
|
|
44
|
+
} | {
|
|
45
|
+
ok: false;
|
|
46
|
+
message: string;
|
|
47
|
+
};
|
|
48
|
+
export interface ValidatedToolCall {
|
|
49
|
+
readonly id: string;
|
|
50
|
+
readonly name: string;
|
|
51
|
+
readonly input: Record<string, unknown>;
|
|
52
|
+
readonly rawInput: Record<string, unknown>;
|
|
53
|
+
}
|
|
54
|
+
export interface RejectedToolCall {
|
|
55
|
+
readonly id: string;
|
|
56
|
+
readonly name: string;
|
|
57
|
+
readonly error: string;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Validate a batch of tool use blocks against registered tool definitions.
|
|
61
|
+
* Separates valid tool calls from rejected ones with clear error messages.
|
|
62
|
+
*
|
|
63
|
+
* Mirrors Claude Code's flow: Zod input validation → tool-specific validateInput → execute
|
|
64
|
+
*/
|
|
65
|
+
export declare function validateToolCallBatch(toolUseBlocks: ToolUseBlock[], toolLookup: Map<string, {
|
|
66
|
+
inputSchema: ZodSchema;
|
|
67
|
+
}>, availableToolNames: Set<string>): {
|
|
68
|
+
valid: ValidatedToolCall[];
|
|
69
|
+
rejected: RejectedToolCall[];
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* Detect if text contains leaked tool call formatting.
|
|
73
|
+
* When a model outputs tool call syntax in its text response instead of
|
|
74
|
+
* through the proper tool calling mechanism, we detect it here so the
|
|
75
|
+
* parser can try to extract valid tool calls from it.
|
|
76
|
+
*/
|
|
77
|
+
export declare function detectToolCallLeakage(text: string): boolean;
|
|
78
|
+
/**
|
|
79
|
+
* Build a corrective system message to send back to the model
|
|
80
|
+
* when tool call leakage is detected.
|
|
81
|
+
*/
|
|
82
|
+
export declare function buildLeakageCorrectionPrompt(): string;
|
|
83
|
+
//# sourceMappingURL=tool-call-schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-call-schema.d.ts","sourceRoot":"","sources":["../../../../src/llm/validation/tool-call-schema.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,CAAC,EAAE,KAAK,SAAS,EAAiB,MAAM,KAAK,CAAA;AACtD,OAAO,KAAK,EAAc,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAMnE;;;GAGG;AACH,eAAO,MAAM,cAAc;;;;;;;;;EAGzB,CAAA;AAEF,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAA;AAE3D;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,GAAG;IACnD,EAAE,EAAE,IAAI,CAAA;IACR,QAAQ,EAAE,cAAc,CAAA;CACzB,GAAG;IACF,EAAE,EAAE,KAAK,CAAA;IACT,MAAM,EAAE,MAAM,EAAE,CAAA;CACjB,CASA;AAMD;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,WAAW,EAAE,SAAS,GACrB;IACD,EAAE,EAAE,IAAI,CAAA;IACR,MAAM,EAAE,OAAO,CAAA;CAChB,GAAG;IACF,EAAE,EAAE,KAAK,CAAA;IACT,OAAO,EAAE,MAAM,CAAA;CAChB,CASA;AAsBD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACvC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAC3C;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACvB;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,aAAa,EAAE,YAAY,EAAE,EAC7B,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE;IAAE,WAAW,EAAE,SAAS,CAAA;CAAE,CAAC,EACnD,kBAAkB,EAAE,GAAG,CAAC,MAAM,CAAC,GAC9B;IACD,KAAK,EAAE,iBAAiB,EAAE,CAAA;IAC1B,QAAQ,EAAE,gBAAgB,EAAE,CAAA;CAC7B,CA6CA;AAoBD;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE3D;AAED;;;GAGG;AACH,wBAAgB,4BAA4B,IAAI,MAAM,CAMrD"}
|