@blackbox_ai/blackbox-cli-core 0.0.9 → 0.8.1
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/README.md +11 -183
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/src/blackbox/blackboxOAuth2.js +17 -1
- package/dist/src/blackbox/blackboxOAuth2.js.map +1 -1
- package/dist/src/code_assist/oauth2.js +15 -3
- package/dist/src/code_assist/oauth2.js.map +1 -1
- package/dist/src/config/blackboxModels.d.ts +3 -2
- package/dist/src/config/blackboxModels.js +262 -33
- package/dist/src/config/blackboxModels.js.map +1 -1
- package/dist/src/config/config.d.ts +65 -0
- package/dist/src/config/config.js +282 -17
- package/dist/src/config/config.js.map +1 -1
- package/dist/src/config/models.d.ts +1 -1
- package/dist/src/config/models.js +1 -1
- package/dist/src/config/models.js.map +1 -1
- package/dist/src/config/multiAgentModels.d.ts +63 -0
- package/dist/src/config/multiAgentModels.js +194 -0
- package/dist/src/config/multiAgentModels.js.map +1 -0
- package/dist/src/core/client.js +8 -2
- package/dist/src/core/client.js.map +1 -1
- package/dist/src/core/contentGenerator.d.ts +1 -0
- package/dist/src/core/contentGenerator.js +57 -7
- package/dist/src/core/contentGenerator.js.map +1 -1
- package/dist/src/core/encryptedClientFactory.d.ts +17 -0
- package/dist/src/core/encryptedClientFactory.js +92 -0
- package/dist/src/core/encryptedClientFactory.js.map +1 -0
- package/dist/src/core/encryptedContentGenerator.d.ts +47 -0
- package/dist/src/core/encryptedContentGenerator.js +445 -0
- package/dist/src/core/encryptedContentGenerator.js.map +1 -0
- package/dist/src/core/encryptedGeminiClient.d.ts +59 -0
- package/dist/src/core/encryptedGeminiClient.js +177 -0
- package/dist/src/core/encryptedGeminiClient.js.map +1 -0
- package/dist/src/core/encryptedGeminiClientBridge.d.ts +107 -0
- package/dist/src/core/encryptedGeminiClientBridge.js +808 -0
- package/dist/src/core/encryptedGeminiClientBridge.js.map +1 -0
- package/dist/src/core/encryptedGeminiClientWrapper.d.ts +129 -0
- package/dist/src/core/encryptedGeminiClientWrapper.js +305 -0
- package/dist/src/core/encryptedGeminiClientWrapper.js.map +1 -0
- package/dist/src/core/encryptedTurn.d.ts +40 -0
- package/dist/src/core/encryptedTurn.js +114 -0
- package/dist/src/core/encryptedTurn.js.map +1 -0
- package/dist/src/core/logger.d.ts +21 -0
- package/dist/src/core/logger.js +110 -0
- package/dist/src/core/logger.js.map +1 -1
- package/dist/src/core/openaiContentGenerator/constants.d.ts +2 -0
- package/dist/src/core/openaiContentGenerator/constants.js +2 -0
- package/dist/src/core/openaiContentGenerator/constants.js.map +1 -1
- package/dist/src/core/openaiContentGenerator/converter.d.ts +16 -1
- package/dist/src/core/openaiContentGenerator/converter.js +135 -4
- package/dist/src/core/openaiContentGenerator/converter.js.map +1 -1
- package/dist/src/core/openaiContentGenerator/pipeline.js +6 -2
- package/dist/src/core/openaiContentGenerator/pipeline.js.map +1 -1
- package/dist/src/core/openaiContentGenerator/provider/default.js +10 -1
- package/dist/src/core/openaiContentGenerator/provider/default.js.map +1 -1
- package/dist/src/core/prompts.d.ts +17 -0
- package/dist/src/core/prompts.js +347 -19
- package/dist/src/core/prompts.js.map +1 -1
- package/dist/src/core/tokenLimits.d.ts +1 -0
- package/dist/src/core/tokenLimits.js +37 -2
- package/dist/src/core/tokenLimits.js.map +1 -1
- package/dist/src/core/tokenLimits.test.js +36 -1
- package/dist/src/core/tokenLimits.test.js.map +1 -1
- package/dist/src/encrypt/attestation.d.ts +5 -0
- package/dist/src/encrypt/attestation.js +100 -0
- package/dist/src/encrypt/attestation.js.map +1 -0
- package/dist/src/encrypt/client.d.ts +14 -0
- package/dist/src/encrypt/client.js +132 -0
- package/dist/src/encrypt/client.js.map +1 -0
- package/dist/src/encrypt/config.d.ts +22 -0
- package/dist/src/encrypt/config.js +43 -0
- package/dist/src/encrypt/config.js.map +1 -0
- package/dist/src/encrypt/crypto-utils.d.ts +57 -0
- package/dist/src/encrypt/crypto-utils.js +257 -0
- package/dist/src/encrypt/crypto-utils.js.map +1 -0
- package/dist/src/encrypt/history-manager.d.ts +43 -0
- package/dist/src/encrypt/history-manager.js +164 -0
- package/dist/src/encrypt/history-manager.js.map +1 -0
- package/dist/src/encrypt/minimax-template.d.ts +73 -0
- package/dist/src/encrypt/minimax-template.js +276 -0
- package/dist/src/encrypt/minimax-template.js.map +1 -0
- package/dist/src/encrypt/sessions.d.ts +17 -0
- package/dist/src/encrypt/sessions.js +221 -0
- package/dist/src/encrypt/sessions.js.map +1 -0
- package/dist/src/encrypt/streaming-client.d.ts +29 -0
- package/dist/src/encrypt/streaming-client.js +232 -0
- package/dist/src/encrypt/streaming-client.js.map +1 -0
- package/dist/src/encrypt/tool-formatter.d.ts +36 -0
- package/dist/src/encrypt/tool-formatter.js +353 -0
- package/dist/src/encrypt/tool-formatter.js.map +1 -0
- package/dist/src/encrypt/tool-parser.d.ts +93 -0
- package/dist/src/encrypt/tool-parser.js +567 -0
- package/dist/src/encrypt/tool-parser.js.map +1 -0
- package/dist/src/encrypt/types.d.ts +81 -0
- package/dist/src/encrypt/types.js +2 -0
- package/dist/src/encrypt/types.js.map +1 -0
- package/dist/src/generated/git-commit.d.ts +3 -3
- package/dist/src/generated/git-commit.js +3 -3
- package/dist/src/ide/ide-client.js +9 -19
- package/dist/src/ide/ide-client.js.map +1 -1
- package/dist/src/index.d.ts +15 -0
- package/dist/src/index.js +15 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/mcp/oauth-provider.js +2 -6
- package/dist/src/mcp/oauth-provider.js.map +1 -1
- package/dist/src/mcp/oauth-token-storage.d.ts +7 -0
- package/dist/src/mcp/oauth-token-storage.js +24 -0
- package/dist/src/mcp/oauth-token-storage.js.map +1 -1
- package/dist/src/services/EncryptedChatService.d.ts +80 -0
- package/dist/src/services/EncryptedChatService.js +202 -0
- package/dist/src/services/EncryptedChatService.js.map +1 -0
- package/dist/src/services/StatsHistoryService.d.ts +131 -0
- package/dist/src/services/StatsHistoryService.js +427 -0
- package/dist/src/services/StatsHistoryService.js.map +1 -0
- package/dist/src/services/checkpointApiService.d.ts +101 -0
- package/dist/src/services/checkpointApiService.js +215 -0
- package/dist/src/services/checkpointApiService.js.map +1 -0
- package/dist/src/services/environmentSanitization.d.ts +24 -0
- package/dist/src/services/environmentSanitization.js +152 -0
- package/dist/src/services/environmentSanitization.js.map +1 -0
- package/dist/src/telemetry/blackbox-logger/blackbox-logger.d.ts +2 -6
- package/dist/src/telemetry/blackbox-logger/blackbox-logger.js +29 -135
- package/dist/src/telemetry/blackbox-logger/blackbox-logger.js.map +1 -1
- package/dist/src/telemetry/blackbox-logger/blackbox-logger.test.js +1 -1
- package/dist/src/telemetry/blackbox-logger/blackbox-logger.test.js.map +1 -1
- package/dist/src/telemetry/uiTelemetry.d.ts +8 -0
- package/dist/src/telemetry/uiTelemetry.js +17 -0
- package/dist/src/telemetry/uiTelemetry.js.map +1 -1
- package/dist/src/tools/browser-interactive.d.ts +63 -0
- package/dist/src/tools/browser-interactive.js +394 -0
- package/dist/src/tools/browser-interactive.js.map +1 -0
- package/dist/src/tools/browser_use.d.ts +22 -1
- package/dist/src/tools/browser_use.js +403 -23
- package/dist/src/tools/browser_use.js.map +1 -1
- package/dist/src/tools/data-file-constants.d.ts +17 -0
- package/dist/src/tools/data-file-constants.js +30 -0
- package/dist/src/tools/data-file-constants.js.map +1 -0
- package/dist/src/tools/edit.js +44 -7
- package/dist/src/tools/edit.js.map +1 -1
- package/dist/src/tools/ls.js +40 -6
- package/dist/src/tools/ls.js.map +1 -1
- package/dist/src/tools/ls.test.js +4 -4
- package/dist/src/tools/ls.test.js.map +1 -1
- package/dist/src/tools/mcp-client-manager.d.ts +28 -2
- package/dist/src/tools/mcp-client-manager.js +62 -4
- package/dist/src/tools/mcp-client-manager.js.map +1 -1
- package/dist/src/tools/mcp-client.d.ts +5 -3
- package/dist/src/tools/mcp-client.js +39 -11
- package/dist/src/tools/mcp-client.js.map +1 -1
- package/dist/src/tools/mcp-tool.d.ts +3 -1
- package/dist/src/tools/mcp-tool.js +37 -9
- package/dist/src/tools/mcp-tool.js.map +1 -1
- package/dist/src/tools/memoryTool.d.ts +14 -4
- package/dist/src/tools/memoryTool.js +98 -39
- package/dist/src/tools/memoryTool.js.map +1 -1
- package/dist/src/tools/read-data-file.d.ts +31 -0
- package/dist/src/tools/read-data-file.js +469 -0
- package/dist/src/tools/read-data-file.js.map +1 -0
- package/dist/src/tools/read-file.js +64 -5
- package/dist/src/tools/read-file.js.map +1 -1
- package/dist/src/tools/read-file.test.js +40 -6
- package/dist/src/tools/read-file.test.js.map +1 -1
- package/dist/src/tools/shell.d.ts +3 -1
- package/dist/src/tools/shell.js +25 -4
- package/dist/src/tools/shell.js.map +1 -1
- package/dist/src/tools/skill.d.ts +34 -0
- package/dist/src/tools/skill.js +143 -0
- package/dist/src/tools/skill.js.map +1 -0
- package/dist/src/tools/sql_db.d.ts +101 -0
- package/dist/src/tools/sql_db.js +1033 -0
- package/dist/src/tools/sql_db.js.map +1 -0
- package/dist/src/tools/sql_db_configure.d.ts +18 -0
- package/dist/src/tools/sql_db_configure.js +96 -0
- package/dist/src/tools/sql_db_configure.js.map +1 -0
- package/dist/src/tools/taskCompletion.d.ts +29 -0
- package/dist/src/tools/taskCompletion.js +231 -0
- package/dist/src/tools/taskCompletion.js.map +1 -0
- package/dist/src/tools/tool-error.d.ts +3 -1
- package/dist/src/tools/tool-error.js +3 -0
- package/dist/src/tools/tool-error.js.map +1 -1
- package/dist/src/tools/tool-names.d.ts +8 -0
- package/dist/src/tools/tool-names.js +8 -0
- package/dist/src/tools/tool-names.js.map +1 -1
- package/dist/src/tools/tool-registry.d.ts +22 -0
- package/dist/src/tools/tool-registry.js +41 -1
- package/dist/src/tools/tool-registry.js.map +1 -1
- package/dist/src/tools/tools.d.ts +18 -2
- package/dist/src/tools/tools.js +3 -0
- package/dist/src/tools/tools.js.map +1 -1
- package/dist/src/tools/web-fetch.js +24 -4
- package/dist/src/tools/web-fetch.js.map +1 -1
- package/dist/src/tools/web-search.js +160 -2
- package/dist/src/tools/web-search.js.map +1 -1
- package/dist/src/tools/workspace-error-helper.d.ts +9 -0
- package/dist/src/tools/workspace-error-helper.js +43 -0
- package/dist/src/tools/workspace-error-helper.js.map +1 -0
- package/dist/src/tools/workspace-error-helper.test.js +85 -0
- package/dist/src/tools/workspace-error-helper.test.js.map +1 -0
- package/dist/src/tools/write-file.js +42 -7
- package/dist/src/tools/write-file.js.map +1 -1
- package/dist/src/utils/environmentContext.js +3 -1
- package/dist/src/utils/environmentContext.js.map +1 -1
- package/dist/src/utils/environmentContext.test.js +3 -2
- package/dist/src/utils/environmentContext.test.js.map +1 -1
- package/dist/src/utils/fetch.d.ts +3 -1
- package/dist/src/utils/fetch.js +35 -2
- package/dist/src/utils/fetch.js.map +1 -1
- package/dist/src/utils/fileUtils.js +30 -3
- package/dist/src/utils/fileUtils.js.map +1 -1
- package/dist/src/utils/filesearch/fileSearch.d.ts +2 -0
- package/dist/src/utils/filesearch/fileSearch.js +38 -7
- package/dist/src/utils/filesearch/fileSearch.js.map +1 -1
- package/dist/src/utils/git-worktree-utils.d.ts +56 -0
- package/dist/src/utils/git-worktree-utils.js +176 -0
- package/dist/src/utils/git-worktree-utils.js.map +1 -0
- package/dist/src/utils/imageCompression.d.ts +34 -0
- package/dist/src/utils/imageCompression.js +170 -0
- package/dist/src/utils/imageCompression.js.map +1 -0
- package/dist/src/utils/messageTruncator.d.ts +51 -0
- package/dist/src/utils/messageTruncator.js +346 -0
- package/dist/src/utils/messageTruncator.js.map +1 -0
- package/dist/src/utils/pathReader.js +26 -6
- package/dist/src/utils/pathReader.js.map +1 -1
- package/dist/src/utils/skill.d.ts +65 -0
- package/dist/src/utils/skill.js +241 -0
- package/dist/src/utils/skill.js.map +1 -0
- package/dist/src/utils/textCleaning.d.ts +51 -0
- package/dist/src/utils/textCleaning.js +327 -0
- package/dist/src/utils/textCleaning.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +16 -2
- package/dist/src/tools/mcp-client-manager.test.js +0 -39
- package/dist/src/tools/mcp-client-manager.test.js.map +0 -1
- package/dist/src/tools/mcp-client.test.d.ts +0 -6
- package/dist/src/tools/mcp-client.test.js +0 -454
- package/dist/src/tools/mcp-client.test.js.map +0 -1
- package/dist/src/tools/mcp-tool.test.d.ts +0 -6
- package/dist/src/tools/mcp-tool.test.js +0 -576
- package/dist/src/tools/mcp-tool.test.js.map +0 -1
- package/dist/src/tools/memoryTool.test.d.ts +0 -6
- package/dist/src/tools/memoryTool.test.js +0 -420
- package/dist/src/tools/memoryTool.test.js.map +0 -1
- package/dist/src/tools/tool-registry.test.d.ts +0 -6
- package/dist/src/tools/tool-registry.test.js +0 -332
- package/dist/src/tools/tool-registry.test.js.map +0 -1
- /package/dist/src/tools/{mcp-client-manager.test.d.ts → workspace-error-helper.test.d.ts} +0 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import type { FunctionDeclaration } from '@google/genai';
|
|
7
|
+
export interface ToolCall {
|
|
8
|
+
name: string;
|
|
9
|
+
arguments: Record<string, unknown>;
|
|
10
|
+
id?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface ParseResult {
|
|
13
|
+
success: boolean;
|
|
14
|
+
normalText: string;
|
|
15
|
+
toolCalls: ToolCall[];
|
|
16
|
+
error?: string;
|
|
17
|
+
}
|
|
18
|
+
export interface StreamingParseResult {
|
|
19
|
+
normalText: string;
|
|
20
|
+
toolCalls: ToolCall[];
|
|
21
|
+
isComplete: boolean;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Enhanced tool parser for MiniMax-M2.1, DeepSeek, and Qwen
|
|
25
|
+
*/
|
|
26
|
+
export declare class EncryptedToolParser {
|
|
27
|
+
private streamingBuffer;
|
|
28
|
+
private readonly callsBeginToken;
|
|
29
|
+
private readonly callsEndToken;
|
|
30
|
+
private readonly callBeginToken;
|
|
31
|
+
private readonly callEndToken;
|
|
32
|
+
private readonly callSepToken;
|
|
33
|
+
private readonly mmToolCallStart;
|
|
34
|
+
private readonly mmToolCallEnd;
|
|
35
|
+
constructor();
|
|
36
|
+
/**
|
|
37
|
+
* Check if text contains tool calls
|
|
38
|
+
*/
|
|
39
|
+
hasToolCall(text: string): boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Check if text contains bare tool calls (tool tags without wrapper)
|
|
42
|
+
*/
|
|
43
|
+
private hasBareToolCalls;
|
|
44
|
+
/**
|
|
45
|
+
* Parse complete text for tool calls
|
|
46
|
+
*/
|
|
47
|
+
parseComplete(text: string, tools: FunctionDeclaration[], modelType?: string): ParseResult;
|
|
48
|
+
/**
|
|
49
|
+
* Parse MiniMax format tool calls with robust XML parsing
|
|
50
|
+
* Format: <minimax:tool_call><invoke name="func"><parameter name="arg">val</parameter></invoke></minimax:tool_call>
|
|
51
|
+
*/
|
|
52
|
+
private parseMiniMaxFormat;
|
|
53
|
+
/**
|
|
54
|
+
* Parse DeepSeek format tool calls
|
|
55
|
+
*/
|
|
56
|
+
private parseDeepSeekFormat;
|
|
57
|
+
/**
|
|
58
|
+
* Parse Qwen format tool calls
|
|
59
|
+
*/
|
|
60
|
+
private parseQwenFormat;
|
|
61
|
+
/**
|
|
62
|
+
* Parse bare tool calls (tool tags without wrapper)
|
|
63
|
+
* Format: <tool_name>param_name="value"</tool_name> or <tool_name param_name="value" />
|
|
64
|
+
*/
|
|
65
|
+
private parseBareToolCalls;
|
|
66
|
+
/**
|
|
67
|
+
* Parse pipe-delimited tool calls
|
|
68
|
+
* Format: <|tool_name|>content<|tool_name|> or <|tool_name|><|parameter_name="value">
|
|
69
|
+
*/
|
|
70
|
+
private parsePipeDelimitedToolCalls;
|
|
71
|
+
/**
|
|
72
|
+
* Find the index of the first bare tool call in text
|
|
73
|
+
*/
|
|
74
|
+
private findFirstBareToolCall;
|
|
75
|
+
/**
|
|
76
|
+
* Parse JSON arguments with recovery
|
|
77
|
+
*/
|
|
78
|
+
private parseJsonArguments;
|
|
79
|
+
/**
|
|
80
|
+
* Parse streaming increment
|
|
81
|
+
*/
|
|
82
|
+
parseStreamingIncrement(newText: string, tools: FunctionDeclaration[], modelType?: string): StreamingParseResult;
|
|
83
|
+
private hasCompleteToolCalls;
|
|
84
|
+
private extractPartialNormalText;
|
|
85
|
+
private endsWithPartialToken;
|
|
86
|
+
/**
|
|
87
|
+
* Add default values for required parameters that are missing
|
|
88
|
+
*/
|
|
89
|
+
private addDefaultParameters;
|
|
90
|
+
private escapeRegex;
|
|
91
|
+
resetStreamingState(): void;
|
|
92
|
+
}
|
|
93
|
+
export declare function createEncryptedToolParser(): EncryptedToolParser;
|
|
@@ -0,0 +1,567 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Enhanced tool parser for MiniMax-M2.1, DeepSeek, and Qwen
|
|
8
|
+
*/
|
|
9
|
+
export class EncryptedToolParser {
|
|
10
|
+
streamingBuffer = '';
|
|
11
|
+
// DeepSeek format tokens
|
|
12
|
+
callsBeginToken = '<|tool▁calls▁begin|>';
|
|
13
|
+
callsEndToken = '<|tool▁calls▁end|>';
|
|
14
|
+
callBeginToken = '<|tool▁call▁begin|>';
|
|
15
|
+
callEndToken = '<|tool▁call▁end|>';
|
|
16
|
+
callSepToken = '<|tool▁sep|>';
|
|
17
|
+
// MiniMax format tokens (Based on M2.1 Jinja)
|
|
18
|
+
mmToolCallStart = '<minimax:tool_call>';
|
|
19
|
+
mmToolCallEnd = '</minimax:tool_call>';
|
|
20
|
+
constructor() { }
|
|
21
|
+
/**
|
|
22
|
+
* Check if text contains tool calls
|
|
23
|
+
*/
|
|
24
|
+
hasToolCall(text) {
|
|
25
|
+
return text.includes(this.callsBeginToken) ||
|
|
26
|
+
text.includes('<tool_call>') || // Qwen format
|
|
27
|
+
text.includes(this.mmToolCallStart) || // MiniMax format
|
|
28
|
+
text.includes('<invoke name=') || // MiniMax invoke format
|
|
29
|
+
this.hasBareToolCalls(text); // Bare tool calls (new format)
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Check if text contains bare tool calls (tool tags without wrapper)
|
|
33
|
+
*/
|
|
34
|
+
hasBareToolCalls(text) {
|
|
35
|
+
// Look for patterns like <tool_name> with parameters
|
|
36
|
+
const bareToolPatterns = [
|
|
37
|
+
/<read_file[\s>]/,
|
|
38
|
+
/<glob[\s>]/,
|
|
39
|
+
/<search_files[\s>]/,
|
|
40
|
+
/<list_files[\s>]/,
|
|
41
|
+
/<create_file[\s>]/,
|
|
42
|
+
/<edit_file[\s>]/,
|
|
43
|
+
/<execute_command[\s>]/,
|
|
44
|
+
/<browser_action[\s>]/,
|
|
45
|
+
/<ask_followup_question[\s>]/,
|
|
46
|
+
/<attempt_completion[\s>]/,
|
|
47
|
+
/<new_task[\s>]/,
|
|
48
|
+
/<retrieve_knowledge[\s>]/
|
|
49
|
+
];
|
|
50
|
+
// Also check for pipe-delimited format: <|tool_name|>
|
|
51
|
+
const pipeDelimitedPatterns = [
|
|
52
|
+
/<\|read_file\|>/,
|
|
53
|
+
/<\|glob\|>/,
|
|
54
|
+
/<\|search_files\|>/,
|
|
55
|
+
/<\|list_files\|>/,
|
|
56
|
+
/<\|create_file\|>/,
|
|
57
|
+
/<\|edit_file\|>/,
|
|
58
|
+
/<\|execute_command\|>/,
|
|
59
|
+
/<\|browser_action\|>/,
|
|
60
|
+
/<\|ask_followup_question\|>/,
|
|
61
|
+
/<\|attempt_completion\|>/,
|
|
62
|
+
/<\|new_task\|>/,
|
|
63
|
+
/<\|retrieve_knowledge\|>/
|
|
64
|
+
];
|
|
65
|
+
return bareToolPatterns.some(pattern => pattern.test(text)) ||
|
|
66
|
+
pipeDelimitedPatterns.some(pattern => pattern.test(text));
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Parse complete text for tool calls
|
|
70
|
+
*/
|
|
71
|
+
parseComplete(text, tools, modelType = 'minimax') {
|
|
72
|
+
try {
|
|
73
|
+
// 1. Clean <think> tags first (MiniMax puts reasoning in <think> before tools)
|
|
74
|
+
const cleanText = text.replace(/<think>[\s\S]*?<\/think>/g, '').trim();
|
|
75
|
+
const hasToolCalls = this.hasToolCall(cleanText);
|
|
76
|
+
if (!hasToolCalls) {
|
|
77
|
+
return {
|
|
78
|
+
success: true,
|
|
79
|
+
normalText: cleanText,
|
|
80
|
+
toolCalls: []
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
let toolCalls = [];
|
|
84
|
+
let normalText = '';
|
|
85
|
+
if (modelType.toLowerCase() === 'minimax') {
|
|
86
|
+
// First try standard MiniMax format
|
|
87
|
+
toolCalls = this.parseMiniMaxFormat(cleanText, tools);
|
|
88
|
+
// If no tool calls found, try bare tool call format
|
|
89
|
+
if (toolCalls.length === 0 && this.hasBareToolCalls(cleanText)) {
|
|
90
|
+
toolCalls = this.parseBareToolCalls(cleanText, tools);
|
|
91
|
+
}
|
|
92
|
+
// If still no tool calls found, try pipe-delimited format
|
|
93
|
+
if (toolCalls.length === 0) {
|
|
94
|
+
toolCalls = this.parsePipeDelimitedToolCalls(cleanText, tools);
|
|
95
|
+
}
|
|
96
|
+
// For MiniMax, text usually comes before the tool call block (if any)
|
|
97
|
+
// or the tool call block is standalone.
|
|
98
|
+
const toolCallIdx = cleanText.indexOf(this.mmToolCallStart);
|
|
99
|
+
const bareToolIdx = this.findFirstBareToolCall(cleanText);
|
|
100
|
+
const firstToolIdx = toolCallIdx !== -1 ? toolCallIdx : bareToolIdx;
|
|
101
|
+
normalText = firstToolIdx !== -1 ? cleanText.substring(0, firstToolIdx).trim() : cleanText.trim();
|
|
102
|
+
}
|
|
103
|
+
else if (modelType.toLowerCase() === 'deepseek') {
|
|
104
|
+
toolCalls = this.parseDeepSeekFormat(cleanText, tools);
|
|
105
|
+
const toolCallIdx = cleanText.indexOf(this.callsBeginToken);
|
|
106
|
+
normalText = toolCallIdx !== -1 ? cleanText.substring(0, toolCallIdx).trim() : cleanText.trim();
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
toolCalls = this.parseQwenFormat(cleanText, tools);
|
|
110
|
+
const toolCallIdx = cleanText.indexOf('<tool_call>');
|
|
111
|
+
normalText = toolCallIdx !== -1 ? cleanText.substring(0, toolCallIdx).trim() : cleanText.trim();
|
|
112
|
+
}
|
|
113
|
+
return {
|
|
114
|
+
success: true,
|
|
115
|
+
normalText,
|
|
116
|
+
toolCalls
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
catch (error) {
|
|
120
|
+
console.error(`❌ [DEBUG] EncryptedToolParser.parseComplete failed:`, error);
|
|
121
|
+
return {
|
|
122
|
+
success: false,
|
|
123
|
+
normalText: text,
|
|
124
|
+
toolCalls: [],
|
|
125
|
+
error: error instanceof Error ? error.message : 'Unknown parsing error'
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Parse MiniMax format tool calls with robust XML parsing
|
|
131
|
+
* Format: <minimax:tool_call><invoke name="func"><parameter name="arg">val</parameter></invoke></minimax:tool_call>
|
|
132
|
+
*/
|
|
133
|
+
parseMiniMaxFormat(text, tools) {
|
|
134
|
+
const toolCalls = [];
|
|
135
|
+
// Regex to capture content inside <minimax:tool_call> tags
|
|
136
|
+
const outerRegex = /<minimax:tool_call>([\s\S]*?)<\/minimax:tool_call>/g;
|
|
137
|
+
let outerMatch;
|
|
138
|
+
while ((outerMatch = outerRegex.exec(text)) !== null) {
|
|
139
|
+
const toolBlockContent = outerMatch[1];
|
|
140
|
+
// Regex to capture individual <invoke> blocks
|
|
141
|
+
// Use [\s\S]*? for non-greedy match across lines
|
|
142
|
+
const invokeRegex = /<invoke name="([^"]+)">([\s\S]*?)<\/invoke>/g;
|
|
143
|
+
let invokeMatch;
|
|
144
|
+
while ((invokeMatch = invokeRegex.exec(toolBlockContent)) !== null) {
|
|
145
|
+
const toolName = invokeMatch[1];
|
|
146
|
+
const paramsContent = invokeMatch[2];
|
|
147
|
+
// Validate tool exists
|
|
148
|
+
if (!tools.some(t => t.name === toolName)) {
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
const toolArguments = {};
|
|
152
|
+
// Regex to capture <parameter> blocks
|
|
153
|
+
const paramRegex = /<parameter name="([^"]+)">([\s\S]*?)<\/parameter>/g;
|
|
154
|
+
let paramMatch;
|
|
155
|
+
while ((paramMatch = paramRegex.exec(paramsContent)) !== null) {
|
|
156
|
+
const paramName = paramMatch[1];
|
|
157
|
+
const rawValue = paramMatch[2].trim();
|
|
158
|
+
// Intelligent Type Inference based on Jinja behavior
|
|
159
|
+
// Jinja says: {{ v | tojson ... else v }}
|
|
160
|
+
try {
|
|
161
|
+
// 1. Try JSON parsing first (for objects, arrays, quoted strings, true/false, numbers)
|
|
162
|
+
toolArguments[paramName] = JSON.parse(rawValue);
|
|
163
|
+
}
|
|
164
|
+
catch {
|
|
165
|
+
// 2. If JSON fails, it's likely a raw string that didn't need JSON encoding
|
|
166
|
+
// However, we should check for simple types that might be unquoted in XML
|
|
167
|
+
if (rawValue === 'true') {
|
|
168
|
+
toolArguments[paramName] = true;
|
|
169
|
+
}
|
|
170
|
+
else if (rawValue === 'false') {
|
|
171
|
+
toolArguments[paramName] = false;
|
|
172
|
+
}
|
|
173
|
+
else if (!isNaN(Number(rawValue)) && rawValue !== '') {
|
|
174
|
+
toolArguments[paramName] = Number(rawValue);
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
toolArguments[paramName] = rawValue; // Fallback to string
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
// Add default values for required parameters if missing
|
|
182
|
+
this.addDefaultParameters(toolName, toolArguments);
|
|
183
|
+
toolCalls.push({
|
|
184
|
+
name: toolName,
|
|
185
|
+
arguments: toolArguments,
|
|
186
|
+
id: `call_${Date.now()}_${toolCalls.length}`
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
return toolCalls;
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Parse DeepSeek format tool calls
|
|
194
|
+
*/
|
|
195
|
+
parseDeepSeekFormat(text, tools) {
|
|
196
|
+
const toolCalls = [];
|
|
197
|
+
// Find all tool call blocks
|
|
198
|
+
const callsBlockRegex = new RegExp(`${this.escapeRegex(this.callsBeginToken)}(.*?)${this.escapeRegex(this.callsEndToken)}`, 'gs');
|
|
199
|
+
const callsMatches = Array.from(text.matchAll(callsBlockRegex));
|
|
200
|
+
for (const callsMatch of callsMatches) {
|
|
201
|
+
const callsContent = callsMatch[1];
|
|
202
|
+
const individualCallRegex = new RegExp(`${this.escapeRegex(this.callBeginToken)}(.*?)${this.escapeRegex(this.callSepToken)}(.*?)${this.escapeRegex(this.callEndToken)}`, 'gs');
|
|
203
|
+
const individualMatches = Array.from(callsContent.matchAll(individualCallRegex));
|
|
204
|
+
for (const [, toolName, argsStr] of individualMatches) {
|
|
205
|
+
const trimmedName = toolName.trim();
|
|
206
|
+
const trimmedArgs = argsStr.trim();
|
|
207
|
+
if (!tools.some(t => t.name === trimmedName))
|
|
208
|
+
continue;
|
|
209
|
+
try {
|
|
210
|
+
const parsedArgs = this.parseJsonArguments(trimmedArgs);
|
|
211
|
+
// Add default values for required parameters if missing
|
|
212
|
+
this.addDefaultParameters(trimmedName, parsedArgs);
|
|
213
|
+
toolCalls.push({
|
|
214
|
+
name: trimmedName,
|
|
215
|
+
arguments: parsedArgs,
|
|
216
|
+
id: `call_${Date.now()}_${toolCalls.length}`
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
catch (error) {
|
|
220
|
+
console.warn(`Failed to parse args for ${trimmedName}`, error);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
return toolCalls;
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Parse Qwen format tool calls
|
|
228
|
+
*/
|
|
229
|
+
parseQwenFormat(text, tools) {
|
|
230
|
+
const toolCalls = [];
|
|
231
|
+
const qwenRegex = /<tool_call>\s*([\s\S]*?)\s*<\/tool_call>/g;
|
|
232
|
+
let match;
|
|
233
|
+
while ((match = qwenRegex.exec(text)) !== null) {
|
|
234
|
+
try {
|
|
235
|
+
const toolCallData = this.parseJsonArguments(match[1].trim());
|
|
236
|
+
if (toolCallData['name'] && toolCallData['arguments']) {
|
|
237
|
+
const toolName = toolCallData['name'];
|
|
238
|
+
if (!tools.some(t => t.name === toolName))
|
|
239
|
+
continue;
|
|
240
|
+
const args = toolCallData['arguments'];
|
|
241
|
+
// Add default values for required parameters if missing
|
|
242
|
+
this.addDefaultParameters(toolName, args);
|
|
243
|
+
toolCalls.push({
|
|
244
|
+
name: toolName,
|
|
245
|
+
arguments: args,
|
|
246
|
+
id: `call_${Date.now()}_${toolCalls.length}`
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
catch (_e) { /* ignore */ }
|
|
251
|
+
}
|
|
252
|
+
return toolCalls;
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Parse bare tool calls (tool tags without wrapper)
|
|
256
|
+
* Format: <tool_name>param_name="value"</tool_name> or <tool_name param_name="value" />
|
|
257
|
+
*/
|
|
258
|
+
parseBareToolCalls(text, tools) {
|
|
259
|
+
const toolCalls = [];
|
|
260
|
+
const toolNames = tools.map(t => t.name).filter((name) => name !== undefined);
|
|
261
|
+
// Create regex pattern for each tool
|
|
262
|
+
for (const toolName of toolNames) {
|
|
263
|
+
// Pattern 1: Self-closing tags with attributes: <tool_name param="value" />
|
|
264
|
+
const selfClosingRegex = new RegExp(`<${toolName}\\s+([^>]*?)\\s*/>`, 'g');
|
|
265
|
+
let selfClosingMatch;
|
|
266
|
+
while ((selfClosingMatch = selfClosingRegex.exec(text)) !== null) {
|
|
267
|
+
const attributesString = selfClosingMatch[1];
|
|
268
|
+
const toolArguments = {};
|
|
269
|
+
// Parse attributes from self-closing tag
|
|
270
|
+
const paramRegex = /(\w+)="([^"]*)"/g;
|
|
271
|
+
let paramMatch;
|
|
272
|
+
while ((paramMatch = paramRegex.exec(attributesString)) !== null) {
|
|
273
|
+
const paramName = paramMatch[1];
|
|
274
|
+
const paramValue = paramMatch[2];
|
|
275
|
+
// Type inference for parameter values
|
|
276
|
+
if (paramValue === 'true') {
|
|
277
|
+
toolArguments[paramName] = true;
|
|
278
|
+
}
|
|
279
|
+
else if (paramValue === 'false') {
|
|
280
|
+
toolArguments[paramName] = false;
|
|
281
|
+
}
|
|
282
|
+
else if (!isNaN(Number(paramValue)) && paramValue !== '') {
|
|
283
|
+
toolArguments[paramName] = Number(paramValue);
|
|
284
|
+
}
|
|
285
|
+
else {
|
|
286
|
+
toolArguments[paramName] = paramValue;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
// Add default values for required parameters if missing
|
|
290
|
+
this.addDefaultParameters(toolName, toolArguments);
|
|
291
|
+
toolCalls.push({
|
|
292
|
+
name: toolName,
|
|
293
|
+
arguments: toolArguments,
|
|
294
|
+
id: `call_${Date.now()}_${toolCalls.length}`
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
// Pattern 2: Opening/closing tags: <tool_name>content</tool_name> or <tool_name param="value">content</tool_name>
|
|
298
|
+
const openCloseRegex = new RegExp(`<${toolName}([^>]*?)>([\\s\\S]*?)<\\/${toolName}>`, 'g');
|
|
299
|
+
let openCloseMatch;
|
|
300
|
+
while ((openCloseMatch = openCloseRegex.exec(text)) !== null) {
|
|
301
|
+
const attributesString = openCloseMatch[1];
|
|
302
|
+
const toolContent = openCloseMatch[2];
|
|
303
|
+
const toolArguments = {};
|
|
304
|
+
// Parse attributes from opening tag
|
|
305
|
+
if (attributesString.trim()) {
|
|
306
|
+
const paramRegex = /(\w+)="([^"]*)"/g;
|
|
307
|
+
let paramMatch;
|
|
308
|
+
while ((paramMatch = paramRegex.exec(attributesString)) !== null) {
|
|
309
|
+
const paramName = paramMatch[1];
|
|
310
|
+
const paramValue = paramMatch[2];
|
|
311
|
+
// Type inference for parameter values
|
|
312
|
+
if (paramValue === 'true') {
|
|
313
|
+
toolArguments[paramName] = true;
|
|
314
|
+
}
|
|
315
|
+
else if (paramValue === 'false') {
|
|
316
|
+
toolArguments[paramName] = false;
|
|
317
|
+
}
|
|
318
|
+
else if (!isNaN(Number(paramValue)) && paramValue !== '') {
|
|
319
|
+
toolArguments[paramName] = Number(paramValue);
|
|
320
|
+
}
|
|
321
|
+
else {
|
|
322
|
+
toolArguments[paramName] = paramValue;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
// Parse parameters from the tool content
|
|
327
|
+
// Look for patterns like: param_name="value"
|
|
328
|
+
const contentParamRegex = /(\w+)="([^"]*)"/g;
|
|
329
|
+
let contentParamMatch;
|
|
330
|
+
while ((contentParamMatch = contentParamRegex.exec(toolContent)) !== null) {
|
|
331
|
+
const paramName = contentParamMatch[1];
|
|
332
|
+
const paramValue = contentParamMatch[2];
|
|
333
|
+
// Type inference for parameter values
|
|
334
|
+
if (paramValue === 'true') {
|
|
335
|
+
toolArguments[paramName] = true;
|
|
336
|
+
}
|
|
337
|
+
else if (paramValue === 'false') {
|
|
338
|
+
toolArguments[paramName] = false;
|
|
339
|
+
}
|
|
340
|
+
else if (!isNaN(Number(paramValue)) && paramValue !== '') {
|
|
341
|
+
toolArguments[paramName] = Number(paramValue);
|
|
342
|
+
}
|
|
343
|
+
else {
|
|
344
|
+
toolArguments[paramName] = paramValue;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
// Also look for content between tags (for tools that take content)
|
|
348
|
+
const contentMatch = toolContent.match(/^\s*([^=\s][^=]*?)\s*$/);
|
|
349
|
+
if (contentMatch && !toolContent.includes('=')) {
|
|
350
|
+
// This is content-based tool call
|
|
351
|
+
const content = contentMatch[1].trim();
|
|
352
|
+
if (content) {
|
|
353
|
+
// For content-based tools, use common parameter names
|
|
354
|
+
if (toolName === 'execute_command') {
|
|
355
|
+
toolArguments['command'] = content;
|
|
356
|
+
}
|
|
357
|
+
else if (toolName === 'ask_followup_question') {
|
|
358
|
+
toolArguments['question'] = content;
|
|
359
|
+
}
|
|
360
|
+
else {
|
|
361
|
+
toolArguments['content'] = content;
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
// Add default values for required parameters if missing
|
|
366
|
+
this.addDefaultParameters(toolName, toolArguments);
|
|
367
|
+
toolCalls.push({
|
|
368
|
+
name: toolName,
|
|
369
|
+
arguments: toolArguments,
|
|
370
|
+
id: `call_${Date.now()}_${toolCalls.length}`
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
return toolCalls;
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* Parse pipe-delimited tool calls
|
|
378
|
+
* Format: <|tool_name|>content<|tool_name|> or <|tool_name|><|parameter_name="value">
|
|
379
|
+
*/
|
|
380
|
+
parsePipeDelimitedToolCalls(text, tools) {
|
|
381
|
+
const toolCalls = [];
|
|
382
|
+
const toolNames = tools.map(t => t.name).filter((name) => name !== undefined);
|
|
383
|
+
for (const toolName of toolNames) {
|
|
384
|
+
// Pattern: <|tool_name|>...content...<|tool_name|> or <|tool_name|>content (without closing)
|
|
385
|
+
const pipeRegex = new RegExp(`<\\|${toolName}\\|>([\\s\\S]*?)(?:<\\|${toolName}\\||$)`, 'g');
|
|
386
|
+
let pipeMatch;
|
|
387
|
+
while ((pipeMatch = pipeRegex.exec(text)) !== null) {
|
|
388
|
+
const toolContent = pipeMatch[1];
|
|
389
|
+
const toolArguments = {};
|
|
390
|
+
// Parse parameters from pipe-delimited format: <|parameter_name="value">
|
|
391
|
+
const paramRegex = /<\|(\w+)="([^"]*)"/g;
|
|
392
|
+
let paramMatch;
|
|
393
|
+
let paramCount = 0;
|
|
394
|
+
while ((paramMatch = paramRegex.exec(toolContent)) !== null) {
|
|
395
|
+
paramCount++;
|
|
396
|
+
const paramName = paramMatch[1];
|
|
397
|
+
const paramValue = paramMatch[2];
|
|
398
|
+
// Type inference for parameter values
|
|
399
|
+
if (paramValue === 'true') {
|
|
400
|
+
toolArguments[paramName] = true;
|
|
401
|
+
}
|
|
402
|
+
else if (paramValue === 'false') {
|
|
403
|
+
toolArguments[paramName] = false;
|
|
404
|
+
}
|
|
405
|
+
else if (!isNaN(Number(paramValue)) && paramValue !== '') {
|
|
406
|
+
toolArguments[paramName] = Number(paramValue);
|
|
407
|
+
}
|
|
408
|
+
else {
|
|
409
|
+
toolArguments[paramName] = paramValue;
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
// If no parameters found in pipe format, treat the content as a direct parameter
|
|
413
|
+
if (paramCount === 0 && toolContent.trim()) {
|
|
414
|
+
const cleanContent = toolContent.trim();
|
|
415
|
+
// For content-based tools, use common parameter names
|
|
416
|
+
if (toolName === 'execute_command') {
|
|
417
|
+
toolArguments['command'] = cleanContent;
|
|
418
|
+
}
|
|
419
|
+
else if (toolName === 'ask_followup_question') {
|
|
420
|
+
toolArguments['question'] = cleanContent;
|
|
421
|
+
}
|
|
422
|
+
else if (toolName === 'read_file') {
|
|
423
|
+
toolArguments['path'] = cleanContent;
|
|
424
|
+
}
|
|
425
|
+
else if (toolName === 'glob') {
|
|
426
|
+
toolArguments['pattern'] = cleanContent;
|
|
427
|
+
}
|
|
428
|
+
else {
|
|
429
|
+
toolArguments['content'] = cleanContent;
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
// Add default values for required parameters if missing
|
|
433
|
+
this.addDefaultParameters(toolName, toolArguments);
|
|
434
|
+
toolCalls.push({
|
|
435
|
+
name: toolName,
|
|
436
|
+
arguments: toolArguments,
|
|
437
|
+
id: `call_${Date.now()}_${toolCalls.length}`
|
|
438
|
+
});
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
return toolCalls;
|
|
442
|
+
}
|
|
443
|
+
/**
|
|
444
|
+
* Find the index of the first bare tool call in text
|
|
445
|
+
*/
|
|
446
|
+
findFirstBareToolCall(text) {
|
|
447
|
+
const bareToolPatterns = [
|
|
448
|
+
/<read_file[\s>]/,
|
|
449
|
+
/<glob[\s>]/,
|
|
450
|
+
/<search_files[\s>]/,
|
|
451
|
+
/<list_files[\s>]/,
|
|
452
|
+
/<create_file[\s>]/,
|
|
453
|
+
/<edit_file[\s>]/,
|
|
454
|
+
/<execute_command[\s>]/,
|
|
455
|
+
/<browser_action[\s>]/,
|
|
456
|
+
/<ask_followup_question[\s>]/,
|
|
457
|
+
/<attempt_completion[\s>]/,
|
|
458
|
+
/<new_task[\s>]/,
|
|
459
|
+
/<retrieve_knowledge[\s>]/
|
|
460
|
+
];
|
|
461
|
+
let earliestIndex = -1;
|
|
462
|
+
for (const pattern of bareToolPatterns) {
|
|
463
|
+
const match = text.match(pattern);
|
|
464
|
+
if (match && typeof match.index === 'number') {
|
|
465
|
+
if (earliestIndex === -1 || match.index < earliestIndex) {
|
|
466
|
+
earliestIndex = match.index;
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
return earliestIndex;
|
|
471
|
+
}
|
|
472
|
+
/**
|
|
473
|
+
* Parse JSON arguments with recovery
|
|
474
|
+
*/
|
|
475
|
+
parseJsonArguments(jsonStr) {
|
|
476
|
+
try {
|
|
477
|
+
return JSON.parse(jsonStr);
|
|
478
|
+
}
|
|
479
|
+
catch {
|
|
480
|
+
try {
|
|
481
|
+
// Fix unescaped quotes and trailing commas
|
|
482
|
+
const fixed = jsonStr.replace(/([^\\])"/g, '$1\\"').replace(/,(\s*[}\]])/g, '$1');
|
|
483
|
+
return JSON.parse(fixed);
|
|
484
|
+
}
|
|
485
|
+
catch {
|
|
486
|
+
return {}; // Parsing failed
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
/**
|
|
491
|
+
* Parse streaming increment
|
|
492
|
+
*/
|
|
493
|
+
parseStreamingIncrement(newText, tools, modelType = 'minimax') {
|
|
494
|
+
this.streamingBuffer += newText;
|
|
495
|
+
const hasComplete = this.hasCompleteToolCalls(this.streamingBuffer, modelType);
|
|
496
|
+
if (hasComplete) {
|
|
497
|
+
const parseResult = this.parseComplete(this.streamingBuffer, tools, modelType);
|
|
498
|
+
this.streamingBuffer = '';
|
|
499
|
+
return {
|
|
500
|
+
normalText: parseResult.normalText,
|
|
501
|
+
toolCalls: parseResult.toolCalls,
|
|
502
|
+
isComplete: true
|
|
503
|
+
};
|
|
504
|
+
}
|
|
505
|
+
return {
|
|
506
|
+
normalText: this.extractPartialNormalText(newText),
|
|
507
|
+
toolCalls: [],
|
|
508
|
+
isComplete: false
|
|
509
|
+
};
|
|
510
|
+
}
|
|
511
|
+
hasCompleteToolCalls(text, modelType) {
|
|
512
|
+
if (modelType.toLowerCase() === 'minimax') {
|
|
513
|
+
return text.includes(this.mmToolCallStart) && text.includes(this.mmToolCallEnd);
|
|
514
|
+
}
|
|
515
|
+
else if (modelType.toLowerCase() === 'deepseek') {
|
|
516
|
+
return text.includes(this.callsBeginToken) && text.includes(this.callsEndToken);
|
|
517
|
+
}
|
|
518
|
+
else {
|
|
519
|
+
return text.includes('<tool_call>') && text.includes('</tool_call>');
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
extractPartialNormalText(newText) {
|
|
523
|
+
// If buffer contains start of tool call or start of thought, block output
|
|
524
|
+
if (this.streamingBuffer.includes('<minimax') ||
|
|
525
|
+
this.streamingBuffer.includes('<invoke') ||
|
|
526
|
+
this.streamingBuffer.includes('<think') ||
|
|
527
|
+
this.streamingBuffer.includes(this.callsBeginToken) ||
|
|
528
|
+
this.streamingBuffer.includes('<tool_call>')) {
|
|
529
|
+
return '';
|
|
530
|
+
}
|
|
531
|
+
// Check partial endings to be safe
|
|
532
|
+
const tokens = ['<minimax', '<invoke', '<think', '<tool_call', '<|tool'];
|
|
533
|
+
for (const t of tokens) {
|
|
534
|
+
if (this.endsWithPartialToken(this.streamingBuffer, t))
|
|
535
|
+
return '';
|
|
536
|
+
}
|
|
537
|
+
return newText;
|
|
538
|
+
}
|
|
539
|
+
endsWithPartialToken(text, target) {
|
|
540
|
+
for (let i = 1; i < target.length; i++) {
|
|
541
|
+
if (text.endsWith(target.substring(0, i)))
|
|
542
|
+
return true;
|
|
543
|
+
}
|
|
544
|
+
return false;
|
|
545
|
+
}
|
|
546
|
+
/**
|
|
547
|
+
* Add default values for required parameters that are missing
|
|
548
|
+
*/
|
|
549
|
+
addDefaultParameters(toolName, toolArguments) {
|
|
550
|
+
// Shell/execute_command tool requires is_background parameter
|
|
551
|
+
// Check if the parameter is undefined or not present at all
|
|
552
|
+
if (toolName === 'execute_command' && !('is_background' in toolArguments)) {
|
|
553
|
+
// Default to foreground execution (false) for safety
|
|
554
|
+
toolArguments['is_background'] = false;
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
escapeRegex(str) {
|
|
558
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
559
|
+
}
|
|
560
|
+
resetStreamingState() {
|
|
561
|
+
this.streamingBuffer = '';
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
export function createEncryptedToolParser() {
|
|
565
|
+
return new EncryptedToolParser();
|
|
566
|
+
}
|
|
567
|
+
//# sourceMappingURL=tool-parser.js.map
|