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,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Retry policy — configures when and how to retry failed tool calls.
|
|
3
|
+
*
|
|
4
|
+
* Produces correction messages that tell the model exactly what went wrong
|
|
5
|
+
* and how to fix it, enabling the repair-retry loop in agent-runner.
|
|
6
|
+
*/
|
|
7
|
+
import { buildLeakageCorrectionPrompt } from '../validation/tool-call-schema.js';
|
|
8
|
+
/** Default retry policy for unknown/reliable models. */
|
|
9
|
+
export const DEFAULT_RETRY_POLICY = {
|
|
10
|
+
maxRetries: 0,
|
|
11
|
+
attemptRepair: false,
|
|
12
|
+
correctionStyle: 'gentle',
|
|
13
|
+
};
|
|
14
|
+
/** Retry policy for models known to produce messy tool calls (Kimi, MiniMax, etc.). */
|
|
15
|
+
export const STRICT_RETRY_POLICY = {
|
|
16
|
+
maxRetries: 2,
|
|
17
|
+
attemptRepair: true,
|
|
18
|
+
correctionStyle: 'strict',
|
|
19
|
+
};
|
|
20
|
+
/** Retry policy for moderately reliable models. */
|
|
21
|
+
export const MODERATE_RETRY_POLICY = {
|
|
22
|
+
maxRetries: 1,
|
|
23
|
+
attemptRepair: true,
|
|
24
|
+
correctionStyle: 'gentle',
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Determine whether to retry after a tool call failure.
|
|
28
|
+
*/
|
|
29
|
+
export function shouldRetry(attempt, policy, errorType) {
|
|
30
|
+
if (attempt >= policy.maxRetries) {
|
|
31
|
+
return { shouldRetry: false, reason: `Max retries (${policy.maxRetries}) exhausted` };
|
|
32
|
+
}
|
|
33
|
+
// Always retry leakage — model is trying to use tools but in the wrong format
|
|
34
|
+
if (errorType === 'leakage') {
|
|
35
|
+
return { shouldRetry: true, reason: 'Tool call leaked into text output' };
|
|
36
|
+
}
|
|
37
|
+
// Retry validation errors if policy allows
|
|
38
|
+
if (errorType === 'validation' && policy.maxRetries > 0) {
|
|
39
|
+
return { shouldRetry: true, reason: 'Tool call failed validation' };
|
|
40
|
+
}
|
|
41
|
+
// Retry unknown tools if policy allows (model may have misspelled)
|
|
42
|
+
if (errorType === 'unknown_tool' && policy.maxRetries > 0) {
|
|
43
|
+
return { shouldRetry: true, reason: 'Unknown tool name — may be misspelled' };
|
|
44
|
+
}
|
|
45
|
+
return { shouldRetry: false, reason: 'No retry policy for this error type' };
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Build correction messages to inject into the conversation before retrying.
|
|
49
|
+
* These tell the model exactly what went wrong and how to fix it.
|
|
50
|
+
*/
|
|
51
|
+
export function buildCorrectionMessages(ctx, policy) {
|
|
52
|
+
const messages = [];
|
|
53
|
+
if (ctx.isLeakage) {
|
|
54
|
+
// Leakage: model outputted tool format in text instead of proper API
|
|
55
|
+
messages.push({
|
|
56
|
+
role: 'user',
|
|
57
|
+
content: [{ type: 'text', text: buildLeakageCorrectionPrompt() }],
|
|
58
|
+
isMeta: true,
|
|
59
|
+
});
|
|
60
|
+
return messages;
|
|
61
|
+
}
|
|
62
|
+
// Build error summary
|
|
63
|
+
const errorLines = ctx.errors.map(e => `- Tool "${e.name}": ${e.error}`).join('\n');
|
|
64
|
+
const toolList = ctx.availableTools.join(', ');
|
|
65
|
+
const gentle = [
|
|
66
|
+
`Your previous tool call(s) had issues:\n${errorLines}`,
|
|
67
|
+
`Available tools: ${toolList}`,
|
|
68
|
+
'Please retry with corrected tool calls.',
|
|
69
|
+
].join('\n\n');
|
|
70
|
+
const strict = [
|
|
71
|
+
`ERROR: Your tool call(s) failed validation. This is attempt ${ctx.attempt + 1}.`,
|
|
72
|
+
`Issues:\n${errorLines}`,
|
|
73
|
+
`You MUST use one of these exact tool names: ${toolList}`,
|
|
74
|
+
'Respond with ONLY a valid tool call. Do not include explanatory text.',
|
|
75
|
+
'Use the exact argument types specified in the tool schema.',
|
|
76
|
+
].join('\n\n');
|
|
77
|
+
const text = policy.correctionStyle === 'strict' ? strict : gentle;
|
|
78
|
+
messages.push({
|
|
79
|
+
role: 'user',
|
|
80
|
+
content: [{ type: 'text', text }],
|
|
81
|
+
isMeta: true,
|
|
82
|
+
});
|
|
83
|
+
return messages;
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=retry-policy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry-policy.js","sourceRoot":"","sources":["../../../../src/llm/repair/retry-policy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool repair module — attempts to fix malformed tool calls before giving up.
|
|
3
|
+
*
|
|
4
|
+
* Strategies (applied in order):
|
|
5
|
+
* A. Strip surrounding text, re-extract JSON
|
|
6
|
+
* B. Fix common JSON issues (trailing commas, unquoted keys, partial brackets)
|
|
7
|
+
* C. Fuzzy-match partial tool names to closest registered tool
|
|
8
|
+
* D. Coerce argument types ("true" → true, "42" → 42) per Zod schema
|
|
9
|
+
*
|
|
10
|
+
* If any strategy produces a valid tool call, it's returned immediately.
|
|
11
|
+
* If none succeed, null is returned → caller should retry or give up.
|
|
12
|
+
*/
|
|
13
|
+
import type { ZodSchema } from 'zod';
|
|
14
|
+
import { type ParsedToolCall } from '../validation/tool-call-schema.js';
|
|
15
|
+
export interface RepairContext {
|
|
16
|
+
/** Names of all registered tools. */
|
|
17
|
+
readonly availableTools: readonly string[];
|
|
18
|
+
/** Registered Zod input schemas, keyed by tool name. */
|
|
19
|
+
readonly toolSchemas: ReadonlyMap<string, ZodSchema>;
|
|
20
|
+
}
|
|
21
|
+
export interface RepairResult {
|
|
22
|
+
readonly repaired: ParsedToolCall[];
|
|
23
|
+
/** Human-readable description of what was fixed. */
|
|
24
|
+
readonly fixes: string[];
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Attempt to repair a set of rejected tool calls.
|
|
28
|
+
*
|
|
29
|
+
* @param rawText The full LLM output text that contained the failed tool calls.
|
|
30
|
+
* @param rejected The tool calls that failed validation, with error details.
|
|
31
|
+
* @param context Available tool names and schemas for fuzzy matching + type coercion.
|
|
32
|
+
* @returns Repaired tool calls, or null if repair failed entirely.
|
|
33
|
+
*/
|
|
34
|
+
export declare function attemptRepair(rawText: string, rejected: Array<{
|
|
35
|
+
name: string;
|
|
36
|
+
arguments: Record<string, unknown>;
|
|
37
|
+
error: string;
|
|
38
|
+
}>, context: RepairContext): RepairResult | null;
|
|
39
|
+
//# sourceMappingURL=tool-repair.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-repair.d.ts","sourceRoot":"","sources":["../../../../src/llm/repair/tool-repair.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAyB,MAAM,KAAK,CAAA;AAC3D,OAAO,EAAyB,KAAK,cAAc,EAAE,MAAM,mCAAmC,CAAA;AAM9F,MAAM,WAAW,aAAa;IAC5B,qCAAqC;IACrC,QAAQ,CAAC,cAAc,EAAE,SAAS,MAAM,EAAE,CAAA;IAC1C,wDAAwD;IACxD,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;CACrD;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,QAAQ,EAAE,cAAc,EAAE,CAAA;IACnC,oDAAoD;IACpD,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CACzB;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,EACpF,OAAO,EAAE,aAAa,GACrB,YAAY,GAAG,IAAI,CAuDrB"}
|
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool repair module — attempts to fix malformed tool calls before giving up.
|
|
3
|
+
*
|
|
4
|
+
* Strategies (applied in order):
|
|
5
|
+
* A. Strip surrounding text, re-extract JSON
|
|
6
|
+
* B. Fix common JSON issues (trailing commas, unquoted keys, partial brackets)
|
|
7
|
+
* C. Fuzzy-match partial tool names to closest registered tool
|
|
8
|
+
* D. Coerce argument types ("true" → true, "42" → 42) per Zod schema
|
|
9
|
+
*
|
|
10
|
+
* If any strategy produces a valid tool call, it's returned immediately.
|
|
11
|
+
* If none succeed, null is returned → caller should retry or give up.
|
|
12
|
+
*/
|
|
13
|
+
import { validateToolCallShape } from '../validation/tool-call-schema.js';
|
|
14
|
+
/**
|
|
15
|
+
* Attempt to repair a set of rejected tool calls.
|
|
16
|
+
*
|
|
17
|
+
* @param rawText The full LLM output text that contained the failed tool calls.
|
|
18
|
+
* @param rejected The tool calls that failed validation, with error details.
|
|
19
|
+
* @param context Available tool names and schemas for fuzzy matching + type coercion.
|
|
20
|
+
* @returns Repaired tool calls, or null if repair failed entirely.
|
|
21
|
+
*/
|
|
22
|
+
export function attemptRepair(rawText, rejected, context) {
|
|
23
|
+
const repaired = [];
|
|
24
|
+
const fixes = [];
|
|
25
|
+
for (const call of rejected) {
|
|
26
|
+
// Strategy C: Fuzzy-match tool name
|
|
27
|
+
let toolName = call.name;
|
|
28
|
+
const nameFixed = fuzzyMatchToolName(toolName, context.availableTools);
|
|
29
|
+
if (nameFixed && nameFixed !== toolName) {
|
|
30
|
+
fixes.push(`Fixed tool name: "${toolName}" → "${nameFixed}"`);
|
|
31
|
+
toolName = nameFixed;
|
|
32
|
+
}
|
|
33
|
+
// Strategy D: Type coercion per Zod schema
|
|
34
|
+
let args = { ...call.arguments };
|
|
35
|
+
const schema = context.toolSchemas.get(toolName);
|
|
36
|
+
if (schema) {
|
|
37
|
+
const coerced = coerceArgumentTypes(args, schema);
|
|
38
|
+
if (coerced.fixed) {
|
|
39
|
+
args = coerced.args;
|
|
40
|
+
fixes.push(...coerced.fixes);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
// Validate after fixes
|
|
44
|
+
const validation = validateToolCallShape({ name: toolName, arguments: args });
|
|
45
|
+
if (validation.ok) {
|
|
46
|
+
// Double-check input schema if available
|
|
47
|
+
if (schema) {
|
|
48
|
+
const result = schema.safeParse(args);
|
|
49
|
+
if (result.success) {
|
|
50
|
+
repaired.push({ name: toolName, arguments: result.data });
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
repaired.push(validation.toolCall);
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// Strategy A+B: Re-extract from raw text if per-call repair failed
|
|
61
|
+
if (repaired.length < rejected.length && rawText) {
|
|
62
|
+
const extracted = extractFromRawText(rawText, context);
|
|
63
|
+
if (extracted.length > 0) {
|
|
64
|
+
fixes.push(`Re-extracted ${extracted.length} tool call(s) from raw output`);
|
|
65
|
+
for (const tc of extracted) {
|
|
66
|
+
if (!repaired.some(r => r.name === tc.name)) {
|
|
67
|
+
repaired.push(tc);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return repaired.length > 0 ? { repaired, fixes } : null;
|
|
73
|
+
}
|
|
74
|
+
// ---------------------------------------------------------------------------
|
|
75
|
+
// Strategy A: Re-extract JSON from raw text
|
|
76
|
+
// ---------------------------------------------------------------------------
|
|
77
|
+
function extractFromRawText(text, context) {
|
|
78
|
+
const results = [];
|
|
79
|
+
// Strip markdown code fences and try to find JSON objects
|
|
80
|
+
const stripped = text
|
|
81
|
+
.replace(/```(?:json|tool_call)?\s*\n?/g, '')
|
|
82
|
+
.replace(/```/g, '');
|
|
83
|
+
// Find all JSON-like objects in the text
|
|
84
|
+
const jsonRegex = /\{[^{}]*(?:\{[^{}]*\}[^{}]*)*\}/g;
|
|
85
|
+
let match;
|
|
86
|
+
while ((match = jsonRegex.exec(stripped)) !== null) {
|
|
87
|
+
const candidate = match[0];
|
|
88
|
+
const parsed = tryParseAndRepairJson(candidate);
|
|
89
|
+
if (parsed && parsed.name && typeof parsed.name === 'string') {
|
|
90
|
+
const args = (parsed.arguments ?? parsed.args ?? parsed.params ?? parsed.input ?? {});
|
|
91
|
+
const toolName = fuzzyMatchToolName(parsed.name, context.availableTools) ?? parsed.name;
|
|
92
|
+
const validation = validateToolCallShape({ name: toolName, arguments: args });
|
|
93
|
+
if (validation.ok) {
|
|
94
|
+
results.push(validation.toolCall);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return results;
|
|
99
|
+
}
|
|
100
|
+
// ---------------------------------------------------------------------------
|
|
101
|
+
// Strategy B: Fix common JSON issues
|
|
102
|
+
// ---------------------------------------------------------------------------
|
|
103
|
+
function tryParseAndRepairJson(text) {
|
|
104
|
+
// Try direct parse first
|
|
105
|
+
try {
|
|
106
|
+
const parsed = JSON.parse(text);
|
|
107
|
+
if (typeof parsed === 'object' && parsed !== null)
|
|
108
|
+
return parsed;
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
// Fall through to repairs
|
|
112
|
+
}
|
|
113
|
+
let repaired = text;
|
|
114
|
+
// Fix trailing commas: { "a": 1, }
|
|
115
|
+
repaired = repaired.replace(/,\s*([}\]])/g, '$1');
|
|
116
|
+
// Fix unquoted keys: { name: "value" } → { "name": "value" }
|
|
117
|
+
repaired = repaired.replace(/([{,]\s*)(\w+)\s*:/g, '$1"$2":');
|
|
118
|
+
// Fix single-quoted strings: { 'name': 'value' } → { "name": "value" }
|
|
119
|
+
repaired = repaired.replace(/'([^'\\]*(?:\\.[^'\\]*)*)'/g, '"$1"');
|
|
120
|
+
// Fix missing closing bracket
|
|
121
|
+
const openBraces = (repaired.match(/\{/g) || []).length;
|
|
122
|
+
const closeBraces = (repaired.match(/\}/g) || []).length;
|
|
123
|
+
if (openBraces > closeBraces) {
|
|
124
|
+
repaired += '}'.repeat(openBraces - closeBraces);
|
|
125
|
+
}
|
|
126
|
+
// Fix missing closing square bracket in arrays
|
|
127
|
+
const openBrackets = (repaired.match(/\[/g) || []).length;
|
|
128
|
+
const closeBrackets = (repaired.match(/\]/g) || []).length;
|
|
129
|
+
if (openBrackets > closeBrackets) {
|
|
130
|
+
// Insert before last }
|
|
131
|
+
const lastBrace = repaired.lastIndexOf('}');
|
|
132
|
+
if (lastBrace > 0) {
|
|
133
|
+
repaired = repaired.slice(0, lastBrace) + ']'.repeat(openBrackets - closeBrackets) + repaired.slice(lastBrace);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
try {
|
|
137
|
+
const parsed = JSON.parse(repaired);
|
|
138
|
+
if (typeof parsed === 'object' && parsed !== null)
|
|
139
|
+
return parsed;
|
|
140
|
+
}
|
|
141
|
+
catch {
|
|
142
|
+
// Could not repair
|
|
143
|
+
}
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
// ---------------------------------------------------------------------------
|
|
147
|
+
// Strategy C: Fuzzy tool name matching
|
|
148
|
+
// ---------------------------------------------------------------------------
|
|
149
|
+
/**
|
|
150
|
+
* Find the closest registered tool name for a possibly misspelled/partial name.
|
|
151
|
+
* Uses: exact match → case-insensitive → prefix match → Levenshtein distance.
|
|
152
|
+
*/
|
|
153
|
+
function fuzzyMatchToolName(name, available) {
|
|
154
|
+
if (!name || available.length === 0)
|
|
155
|
+
return null;
|
|
156
|
+
// Exact match
|
|
157
|
+
if (available.includes(name))
|
|
158
|
+
return name;
|
|
159
|
+
// Case-insensitive match
|
|
160
|
+
const lower = name.toLowerCase();
|
|
161
|
+
const ciMatch = available.find(t => t.toLowerCase() === lower);
|
|
162
|
+
if (ciMatch)
|
|
163
|
+
return ciMatch;
|
|
164
|
+
// Prefix match (e.g., "file_wr" → "file_write")
|
|
165
|
+
const prefixMatches = available.filter(t => t.toLowerCase().startsWith(lower));
|
|
166
|
+
if (prefixMatches.length === 1)
|
|
167
|
+
return prefixMatches[0];
|
|
168
|
+
// Contains match (e.g., "write" → "file_write")
|
|
169
|
+
const containsMatches = available.filter(t => t.toLowerCase().includes(lower));
|
|
170
|
+
if (containsMatches.length === 1)
|
|
171
|
+
return containsMatches[0];
|
|
172
|
+
// Levenshtein distance (max distance 3 to avoid wild matches)
|
|
173
|
+
let bestMatch = null;
|
|
174
|
+
let bestDist = 4;
|
|
175
|
+
for (const tool of available) {
|
|
176
|
+
const dist = levenshtein(lower, tool.toLowerCase());
|
|
177
|
+
if (dist < bestDist) {
|
|
178
|
+
bestDist = dist;
|
|
179
|
+
bestMatch = tool;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return bestMatch;
|
|
183
|
+
}
|
|
184
|
+
function levenshtein(a, b) {
|
|
185
|
+
const m = a.length;
|
|
186
|
+
const n = b.length;
|
|
187
|
+
// Use single-row optimization for memory efficiency
|
|
188
|
+
const row = Array.from({ length: n + 1 }, (_, i) => i);
|
|
189
|
+
for (let i = 1; i <= m; i++) {
|
|
190
|
+
let prev = i - 1;
|
|
191
|
+
row[0] = i;
|
|
192
|
+
for (let j = 1; j <= n; j++) {
|
|
193
|
+
const cost = a[i - 1] === b[j - 1] ? 0 : 1;
|
|
194
|
+
const val = Math.min(row[j] + 1, // deletion
|
|
195
|
+
row[j - 1] + 1, // insertion
|
|
196
|
+
prev + cost);
|
|
197
|
+
prev = row[j];
|
|
198
|
+
row[j] = val;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
return row[n];
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Coerce argument types to match the tool's Zod schema.
|
|
205
|
+
* Handles: string "true" → boolean, "42" → number, "null" → null.
|
|
206
|
+
*/
|
|
207
|
+
function coerceArgumentTypes(args, schema) {
|
|
208
|
+
const result = { ...args };
|
|
209
|
+
const fixes = [];
|
|
210
|
+
let fixed = false;
|
|
211
|
+
// Extract shape from ZodObject if possible
|
|
212
|
+
const shape = getZodObjectShape(schema);
|
|
213
|
+
if (!shape)
|
|
214
|
+
return { args, fixed: false, fixes };
|
|
215
|
+
for (const [key, value] of Object.entries(args)) {
|
|
216
|
+
const fieldSchema = shape[key];
|
|
217
|
+
if (!fieldSchema)
|
|
218
|
+
continue;
|
|
219
|
+
const expectedType = getZodBaseType(fieldSchema);
|
|
220
|
+
if (!expectedType)
|
|
221
|
+
continue;
|
|
222
|
+
// String → boolean coercion
|
|
223
|
+
if (expectedType === 'boolean' && typeof value === 'string') {
|
|
224
|
+
const lower = value.toLowerCase();
|
|
225
|
+
if (lower === 'true' || lower === 'yes' || lower === '1') {
|
|
226
|
+
result[key] = true;
|
|
227
|
+
fixes.push(`Coerced "${key}": "${value}" → true`);
|
|
228
|
+
fixed = true;
|
|
229
|
+
}
|
|
230
|
+
else if (lower === 'false' || lower === 'no' || lower === '0') {
|
|
231
|
+
result[key] = false;
|
|
232
|
+
fixes.push(`Coerced "${key}": "${value}" → false`);
|
|
233
|
+
fixed = true;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
// String → number coercion
|
|
237
|
+
if (expectedType === 'number' && typeof value === 'string') {
|
|
238
|
+
const num = Number(value);
|
|
239
|
+
if (!isNaN(num) && value.trim() !== '') {
|
|
240
|
+
result[key] = num;
|
|
241
|
+
fixes.push(`Coerced "${key}": "${value}" → ${num}`);
|
|
242
|
+
fixed = true;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
// String → null coercion
|
|
246
|
+
if (expectedType === 'null' && typeof value === 'string') {
|
|
247
|
+
if (value.toLowerCase() === 'null' || value === '') {
|
|
248
|
+
result[key] = null;
|
|
249
|
+
fixes.push(`Coerced "${key}": "${value}" → null`);
|
|
250
|
+
fixed = true;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
// Array string → array coercion (e.g. "[1,2,3]" → [1,2,3])
|
|
254
|
+
if (expectedType === 'array' && typeof value === 'string') {
|
|
255
|
+
try {
|
|
256
|
+
const parsed = JSON.parse(value);
|
|
257
|
+
if (Array.isArray(parsed)) {
|
|
258
|
+
result[key] = parsed;
|
|
259
|
+
fixes.push(`Coerced "${key}": string → array`);
|
|
260
|
+
fixed = true;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
catch {
|
|
264
|
+
// Not valid JSON array
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
return { args: result, fixed, fixes };
|
|
269
|
+
}
|
|
270
|
+
// ---------------------------------------------------------------------------
|
|
271
|
+
// Zod introspection helpers
|
|
272
|
+
// ---------------------------------------------------------------------------
|
|
273
|
+
function getZodObjectShape(schema) {
|
|
274
|
+
try {
|
|
275
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
276
|
+
const def = schema?._def;
|
|
277
|
+
if (def?.typeName === 'ZodObject') {
|
|
278
|
+
return def.shape();
|
|
279
|
+
}
|
|
280
|
+
// Handle ZodEffects wrapping (e.g., .transform(), .refine())
|
|
281
|
+
if (def?.typeName === 'ZodEffects' && def?.schema) {
|
|
282
|
+
return getZodObjectShape(def.schema);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
catch {
|
|
286
|
+
// Schema introspection failed
|
|
287
|
+
}
|
|
288
|
+
return null;
|
|
289
|
+
}
|
|
290
|
+
function getZodBaseType(schema) {
|
|
291
|
+
try {
|
|
292
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
293
|
+
const def = schema?._def;
|
|
294
|
+
const typeName = def?.typeName;
|
|
295
|
+
if (!typeName)
|
|
296
|
+
return null;
|
|
297
|
+
switch (typeName) {
|
|
298
|
+
case 'ZodString': return 'string';
|
|
299
|
+
case 'ZodNumber': return 'number';
|
|
300
|
+
case 'ZodBoolean': return 'boolean';
|
|
301
|
+
case 'ZodNull': return 'null';
|
|
302
|
+
case 'ZodArray': return 'array';
|
|
303
|
+
case 'ZodOptional': return getZodBaseType(def.innerType);
|
|
304
|
+
case 'ZodDefault': return getZodBaseType(def.innerType);
|
|
305
|
+
case 'ZodNullable': return getZodBaseType(def.innerType);
|
|
306
|
+
default: return null;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
catch {
|
|
310
|
+
return null;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
//# sourceMappingURL=tool-repair.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-repair.js","sourceRoot":"","sources":["../../../../src/llm/repair/tool-repair.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pre-parse text cleanup — sanitizes raw LLM output before tool call parsing.
|
|
3
|
+
*
|
|
4
|
+
* Fixes common model artifacts that break JSON/XML parsing:
|
|
5
|
+
* - Markdown code fence wrappers around JSON
|
|
6
|
+
* - Thinking/reasoning tags (<think>, <thought>, etc.)
|
|
7
|
+
* - Control characters
|
|
8
|
+
* - Repeated newlines in JSON
|
|
9
|
+
* - Incomplete/truncated brackets
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Clean raw LLM output text before passing it to tool call parsers.
|
|
13
|
+
* This is a pure function that returns sanitized text — idempotent and safe.
|
|
14
|
+
*/
|
|
15
|
+
export declare function cleanLLMOutput(text: string): string;
|
|
16
|
+
//# sourceMappingURL=text-cleanup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text-cleanup.d.ts","sourceRoot":"","sources":["../../../../src/llm/shared/text-cleanup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAMH;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAmBnD"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pre-parse text cleanup — sanitizes raw LLM output before tool call parsing.
|
|
3
|
+
*
|
|
4
|
+
* Fixes common model artifacts that break JSON/XML parsing:
|
|
5
|
+
* - Markdown code fence wrappers around JSON
|
|
6
|
+
* - Thinking/reasoning tags (<think>, <thought>, etc.)
|
|
7
|
+
* - Control characters
|
|
8
|
+
* - Repeated newlines in JSON
|
|
9
|
+
* - Incomplete/truncated brackets
|
|
10
|
+
*/
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
// Main cleanup function
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
/**
|
|
15
|
+
* Clean raw LLM output text before passing it to tool call parsers.
|
|
16
|
+
* This is a pure function that returns sanitized text — idempotent and safe.
|
|
17
|
+
*/
|
|
18
|
+
export function cleanLLMOutput(text) {
|
|
19
|
+
if (!text)
|
|
20
|
+
return text;
|
|
21
|
+
let cleaned = text;
|
|
22
|
+
// 1. Strip thinking/reasoning tags and their content
|
|
23
|
+
cleaned = stripThinkingTags(cleaned);
|
|
24
|
+
// 2. Strip control characters (except newline, tab, carriage return)
|
|
25
|
+
cleaned = stripControlChars(cleaned);
|
|
26
|
+
// 3. Unwrap bare markdown JSON fences that wrap the entire response
|
|
27
|
+
// (but NOT tool_call fences — those are handled by the parser)
|
|
28
|
+
cleaned = unwrapBareJsonFences(cleaned);
|
|
29
|
+
// 4. Collapse excessive whitespace inside JSON-like structures
|
|
30
|
+
cleaned = collapseJsonWhitespace(cleaned);
|
|
31
|
+
return cleaned;
|
|
32
|
+
}
|
|
33
|
+
// ---------------------------------------------------------------------------
|
|
34
|
+
// Individual cleanup strategies
|
|
35
|
+
// ---------------------------------------------------------------------------
|
|
36
|
+
/**
|
|
37
|
+
* Strip thinking/reasoning tags and their content.
|
|
38
|
+
* Models like Qwen3, DeepSeek emit <think>...</think> blocks.
|
|
39
|
+
*/
|
|
40
|
+
function stripThinkingTags(text) {
|
|
41
|
+
// <think>...</think>
|
|
42
|
+
let cleaned = text.replace(/<think>[\s\S]*?<\/think>/gi, '');
|
|
43
|
+
// <thought>...</thought>
|
|
44
|
+
cleaned = cleaned.replace(/<thought>[\s\S]*?<\/thought>/gi, '');
|
|
45
|
+
// <reasoning>...</reasoning>
|
|
46
|
+
cleaned = cleaned.replace(/<reasoning>[\s\S]*?<\/reasoning>/gi, '');
|
|
47
|
+
// <reflection>...</reflection>
|
|
48
|
+
cleaned = cleaned.replace(/<reflection>[\s\S]*?<\/reflection>/gi, '');
|
|
49
|
+
// Ollama-specific thinking channel markers
|
|
50
|
+
cleaned = cleaned.replace(/<\|channel>thought[\s\S]*?<channel\|>/g, '');
|
|
51
|
+
cleaned = cleaned.replace(/<channel\|>/g, '');
|
|
52
|
+
return cleaned.trim();
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Strip control characters that break JSON parsing.
|
|
56
|
+
* Preserves: \n (0x0A), \r (0x0D), \t (0x09)
|
|
57
|
+
*/
|
|
58
|
+
function stripControlChars(text) {
|
|
59
|
+
// eslint-disable-next-line no-control-regex
|
|
60
|
+
return text.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g, '');
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Unwrap bare JSON code fences that wrap the entire response.
|
|
64
|
+
*
|
|
65
|
+
* Some models wrap their entire tool call in ```json ... ``` instead of
|
|
66
|
+
* using the proper ```tool_call format. We unwrap these to expose the
|
|
67
|
+
* raw JSON for the parser.
|
|
68
|
+
*
|
|
69
|
+
* Does NOT unwrap ```tool_call fences — those are handled by the parser.
|
|
70
|
+
*/
|
|
71
|
+
function unwrapBareJsonFences(text) {
|
|
72
|
+
const trimmed = text.trim();
|
|
73
|
+
// Check if the entire response is a single ```json fence
|
|
74
|
+
const jsonFenceMatch = trimmed.match(/^```(?:json)?\s*\n([\s\S]*?)\n```\s*$/);
|
|
75
|
+
if (jsonFenceMatch) {
|
|
76
|
+
const inner = jsonFenceMatch[1].trim();
|
|
77
|
+
// Only unwrap if the inner content looks like a tool call JSON
|
|
78
|
+
if (isToolCallLike(inner)) {
|
|
79
|
+
// Re-wrap as ```tool_call so the parser picks it up
|
|
80
|
+
return '```tool_call\n' + inner + '\n```';
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return text;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Collapse excessive whitespace inside JSON structures.
|
|
87
|
+
* Some models emit JSON with many blank lines between keys.
|
|
88
|
+
*/
|
|
89
|
+
function collapseJsonWhitespace(text) {
|
|
90
|
+
// Only apply inside ```tool_call blocks to avoid mangling prose
|
|
91
|
+
return text.replace(/```tool_call\s*\n([\s\S]*?)\n```/g, (_match, inner) => {
|
|
92
|
+
const collapsed = inner
|
|
93
|
+
.split('\n')
|
|
94
|
+
.map((line) => line.trimEnd())
|
|
95
|
+
.filter((line, i, arr) => {
|
|
96
|
+
// Remove blank lines between JSON lines, but keep at least one
|
|
97
|
+
if (line === '' && i > 0 && arr[i - 1] === '')
|
|
98
|
+
return false;
|
|
99
|
+
return true;
|
|
100
|
+
})
|
|
101
|
+
.join('\n');
|
|
102
|
+
return '```tool_call\n' + collapsed + '\n```';
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
// ---------------------------------------------------------------------------
|
|
106
|
+
// Helpers
|
|
107
|
+
// ---------------------------------------------------------------------------
|
|
108
|
+
/**
|
|
109
|
+
* Heuristic: does this text look like a tool call JSON object?
|
|
110
|
+
*/
|
|
111
|
+
function isToolCallLike(text) {
|
|
112
|
+
const trimmed = text.trim();
|
|
113
|
+
if (!trimmed.startsWith('{'))
|
|
114
|
+
return false;
|
|
115
|
+
// Check for tool call shape indicators
|
|
116
|
+
return ((trimmed.includes('"name"') && trimmed.includes('"arguments"')) ||
|
|
117
|
+
(trimmed.includes('"name"') && trimmed.includes('"args"')) ||
|
|
118
|
+
(trimmed.includes('"function"') && trimmed.includes('"arguments"')));
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=text-cleanup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text-cleanup.js","sourceRoot":"","sources":["../../../../src/llm/shared/text-cleanup.ts"],"names":[],"mappings":"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"}
|