@vybestack/llxprt-code-core 0.4.7 → 0.5.0-nightly.251102.6bb3db7a
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/prompt-config/defaults/default-prompts.json +4 -17
- package/dist/src/auth/precedence.d.ts +69 -9
- package/dist/src/auth/precedence.js +467 -69
- package/dist/src/auth/precedence.js.map +1 -1
- package/dist/src/auth/types.d.ts +2 -2
- package/dist/src/config/config.d.ts +18 -1
- package/dist/src/config/config.js +123 -6
- package/dist/src/config/config.js.map +1 -1
- package/dist/src/config/index.d.ts +6 -0
- package/dist/src/config/index.js +5 -0
- package/dist/src/config/index.js.map +1 -1
- package/dist/src/config/profileManager.d.ts +23 -3
- package/dist/src/config/profileManager.js +54 -7
- package/dist/src/config/profileManager.js.map +1 -1
- package/dist/src/config/subagentManager.d.ts +96 -0
- package/dist/src/config/subagentManager.js +371 -0
- package/dist/src/config/subagentManager.js.map +1 -0
- package/dist/src/config/types.d.ts +18 -0
- package/dist/src/config/types.js +3 -0
- package/dist/src/config/types.js.map +1 -0
- package/dist/src/core/client.d.ts +27 -7
- package/dist/src/core/client.js +235 -56
- package/dist/src/core/client.js.map +1 -1
- package/dist/src/core/contentGenerator.d.ts +3 -1
- package/dist/src/core/contentGenerator.js +3 -0
- package/dist/src/core/contentGenerator.js.map +1 -1
- package/dist/src/core/coreToolScheduler.d.ts +1 -5
- package/dist/src/core/coreToolScheduler.js +95 -23
- package/dist/src/core/coreToolScheduler.js.map +1 -1
- package/dist/src/core/geminiChat.d.ts +42 -12
- package/dist/src/core/geminiChat.js +413 -207
- package/dist/src/core/geminiChat.js.map +1 -1
- package/dist/src/core/nonInteractiveToolExecutor.d.ts +3 -2
- package/dist/src/core/nonInteractiveToolExecutor.js +94 -10
- package/dist/src/core/nonInteractiveToolExecutor.js.map +1 -1
- package/dist/src/core/subagent.d.ts +86 -7
- package/dist/src/core/subagent.js +809 -79
- package/dist/src/core/subagent.js.map +1 -1
- package/dist/src/core/subagentOrchestrator.d.ts +73 -0
- package/dist/src/core/subagentOrchestrator.js +383 -0
- package/dist/src/core/subagentOrchestrator.js.map +1 -0
- package/dist/src/core/subagentScheduler.d.ts +16 -0
- package/dist/src/core/subagentScheduler.js +7 -0
- package/dist/src/core/subagentScheduler.js.map +1 -0
- package/dist/src/core/turn.d.ts +5 -1
- package/dist/src/core/turn.js +5 -1
- package/dist/src/core/turn.js.map +1 -1
- package/dist/src/hooks/tool-render-suppression-hook.js +6 -1
- package/dist/src/hooks/tool-render-suppression-hook.js.map +1 -1
- package/dist/src/ide/ideContext.d.ts +32 -32
- package/dist/src/index.d.ts +19 -1
- package/dist/src/index.js +15 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/interfaces/index.d.ts +1 -0
- package/dist/src/interfaces/index.js +4 -0
- package/dist/src/interfaces/index.js.map +1 -0
- package/dist/src/interfaces/nodejs-error.interface.d.ts +4 -0
- package/dist/src/interfaces/nodejs-error.interface.js +2 -0
- package/dist/src/interfaces/nodejs-error.interface.js.map +1 -0
- package/dist/src/parsers/TextToolCallParser.d.ts +17 -1
- package/dist/src/parsers/TextToolCallParser.js +542 -148
- package/dist/src/parsers/TextToolCallParser.js.map +1 -1
- package/dist/src/prompt-config/defaults/core.md +15 -0
- package/dist/src/prompt-config/defaults/providers/gemini/core.md +203 -119
- package/dist/src/prompt-config/defaults/tool-defaults.js +2 -0
- package/dist/src/prompt-config/defaults/tool-defaults.js.map +1 -1
- package/dist/src/prompt-config/defaults/tools/list-subagents.md +7 -0
- package/dist/src/prompt-config/defaults/tools/task.md +8 -0
- package/dist/src/providers/BaseProvider.d.ts +115 -30
- package/dist/src/providers/BaseProvider.js +445 -109
- package/dist/src/providers/BaseProvider.js.map +1 -1
- package/dist/src/providers/IProvider.d.ts +50 -18
- package/dist/src/providers/LoggingProviderWrapper.d.ts +60 -16
- package/dist/src/providers/LoggingProviderWrapper.js +213 -60
- package/dist/src/providers/LoggingProviderWrapper.js.map +1 -1
- package/dist/src/providers/ProviderManager.d.ts +73 -2
- package/dist/src/providers/ProviderManager.js +492 -40
- package/dist/src/providers/ProviderManager.js.map +1 -1
- package/dist/src/providers/anthropic/AnthropicProvider.d.ts +35 -38
- package/dist/src/providers/anthropic/AnthropicProvider.js +222 -227
- package/dist/src/providers/anthropic/AnthropicProvider.js.map +1 -1
- package/dist/src/providers/errors.d.ts +86 -0
- package/dist/src/providers/errors.js +89 -0
- package/dist/src/providers/errors.js.map +1 -1
- package/dist/src/providers/gemini/GeminiProvider.d.ts +101 -41
- package/dist/src/providers/gemini/GeminiProvider.js +386 -311
- package/dist/src/providers/gemini/GeminiProvider.js.map +1 -1
- package/dist/src/providers/openai/ConversationCache.d.ts +5 -3
- package/dist/src/providers/openai/ConversationCache.js +93 -32
- package/dist/src/providers/openai/ConversationCache.js.map +1 -1
- package/dist/src/providers/openai/OpenAIProvider.d.ts +82 -42
- package/dist/src/providers/openai/OpenAIProvider.js +392 -457
- package/dist/src/providers/openai/OpenAIProvider.js.map +1 -1
- package/dist/src/providers/openai/getOpenAIProviderInfo.d.ts +1 -1
- package/dist/src/providers/openai/getOpenAIProviderInfo.js +52 -22
- package/dist/src/providers/openai/getOpenAIProviderInfo.js.map +1 -1
- package/dist/src/providers/openai/openaiRequestParams.d.ts +7 -0
- package/dist/src/providers/openai/openaiRequestParams.js +66 -0
- package/dist/src/providers/openai/openaiRequestParams.js.map +1 -0
- package/dist/src/providers/openai-responses/OpenAIResponsesProvider.d.ts +6 -33
- package/dist/src/providers/openai-responses/OpenAIResponsesProvider.js +84 -183
- package/dist/src/providers/openai-responses/OpenAIResponsesProvider.js.map +1 -1
- package/dist/src/providers/types/providerRuntime.d.ts +17 -0
- package/dist/src/providers/types/providerRuntime.js +7 -0
- package/dist/src/providers/types/providerRuntime.js.map +1 -0
- package/dist/src/providers/utils/authToken.d.ts +12 -0
- package/dist/src/providers/utils/authToken.js +17 -0
- package/dist/src/providers/utils/authToken.js.map +1 -0
- package/dist/src/providers/utils/userMemory.d.ts +8 -0
- package/dist/src/providers/utils/userMemory.js +34 -0
- package/dist/src/providers/utils/userMemory.js.map +1 -0
- package/dist/src/runtime/AgentRuntimeContext.d.ts +213 -0
- package/dist/src/runtime/AgentRuntimeContext.js +17 -0
- package/dist/src/runtime/AgentRuntimeContext.js.map +1 -0
- package/dist/src/runtime/AgentRuntimeLoader.d.ts +47 -0
- package/dist/src/runtime/AgentRuntimeLoader.js +122 -0
- package/dist/src/runtime/AgentRuntimeLoader.js.map +1 -0
- package/dist/src/runtime/AgentRuntimeState.d.ts +232 -0
- package/dist/src/runtime/AgentRuntimeState.js +439 -0
- package/dist/src/runtime/AgentRuntimeState.js.map +1 -0
- package/dist/src/runtime/RuntimeInvocationContext.d.ts +51 -0
- package/dist/src/runtime/RuntimeInvocationContext.js +52 -0
- package/dist/src/runtime/RuntimeInvocationContext.js.map +1 -0
- package/dist/src/runtime/createAgentRuntimeContext.d.ts +7 -0
- package/dist/src/runtime/createAgentRuntimeContext.js +65 -0
- package/dist/src/runtime/createAgentRuntimeContext.js.map +1 -0
- package/dist/src/runtime/index.d.ts +13 -0
- package/dist/src/runtime/index.js +14 -0
- package/dist/src/runtime/index.js.map +1 -0
- package/dist/src/runtime/providerRuntimeContext.d.ts +30 -0
- package/dist/src/runtime/providerRuntimeContext.js +70 -0
- package/dist/src/runtime/providerRuntimeContext.js.map +1 -0
- package/dist/src/runtime/runtimeAdapters.d.ts +22 -0
- package/dist/src/runtime/runtimeAdapters.js +81 -0
- package/dist/src/runtime/runtimeAdapters.js.map +1 -0
- package/dist/src/runtime/runtimeStateFactory.d.ts +21 -0
- package/dist/src/runtime/runtimeStateFactory.js +104 -0
- package/dist/src/runtime/runtimeStateFactory.js.map +1 -0
- package/dist/src/services/history/ContentConverters.js +3 -5
- package/dist/src/services/history/ContentConverters.js.map +1 -1
- package/dist/src/services/shellExecutionService.js +2 -2
- package/dist/src/services/shellExecutionService.js.map +1 -1
- package/dist/src/services/todo-context-tracker.d.ts +10 -8
- package/dist/src/services/todo-context-tracker.js +26 -10
- package/dist/src/services/todo-context-tracker.js.map +1 -1
- package/dist/src/services/tool-call-tracker-service.d.ts +11 -7
- package/dist/src/services/tool-call-tracker-service.js +89 -29
- package/dist/src/services/tool-call-tracker-service.js.map +1 -1
- package/dist/src/settings/SettingsService.d.ts +4 -0
- package/dist/src/settings/SettingsService.js +65 -2
- package/dist/src/settings/SettingsService.js.map +1 -1
- package/dist/src/settings/settingsServiceInstance.d.ts +6 -1
- package/dist/src/settings/settingsServiceInstance.js +28 -8
- package/dist/src/settings/settingsServiceInstance.js.map +1 -1
- package/dist/src/telemetry/loggers.d.ts +5 -1
- package/dist/src/telemetry/loggers.js.map +1 -1
- package/dist/src/telemetry/loggers.test.circular.js +4 -0
- package/dist/src/telemetry/loggers.test.circular.js.map +1 -1
- package/dist/src/telemetry/metrics.d.ts +3 -1
- package/dist/src/telemetry/metrics.js.map +1 -1
- package/dist/src/telemetry/types.d.ts +1 -0
- package/dist/src/telemetry/types.js +3 -0
- package/dist/src/telemetry/types.js.map +1 -1
- package/dist/src/test-utils/index.d.ts +2 -0
- package/dist/src/test-utils/index.js +2 -0
- package/dist/src/test-utils/index.js.map +1 -1
- package/dist/src/test-utils/mockWorkspaceContext.d.ts +0 -3
- package/dist/src/test-utils/mockWorkspaceContext.js +3 -4
- package/dist/src/test-utils/mockWorkspaceContext.js.map +1 -1
- package/dist/src/test-utils/providerCallOptions.d.ts +43 -0
- package/dist/src/test-utils/providerCallOptions.js +137 -0
- package/dist/src/test-utils/providerCallOptions.js.map +1 -0
- package/dist/src/test-utils/runtime.d.ts +92 -0
- package/dist/src/test-utils/runtime.js +226 -0
- package/dist/src/test-utils/runtime.js.map +1 -0
- package/dist/src/test-utils/tools.d.ts +4 -4
- package/dist/src/test-utils/tools.js +20 -10
- package/dist/src/test-utils/tools.js.map +1 -1
- package/dist/src/tools/list-subagents.d.ts +31 -0
- package/dist/src/tools/list-subagents.js +109 -0
- package/dist/src/tools/list-subagents.js.map +1 -0
- package/dist/src/tools/task.d.ts +87 -0
- package/dist/src/tools/task.js +427 -0
- package/dist/src/tools/task.js.map +1 -0
- package/dist/src/tools/todo-read.js +1 -1
- package/dist/src/tools/todo-read.js.map +1 -1
- package/dist/src/tools/todo-store.js +4 -2
- package/dist/src/tools/todo-store.js.map +1 -1
- package/dist/src/tools/todo-write.js +4 -2
- package/dist/src/tools/todo-write.js.map +1 -1
- package/dist/src/tools/tool-error.d.ts +1 -0
- package/dist/src/tools/tool-error.js +1 -0
- package/dist/src/tools/tool-error.js.map +1 -1
- package/dist/src/tools/tool-registry.d.ts +2 -0
- package/dist/src/tools/tool-registry.js +46 -21
- package/dist/src/tools/tool-registry.js.map +1 -1
- package/dist/src/types/modelParams.d.ts +4 -0
- package/dist/src/utils/editor.js +10 -8
- package/dist/src/utils/editor.js.map +1 -1
- package/dist/src/utils/gitIgnoreParser.js +15 -3
- package/dist/src/utils/gitIgnoreParser.js.map +1 -1
- package/dist/src/utils/memoryImportProcessor.js +22 -3
- package/dist/src/utils/memoryImportProcessor.js.map +1 -1
- package/package.json +1 -1
- package/dist/src/prompt-config/defaults/providers/anthropic/core.md +0 -97
- package/dist/src/prompt-config/defaults/providers/anthropic/tools/glob.md +0 -34
- package/dist/src/prompt-config/defaults/providers/anthropic/tools/list-directory.md +0 -11
- package/dist/src/prompt-config/defaults/providers/anthropic/tools/read-file.md +0 -14
- package/dist/src/prompt-config/defaults/providers/anthropic/tools/read-many-files.md +0 -31
- package/dist/src/prompt-config/defaults/providers/anthropic/tools/replace.md +0 -41
- package/dist/src/prompt-config/defaults/providers/anthropic/tools/run-shell-command.md +0 -32
- package/dist/src/prompt-config/defaults/providers/anthropic/tools/save-memory.md +0 -35
- package/dist/src/prompt-config/defaults/providers/anthropic/tools/search-file-content.md +0 -44
- package/dist/src/prompt-config/defaults/providers/anthropic/tools/todo-write.md +0 -45
- package/dist/src/prompt-config/defaults/providers/anthropic/tools/write-file.md +0 -11
- package/dist/src/prompt-config/defaults/providers/openai/core.md +0 -97
- package/dist/src/prompt-config/defaults/providers/openai/tools/todo-pause.md +0 -28
- package/dist/src/prompt-config/defaults/providers/openai/tools/todo-read.md +0 -5
- package/dist/src/prompt-config/defaults/providers/openai/tools/todo-write.md +0 -45
|
@@ -4,25 +4,8 @@
|
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
6
|
export class GemmaToolCallParser {
|
|
7
|
-
|
|
8
|
-
patterns = [
|
|
9
|
-
// Format 1: [TOOL_REQUEST] toolName {args} [TOOL_REQUEST_END]
|
|
10
|
-
/\[TOOL_REQUEST\]\s*(\w+)\s+({.*?})\s*\[TOOL_REQUEST_END\]/gs,
|
|
11
|
-
// Format 2: ✦ tool_call: toolName for key value pairs (more specific to avoid false positives)
|
|
12
|
-
/✦\s*tool_call:\s*(\w+)\s+for\s+(.+?)(?=\n|✦|$)/gs,
|
|
13
|
-
// Format 3: JSON object with name/arguments followed by [END_TOOL_REQUEST]
|
|
14
|
-
/(\d+\s+)?{"name":\s*"(\w+)",\s*"arguments":\s*({.*?})}\s*(?:\n\s*\d+\s+)?\[END_TOOL_REQUEST\]/gs,
|
|
15
|
-
// Format 4: Hermes format with <tool_call> tags
|
|
16
|
-
/<tool_call>\s*({.*?"name":\s*"(\w+)".*?})\s*<\/tool_call>/gs,
|
|
17
|
-
// Format 5: XML with <invoke> tags (Claude-style)
|
|
18
|
-
/<invoke\s+name="(\w+)">(.*?)<\/invoke>/gs,
|
|
19
|
-
// Format 6: Generic XML tool format
|
|
20
|
-
/<tool>\s*<name>(\w+)<\/name>\s*<arguments>(.*?)<\/arguments>\s*<\/tool>/gs,
|
|
21
|
-
];
|
|
7
|
+
keyValuePattern = /✦\s*tool_call:\s*([A-Za-z0-9_.-]+)\s+for\s+([^\n✦]*)/g;
|
|
22
8
|
parse(content) {
|
|
23
|
-
const toolCalls = [];
|
|
24
|
-
let cleanedContent = content;
|
|
25
|
-
const matches = [];
|
|
26
9
|
// Quick check: if content doesn't contain any tool call markers, return early
|
|
27
10
|
if (!content.includes('[TOOL_REQUEST') &&
|
|
28
11
|
!content.includes('tool_call:') &&
|
|
@@ -30,154 +13,449 @@ export class GemmaToolCallParser {
|
|
|
30
13
|
!content.includes('{"name":') &&
|
|
31
14
|
!content.includes('<tool_call>') &&
|
|
32
15
|
!content.includes('<invoke') &&
|
|
33
|
-
!content.includes('<tool>')
|
|
16
|
+
!content.includes('<tool>') &&
|
|
17
|
+
!content.includes('<use ')) {
|
|
34
18
|
return { cleanedContent: content, toolCalls: [] };
|
|
35
19
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
// Format 3: JSON object format {"name": "tool", "arguments": {...}}
|
|
48
|
-
const [fullMatch, , toolName, jsonArgs] = match;
|
|
49
|
-
matches.push({ fullMatch, toolName, args: jsonArgs });
|
|
50
|
-
}
|
|
51
|
-
else if (pattern === this.patterns[3]) {
|
|
52
|
-
// Format 4: Hermes format <tool_call>{"arguments": {...}, "name": "tool"}</tool_call>
|
|
53
|
-
const [fullMatch, hermesJson, toolName] = match;
|
|
54
|
-
try {
|
|
55
|
-
const parsed = JSON.parse(hermesJson);
|
|
56
|
-
matches.push({
|
|
57
|
-
fullMatch,
|
|
58
|
-
toolName,
|
|
59
|
-
args: JSON.stringify(parsed.arguments || {}),
|
|
60
|
-
});
|
|
61
|
-
}
|
|
62
|
-
catch (error) {
|
|
63
|
-
console.error(`[GemmaToolCallParser] Failed to parse Hermes format: ${error}`);
|
|
64
|
-
// Still need to track the match to remove it from content
|
|
65
|
-
matches.push({ fullMatch, toolName: '', args: '' });
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
else if (pattern === this.patterns[4]) {
|
|
69
|
-
// Format 5: XML with <invoke> tags (Claude-style)
|
|
70
|
-
const [fullMatch, toolName, xmlContent] = match;
|
|
71
|
-
matches.push({ fullMatch, toolName, args: xmlContent });
|
|
72
|
-
}
|
|
73
|
-
else if (pattern === this.patterns[5]) {
|
|
74
|
-
// Format 6: Generic XML tool format
|
|
75
|
-
const [fullMatch, toolName, xmlArgs] = match;
|
|
76
|
-
matches.push({ fullMatch, toolName, args: xmlArgs });
|
|
77
|
-
}
|
|
78
|
-
else {
|
|
79
|
-
// Format 1: tool name followed by JSON arguments
|
|
80
|
-
const [fullMatch, toolName, jsonArgs] = match;
|
|
81
|
-
matches.push({ fullMatch, toolName, args: jsonArgs });
|
|
82
|
-
}
|
|
20
|
+
const matches = this.collectMatches(content);
|
|
21
|
+
const toolCalls = [];
|
|
22
|
+
const ranges = [];
|
|
23
|
+
for (const match of matches) {
|
|
24
|
+
ranges.push({ start: match.start, end: match.end });
|
|
25
|
+
if (!match.toolName) {
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
const parsedArgs = this.normalizeArguments(match.rawArgs, match.toolName, match.fullMatch);
|
|
29
|
+
if (!parsedArgs) {
|
|
30
|
+
continue;
|
|
83
31
|
}
|
|
84
|
-
|
|
85
|
-
|
|
32
|
+
toolCalls.push({
|
|
33
|
+
name: match.toolName,
|
|
34
|
+
arguments: parsedArgs,
|
|
35
|
+
});
|
|
86
36
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
37
|
+
const withoutMatches = this.removeMatchedRanges(content, ranges);
|
|
38
|
+
const cleanedContent = this.postProcessCleanedContent(withoutMatches);
|
|
39
|
+
return { cleanedContent, toolCalls };
|
|
40
|
+
}
|
|
41
|
+
collectMatches(content) {
|
|
42
|
+
const matches = [
|
|
43
|
+
...this.findBracketToolRequests(content),
|
|
44
|
+
...this.findJsonToolRequests(content),
|
|
45
|
+
...this.findHermesToolRequests(content),
|
|
46
|
+
...this.findInvokeToolRequests(content),
|
|
47
|
+
...this.findGenericXmlToolRequests(content),
|
|
48
|
+
...this.findUseToolRequests(content),
|
|
49
|
+
...this.findUseUnderscoreToolRequests(content),
|
|
50
|
+
...this.findKeyValueToolRequests(content),
|
|
51
|
+
];
|
|
52
|
+
return matches.sort((a, b) => a.start - b.start);
|
|
53
|
+
}
|
|
54
|
+
findBracketToolRequests(content) {
|
|
55
|
+
const matches = [];
|
|
56
|
+
const startMarker = '[TOOL_REQUEST]';
|
|
57
|
+
const endMarker = '[TOOL_REQUEST_END]';
|
|
58
|
+
let searchIndex = 0;
|
|
59
|
+
while (searchIndex < content.length) {
|
|
60
|
+
const start = content.indexOf(startMarker, searchIndex);
|
|
61
|
+
if (start === -1)
|
|
62
|
+
break;
|
|
63
|
+
const afterStart = start + startMarker.length;
|
|
64
|
+
const endMarkerIndex = content.indexOf(endMarker, afterStart);
|
|
65
|
+
if (endMarkerIndex === -1)
|
|
66
|
+
break;
|
|
67
|
+
const segment = content.slice(afterStart, endMarkerIndex);
|
|
68
|
+
const toolNameMatch = segment.match(/^\s*([^\s{]+)\s+/);
|
|
69
|
+
if (!toolNameMatch) {
|
|
70
|
+
searchIndex = endMarkerIndex + endMarker.length;
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
const toolName = toolNameMatch[1];
|
|
74
|
+
const braceOffset = segment.indexOf('{', toolNameMatch[0].length);
|
|
75
|
+
if (braceOffset === -1) {
|
|
76
|
+
searchIndex = endMarkerIndex + endMarker.length;
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
const jsonStart = afterStart + braceOffset;
|
|
80
|
+
const jsonSegment = this.extractBalancedSegment(content, jsonStart, '{', '}');
|
|
81
|
+
if (!jsonSegment || jsonSegment.endIndex > endMarkerIndex) {
|
|
82
|
+
searchIndex = endMarkerIndex + endMarker.length;
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
const fullEnd = endMarkerIndex + endMarker.length;
|
|
86
|
+
matches.push({
|
|
87
|
+
start,
|
|
88
|
+
end: fullEnd,
|
|
89
|
+
toolName,
|
|
90
|
+
rawArgs: jsonSegment.segment,
|
|
91
|
+
fullMatch: content.slice(start, fullEnd),
|
|
92
|
+
});
|
|
93
|
+
searchIndex = fullEnd;
|
|
94
|
+
}
|
|
95
|
+
return matches;
|
|
96
|
+
}
|
|
97
|
+
findJsonToolRequests(content) {
|
|
98
|
+
const matches = [];
|
|
99
|
+
const marker = '{"name":';
|
|
100
|
+
const endMarker = '[END_TOOL_REQUEST]';
|
|
101
|
+
let searchIndex = 0;
|
|
102
|
+
while (searchIndex < content.length) {
|
|
103
|
+
const candidateIndex = content.indexOf(marker, searchIndex);
|
|
104
|
+
if (candidateIndex === -1) {
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
let startIndex = candidateIndex;
|
|
108
|
+
let backPointer = candidateIndex;
|
|
109
|
+
while (backPointer > 0 && /\s/.test(content.charAt(backPointer - 1))) {
|
|
110
|
+
backPointer--;
|
|
111
|
+
}
|
|
112
|
+
let digitPointer = backPointer;
|
|
113
|
+
while (digitPointer > 0 && /\d/.test(content.charAt(digitPointer - 1))) {
|
|
114
|
+
digitPointer--;
|
|
115
|
+
}
|
|
116
|
+
if (digitPointer < backPointer) {
|
|
117
|
+
startIndex = digitPointer;
|
|
118
|
+
}
|
|
119
|
+
const jsonSegment = this.extractBalancedSegment(content, candidateIndex, '{', '}');
|
|
120
|
+
if (!jsonSegment) {
|
|
121
|
+
searchIndex = candidateIndex + marker.length;
|
|
93
122
|
continue;
|
|
94
123
|
}
|
|
95
124
|
try {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
125
|
+
const parsed = JSON.parse(jsonSegment.segment);
|
|
126
|
+
const toolName = String(parsed.name ?? '');
|
|
127
|
+
const argsText = JSON.stringify(parsed.arguments ?? {});
|
|
128
|
+
const endMarkerIndex = content.indexOf(endMarker, jsonSegment.endIndex);
|
|
129
|
+
if (toolName && endMarkerIndex !== -1) {
|
|
130
|
+
const fullEnd = endMarkerIndex + endMarker.length;
|
|
131
|
+
matches.push({
|
|
132
|
+
start: startIndex,
|
|
133
|
+
end: fullEnd,
|
|
134
|
+
toolName,
|
|
135
|
+
rawArgs: argsText,
|
|
136
|
+
fullMatch: content.slice(startIndex, fullEnd),
|
|
137
|
+
});
|
|
138
|
+
searchIndex = fullEnd;
|
|
139
|
+
continue;
|
|
111
140
|
}
|
|
112
|
-
toolCalls.push({
|
|
113
|
-
name: toolName,
|
|
114
|
-
arguments: parsedArgs,
|
|
115
|
-
});
|
|
116
141
|
}
|
|
117
142
|
catch (error) {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
143
|
+
console.error(`[GemmaToolCallParser] Failed to parse structured tool call JSON: ${error}`);
|
|
144
|
+
}
|
|
145
|
+
searchIndex = candidateIndex + marker.length;
|
|
146
|
+
}
|
|
147
|
+
return matches;
|
|
148
|
+
}
|
|
149
|
+
findHermesToolRequests(content) {
|
|
150
|
+
const matches = [];
|
|
151
|
+
const startTag = '<tool_call>';
|
|
152
|
+
const endTag = '</tool_call>';
|
|
153
|
+
let searchIndex = 0;
|
|
154
|
+
while (searchIndex < content.length) {
|
|
155
|
+
const start = content.indexOf(startTag, searchIndex);
|
|
156
|
+
if (start === -1)
|
|
157
|
+
break;
|
|
158
|
+
const end = content.indexOf(endTag, start + startTag.length);
|
|
159
|
+
if (end === -1)
|
|
160
|
+
break;
|
|
161
|
+
const jsonText = content.slice(start + startTag.length, end).trim();
|
|
162
|
+
let toolName = '';
|
|
163
|
+
let args = '{}';
|
|
164
|
+
try {
|
|
165
|
+
const parsed = JSON.parse(jsonText);
|
|
166
|
+
toolName = String(parsed.name ?? '');
|
|
167
|
+
args = JSON.stringify(parsed.arguments ?? {});
|
|
168
|
+
}
|
|
169
|
+
catch (error) {
|
|
170
|
+
console.error(`[GemmaToolCallParser] Failed to parse Hermes format: ${error}`);
|
|
171
|
+
}
|
|
172
|
+
const fullEnd = end + endTag.length;
|
|
173
|
+
matches.push({
|
|
174
|
+
start,
|
|
175
|
+
end: fullEnd,
|
|
176
|
+
toolName,
|
|
177
|
+
rawArgs: args,
|
|
178
|
+
fullMatch: content.slice(start, fullEnd),
|
|
179
|
+
});
|
|
180
|
+
searchIndex = fullEnd;
|
|
181
|
+
}
|
|
182
|
+
return matches;
|
|
183
|
+
}
|
|
184
|
+
findInvokeToolRequests(content) {
|
|
185
|
+
const matches = [];
|
|
186
|
+
const tagPrefix = '<invoke';
|
|
187
|
+
const closing = '</invoke>';
|
|
188
|
+
let searchIndex = 0;
|
|
189
|
+
while (searchIndex < content.length) {
|
|
190
|
+
const start = content.indexOf(tagPrefix, searchIndex);
|
|
191
|
+
if (start === -1) {
|
|
192
|
+
break;
|
|
193
|
+
}
|
|
194
|
+
const tagEnd = this.findTagClose(content, start + tagPrefix.length);
|
|
195
|
+
if (tagEnd === -1) {
|
|
196
|
+
break;
|
|
197
|
+
}
|
|
198
|
+
const header = content.slice(start + tagPrefix.length, tagEnd);
|
|
199
|
+
const attributes = this.parseAttributeArguments(header);
|
|
200
|
+
const toolNameValue = attributes.name;
|
|
201
|
+
const toolName = typeof toolNameValue === 'string' ? toolNameValue.trim() : '';
|
|
202
|
+
const bodyStart = tagEnd + 1;
|
|
203
|
+
const closingIndex = content.indexOf(closing, bodyStart);
|
|
204
|
+
if (!toolName || closingIndex === -1) {
|
|
205
|
+
searchIndex = bodyStart;
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
const fullEnd = closingIndex + closing.length;
|
|
209
|
+
matches.push({
|
|
210
|
+
start,
|
|
211
|
+
end: fullEnd,
|
|
212
|
+
toolName,
|
|
213
|
+
rawArgs: content.slice(bodyStart, closingIndex),
|
|
214
|
+
fullMatch: content.slice(start, fullEnd),
|
|
215
|
+
});
|
|
216
|
+
searchIndex = fullEnd;
|
|
217
|
+
}
|
|
218
|
+
return matches;
|
|
219
|
+
}
|
|
220
|
+
findGenericXmlToolRequests(content) {
|
|
221
|
+
const matches = [];
|
|
222
|
+
const startTag = '<tool>';
|
|
223
|
+
const endTag = '</tool>';
|
|
224
|
+
let searchIndex = 0;
|
|
225
|
+
while (searchIndex < content.length) {
|
|
226
|
+
const start = content.indexOf(startTag, searchIndex);
|
|
227
|
+
if (start === -1)
|
|
228
|
+
break;
|
|
229
|
+
const end = content.indexOf(endTag, start + startTag.length);
|
|
230
|
+
if (end === -1)
|
|
231
|
+
break;
|
|
232
|
+
const inner = content.slice(start + startTag.length, end);
|
|
233
|
+
const nameMatch = inner.match(/<name>([^<]+)<\/name>/i);
|
|
234
|
+
const argsMatch = inner.match(/<arguments>([\s\S]*?)<\/arguments>/i);
|
|
235
|
+
if (!nameMatch || !argsMatch) {
|
|
236
|
+
searchIndex = end + endTag.length;
|
|
237
|
+
continue;
|
|
238
|
+
}
|
|
239
|
+
const fullEnd = end + endTag.length;
|
|
240
|
+
matches.push({
|
|
241
|
+
start,
|
|
242
|
+
end: fullEnd,
|
|
243
|
+
toolName: nameMatch[1].trim(),
|
|
244
|
+
rawArgs: argsMatch[1],
|
|
245
|
+
fullMatch: content.slice(start, fullEnd),
|
|
246
|
+
});
|
|
247
|
+
searchIndex = fullEnd;
|
|
248
|
+
}
|
|
249
|
+
return matches;
|
|
250
|
+
}
|
|
251
|
+
findUseToolRequests(content) {
|
|
252
|
+
const matches = [];
|
|
253
|
+
const prefix = '<use';
|
|
254
|
+
const closing = '</use>';
|
|
255
|
+
let searchIndex = 0;
|
|
256
|
+
while (searchIndex < content.length) {
|
|
257
|
+
const start = content.indexOf(prefix, searchIndex);
|
|
258
|
+
if (start === -1)
|
|
259
|
+
break;
|
|
260
|
+
const tagEnd = this.findTagClose(content, start + prefix.length);
|
|
261
|
+
if (tagEnd === -1)
|
|
262
|
+
break;
|
|
263
|
+
const header = content.slice(start + prefix.length, tagEnd);
|
|
264
|
+
const { toolName, attributeText } = this.extractToolNameAndAttributes(header);
|
|
265
|
+
const closingIndex = content.startsWith(closing, tagEnd + 1)
|
|
266
|
+
? tagEnd + 1 + closing.length
|
|
267
|
+
: tagEnd + 1;
|
|
268
|
+
if (!toolName) {
|
|
269
|
+
searchIndex = tagEnd + 1;
|
|
270
|
+
continue;
|
|
271
|
+
}
|
|
272
|
+
matches.push({
|
|
273
|
+
start,
|
|
274
|
+
end: closingIndex,
|
|
275
|
+
toolName,
|
|
276
|
+
rawArgs: this.parseAttributeArguments(attributeText),
|
|
277
|
+
fullMatch: content.slice(start, closingIndex),
|
|
278
|
+
});
|
|
279
|
+
searchIndex = closingIndex;
|
|
280
|
+
}
|
|
281
|
+
return matches;
|
|
282
|
+
}
|
|
283
|
+
findUseUnderscoreToolRequests(content) {
|
|
284
|
+
const matches = [];
|
|
285
|
+
const prefix = '<use_';
|
|
286
|
+
let searchIndex = 0;
|
|
287
|
+
while (searchIndex < content.length) {
|
|
288
|
+
const start = content.indexOf(prefix, searchIndex);
|
|
289
|
+
if (start === -1)
|
|
290
|
+
break;
|
|
291
|
+
let nameEnd = start + prefix.length;
|
|
292
|
+
while (nameEnd < content.length &&
|
|
293
|
+
/[A-Za-z0-9_.-]/.test(content[nameEnd])) {
|
|
294
|
+
nameEnd++;
|
|
295
|
+
}
|
|
296
|
+
const toolName = content.slice(start + prefix.length, nameEnd);
|
|
297
|
+
const tagEnd = this.findTagClose(content, nameEnd);
|
|
298
|
+
if (tagEnd === -1)
|
|
299
|
+
break;
|
|
300
|
+
const attributeText = content.slice(nameEnd, tagEnd);
|
|
301
|
+
const closingTag = `</use_${toolName}>`;
|
|
302
|
+
const bodyEnd = tagEnd + 1;
|
|
303
|
+
const closingIndex = content.startsWith(closingTag, bodyEnd)
|
|
304
|
+
? bodyEnd + closingTag.length
|
|
305
|
+
: bodyEnd;
|
|
306
|
+
if (!toolName) {
|
|
307
|
+
searchIndex = bodyEnd;
|
|
308
|
+
continue;
|
|
309
|
+
}
|
|
310
|
+
matches.push({
|
|
311
|
+
start,
|
|
312
|
+
end: closingIndex,
|
|
313
|
+
toolName,
|
|
314
|
+
rawArgs: this.parseAttributeArguments(attributeText),
|
|
315
|
+
fullMatch: content.slice(start, closingIndex),
|
|
316
|
+
});
|
|
317
|
+
searchIndex = closingIndex;
|
|
318
|
+
}
|
|
319
|
+
return matches;
|
|
320
|
+
}
|
|
321
|
+
findKeyValueToolRequests(content) {
|
|
322
|
+
const matches = [];
|
|
323
|
+
let match;
|
|
324
|
+
while ((match = this.keyValuePattern.exec(content)) !== null) {
|
|
325
|
+
const fullMatch = match[0];
|
|
326
|
+
matches.push({
|
|
327
|
+
start: match.index,
|
|
328
|
+
end: match.index + fullMatch.length,
|
|
329
|
+
toolName: match[1],
|
|
330
|
+
rawArgs: this.parseKeyValuePairs(match[2]),
|
|
331
|
+
fullMatch,
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
this.keyValuePattern.lastIndex = 0;
|
|
335
|
+
return matches;
|
|
336
|
+
}
|
|
337
|
+
removeMatchedRanges(content, ranges) {
|
|
338
|
+
if (ranges.length === 0) {
|
|
339
|
+
return content;
|
|
340
|
+
}
|
|
341
|
+
const sorted = ranges
|
|
342
|
+
.filter(({ start, end }) => start < end)
|
|
343
|
+
.sort((a, b) => a.start - b.start);
|
|
344
|
+
const merged = [];
|
|
345
|
+
for (const range of sorted) {
|
|
346
|
+
const last = merged[merged.length - 1];
|
|
347
|
+
if (last && range.start <= last.end) {
|
|
348
|
+
last.end = Math.max(last.end, range.end);
|
|
349
|
+
}
|
|
350
|
+
else {
|
|
351
|
+
merged.push({ ...range });
|
|
156
352
|
}
|
|
157
353
|
}
|
|
158
|
-
|
|
159
|
-
|
|
354
|
+
let cursor = 0;
|
|
355
|
+
const pieces = [];
|
|
356
|
+
for (const range of merged) {
|
|
357
|
+
if (cursor < range.start) {
|
|
358
|
+
pieces.push(content.slice(cursor, range.start));
|
|
359
|
+
}
|
|
360
|
+
cursor = Math.max(cursor, range.end);
|
|
361
|
+
}
|
|
362
|
+
pieces.push(content.slice(cursor));
|
|
363
|
+
return pieces.join('');
|
|
364
|
+
}
|
|
365
|
+
postProcessCleanedContent(content) {
|
|
366
|
+
return content
|
|
160
367
|
.replace(/\[TOOL_REQUEST(?:_END)?]/g, '')
|
|
161
368
|
.replace(/<\|im_start\|>assistant/g, '')
|
|
162
369
|
.replace(/<\|im_end\|>/g, '')
|
|
163
|
-
.replace(/<tool_call>[\s\S]*?<\/tool_call>/g, '')
|
|
164
|
-
.replace(/<function_calls>[\s\S]*?<\/function_calls>/g, '')
|
|
165
|
-
.replace(/<invoke[\s\S]*?<\/invoke>/g, '')
|
|
166
|
-
.replace(/<tool>[\s\S]*?<\/tool>/g, '')
|
|
167
|
-
|
|
168
|
-
.replace(
|
|
169
|
-
.replace(
|
|
370
|
+
.replace(/<tool_call>[\s\S]*?<\/tool_call>/g, '')
|
|
371
|
+
.replace(/<function_calls>[\s\S]*?<\/function_calls>/g, '')
|
|
372
|
+
.replace(/<invoke[\s\S]*?<\/invoke>/g, '')
|
|
373
|
+
.replace(/<tool>[\s\S]*?<\/tool>/g, '')
|
|
374
|
+
.replace(/<\/use_[A-Za-z0-9_.-]+>/g, '')
|
|
375
|
+
.replace(/<\/use>/g, '')
|
|
376
|
+
.replace(/<tool_call>\s*\{[^}]*$/gm, '')
|
|
377
|
+
.replace(/\{"name"\s*:\s*"[^"]*"\s*,?\s*"arguments"\s*:\s*\{[^}]*$/gm, '')
|
|
170
378
|
.replace(/✦\s*<think>/g, '')
|
|
171
|
-
.trim();
|
|
172
|
-
// Collapse multiple consecutive newlines/spaces after removing tool calls
|
|
173
|
-
cleanedContent = cleanedContent
|
|
174
379
|
.replace(/\n\s*\n/g, '\n')
|
|
175
380
|
.replace(/\n/g, ' ')
|
|
176
381
|
.trim();
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
382
|
+
}
|
|
383
|
+
normalizeArguments(args, toolName, fullMatch) {
|
|
384
|
+
if (typeof args !== 'string') {
|
|
385
|
+
return args;
|
|
386
|
+
}
|
|
387
|
+
try {
|
|
388
|
+
if (args.includes('<parameter') ||
|
|
389
|
+
(args.includes('<') && args.includes('>'))) {
|
|
390
|
+
return this.parseXMLParameters(args);
|
|
391
|
+
}
|
|
392
|
+
return JSON.parse(args);
|
|
393
|
+
}
|
|
394
|
+
catch (error) {
|
|
395
|
+
const repaired = this.tryRepairJson(args);
|
|
396
|
+
if (repaired) {
|
|
397
|
+
try {
|
|
398
|
+
return JSON.parse(repaired);
|
|
399
|
+
}
|
|
400
|
+
catch {
|
|
401
|
+
// ignore and fall through
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
const simpleJsonMatch = args.match(/^{[^{]*}$/);
|
|
405
|
+
if (simpleJsonMatch) {
|
|
406
|
+
try {
|
|
407
|
+
return JSON.parse(simpleJsonMatch[0]);
|
|
408
|
+
}
|
|
409
|
+
catch {
|
|
410
|
+
// fall through to logging
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
console.error(`[GemmaToolCallParser] Failed to parse tool arguments for ${toolName}:`, error);
|
|
414
|
+
console.error(`[GemmaToolCallParser] Raw arguments excerpt: ${fullMatch.slice(0, 200)}`);
|
|
415
|
+
return null;
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
extractBalancedSegment(content, startIndex, openChar, closeChar) {
|
|
419
|
+
if (content[startIndex] !== openChar) {
|
|
420
|
+
return null;
|
|
421
|
+
}
|
|
422
|
+
let depth = 0;
|
|
423
|
+
let inString = null;
|
|
424
|
+
let escapeNext = false;
|
|
425
|
+
for (let i = startIndex; i < content.length; i++) {
|
|
426
|
+
const char = content[i];
|
|
427
|
+
if (escapeNext) {
|
|
428
|
+
escapeNext = false;
|
|
429
|
+
continue;
|
|
430
|
+
}
|
|
431
|
+
if (char === '\\' && inString) {
|
|
432
|
+
escapeNext = true;
|
|
433
|
+
continue;
|
|
434
|
+
}
|
|
435
|
+
if (inString) {
|
|
436
|
+
if (char === inString) {
|
|
437
|
+
inString = null;
|
|
438
|
+
}
|
|
439
|
+
continue;
|
|
440
|
+
}
|
|
441
|
+
if (char === '"' || char === "'") {
|
|
442
|
+
inString = char;
|
|
443
|
+
continue;
|
|
444
|
+
}
|
|
445
|
+
if (char === openChar) {
|
|
446
|
+
depth++;
|
|
447
|
+
}
|
|
448
|
+
else if (char === closeChar) {
|
|
449
|
+
depth--;
|
|
450
|
+
if (depth === 0) {
|
|
451
|
+
return {
|
|
452
|
+
segment: content.slice(startIndex, i + 1),
|
|
453
|
+
endIndex: i + 1,
|
|
454
|
+
};
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
return null;
|
|
181
459
|
}
|
|
182
460
|
// Best-effort repair for JSON with unescaped inner quotes in string values.
|
|
183
461
|
tryRepairJson(args) {
|
|
@@ -188,7 +466,7 @@ export class GemmaToolCallParser {
|
|
|
188
466
|
catch {
|
|
189
467
|
// Target only inner quotes within JSON string values, preserving multibyte and spacing
|
|
190
468
|
// e.g., { "command": "printf "ありがとう 世界"" } -> { "command": "printf \"ありがとう 世界\"" }
|
|
191
|
-
const repaired = args.replace(/:(\s)
|
|
469
|
+
const repaired = args.replace(/:(\s*)"((?:\\.|[^"\\])*)"(\s*)([,}])/g, (_m, s1, val, s2, tail) => {
|
|
192
470
|
// Escape only unescaped quotes inside the value
|
|
193
471
|
const fixed = val.replace(/(?<!\\)"/g, '\\"');
|
|
194
472
|
return `:${s1}"${fixed}"${s2}${tail}`;
|
|
@@ -239,6 +517,88 @@ export class GemmaToolCallParser {
|
|
|
239
517
|
}
|
|
240
518
|
return args;
|
|
241
519
|
}
|
|
520
|
+
parseAttributeArguments(attributeText) {
|
|
521
|
+
const args = {};
|
|
522
|
+
const text = attributeText ?? '';
|
|
523
|
+
const length = text.length;
|
|
524
|
+
let index = 0;
|
|
525
|
+
const readIdentifier = () => {
|
|
526
|
+
const start = index;
|
|
527
|
+
while (index < length && /[A-Za-z0-9_.-]/.test(text.charAt(index))) {
|
|
528
|
+
index++;
|
|
529
|
+
}
|
|
530
|
+
return text.slice(start, index);
|
|
531
|
+
};
|
|
532
|
+
const skipWhitespace = () => {
|
|
533
|
+
while (index < length && /\s/.test(text.charAt(index))) {
|
|
534
|
+
index++;
|
|
535
|
+
}
|
|
536
|
+
};
|
|
537
|
+
while (index < length) {
|
|
538
|
+
skipWhitespace();
|
|
539
|
+
const key = readIdentifier();
|
|
540
|
+
if (!key) {
|
|
541
|
+
index++;
|
|
542
|
+
continue;
|
|
543
|
+
}
|
|
544
|
+
skipWhitespace();
|
|
545
|
+
if (text.charAt(index) !== '=') {
|
|
546
|
+
index++;
|
|
547
|
+
continue;
|
|
548
|
+
}
|
|
549
|
+
index++;
|
|
550
|
+
skipWhitespace();
|
|
551
|
+
const quote = text.charAt(index);
|
|
552
|
+
if (quote !== '"' && quote !== "'") {
|
|
553
|
+
index++;
|
|
554
|
+
continue;
|
|
555
|
+
}
|
|
556
|
+
index++;
|
|
557
|
+
let value = '';
|
|
558
|
+
let escaped = false;
|
|
559
|
+
while (index < length) {
|
|
560
|
+
const char = text.charAt(index);
|
|
561
|
+
index++;
|
|
562
|
+
if (escaped) {
|
|
563
|
+
value += char;
|
|
564
|
+
escaped = false;
|
|
565
|
+
continue;
|
|
566
|
+
}
|
|
567
|
+
if (char === '\\') {
|
|
568
|
+
escaped = true;
|
|
569
|
+
continue;
|
|
570
|
+
}
|
|
571
|
+
if (char === quote) {
|
|
572
|
+
break;
|
|
573
|
+
}
|
|
574
|
+
value += char;
|
|
575
|
+
}
|
|
576
|
+
const unescaped = value.trim();
|
|
577
|
+
if (!key) {
|
|
578
|
+
continue;
|
|
579
|
+
}
|
|
580
|
+
if (unescaped.startsWith('{') || unescaped.startsWith('[')) {
|
|
581
|
+
try {
|
|
582
|
+
args[key] = JSON.parse(unescaped);
|
|
583
|
+
continue;
|
|
584
|
+
}
|
|
585
|
+
catch {
|
|
586
|
+
// fall through to scalar handling
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
if (/^-?\d+(\.\d+)?$/.test(unescaped)) {
|
|
590
|
+
args[key] = Number(unescaped);
|
|
591
|
+
}
|
|
592
|
+
else if (unescaped.toLowerCase() === 'true' ||
|
|
593
|
+
unescaped.toLowerCase() === 'false') {
|
|
594
|
+
args[key] = unescaped.toLowerCase() === 'true';
|
|
595
|
+
}
|
|
596
|
+
else {
|
|
597
|
+
args[key] = unescaped;
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
return args;
|
|
601
|
+
}
|
|
242
602
|
parseXMLParameters(xmlContent) {
|
|
243
603
|
const args = {};
|
|
244
604
|
// Parse Claude-style <parameter name="key">value</parameter>
|
|
@@ -276,5 +636,39 @@ export class GemmaToolCallParser {
|
|
|
276
636
|
.replace(/"/g, '"')
|
|
277
637
|
.replace(/'/g, "'");
|
|
278
638
|
}
|
|
639
|
+
findTagClose(content, fromIndex) {
|
|
640
|
+
let inQuote = null;
|
|
641
|
+
for (let i = fromIndex; i < content.length; i++) {
|
|
642
|
+
const char = content[i];
|
|
643
|
+
if (inQuote) {
|
|
644
|
+
if (char === inQuote && content[i - 1] !== '\\') {
|
|
645
|
+
inQuote = null;
|
|
646
|
+
}
|
|
647
|
+
continue;
|
|
648
|
+
}
|
|
649
|
+
if (char === '"' || char === "'") {
|
|
650
|
+
inQuote = char;
|
|
651
|
+
continue;
|
|
652
|
+
}
|
|
653
|
+
if (char === '>') {
|
|
654
|
+
return i;
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
return -1;
|
|
658
|
+
}
|
|
659
|
+
extractToolNameAndAttributes(header) {
|
|
660
|
+
let index = 0;
|
|
661
|
+
const length = header.length;
|
|
662
|
+
while (index < length && /\s/.test(header.charAt(index))) {
|
|
663
|
+
index++;
|
|
664
|
+
}
|
|
665
|
+
const nameStart = index;
|
|
666
|
+
while (index < length && /[A-Za-z0-9_.-]/.test(header.charAt(index))) {
|
|
667
|
+
index++;
|
|
668
|
+
}
|
|
669
|
+
const toolName = header.slice(nameStart, index).trim();
|
|
670
|
+
const attributeText = header.slice(index);
|
|
671
|
+
return { toolName, attributeText };
|
|
672
|
+
}
|
|
279
673
|
}
|
|
280
674
|
//# sourceMappingURL=TextToolCallParser.js.map
|