@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.
Files changed (247) hide show
  1. package/README.md +11 -183
  2. package/dist/index.d.ts +2 -1
  3. package/dist/index.js +2 -1
  4. package/dist/index.js.map +1 -1
  5. package/dist/src/blackbox/blackboxOAuth2.js +17 -1
  6. package/dist/src/blackbox/blackboxOAuth2.js.map +1 -1
  7. package/dist/src/code_assist/oauth2.js +15 -3
  8. package/dist/src/code_assist/oauth2.js.map +1 -1
  9. package/dist/src/config/blackboxModels.d.ts +3 -2
  10. package/dist/src/config/blackboxModels.js +262 -33
  11. package/dist/src/config/blackboxModels.js.map +1 -1
  12. package/dist/src/config/config.d.ts +65 -0
  13. package/dist/src/config/config.js +282 -17
  14. package/dist/src/config/config.js.map +1 -1
  15. package/dist/src/config/models.d.ts +1 -1
  16. package/dist/src/config/models.js +1 -1
  17. package/dist/src/config/models.js.map +1 -1
  18. package/dist/src/config/multiAgentModels.d.ts +63 -0
  19. package/dist/src/config/multiAgentModels.js +194 -0
  20. package/dist/src/config/multiAgentModels.js.map +1 -0
  21. package/dist/src/core/client.js +8 -2
  22. package/dist/src/core/client.js.map +1 -1
  23. package/dist/src/core/contentGenerator.d.ts +1 -0
  24. package/dist/src/core/contentGenerator.js +57 -7
  25. package/dist/src/core/contentGenerator.js.map +1 -1
  26. package/dist/src/core/encryptedClientFactory.d.ts +17 -0
  27. package/dist/src/core/encryptedClientFactory.js +92 -0
  28. package/dist/src/core/encryptedClientFactory.js.map +1 -0
  29. package/dist/src/core/encryptedContentGenerator.d.ts +47 -0
  30. package/dist/src/core/encryptedContentGenerator.js +445 -0
  31. package/dist/src/core/encryptedContentGenerator.js.map +1 -0
  32. package/dist/src/core/encryptedGeminiClient.d.ts +59 -0
  33. package/dist/src/core/encryptedGeminiClient.js +177 -0
  34. package/dist/src/core/encryptedGeminiClient.js.map +1 -0
  35. package/dist/src/core/encryptedGeminiClientBridge.d.ts +107 -0
  36. package/dist/src/core/encryptedGeminiClientBridge.js +808 -0
  37. package/dist/src/core/encryptedGeminiClientBridge.js.map +1 -0
  38. package/dist/src/core/encryptedGeminiClientWrapper.d.ts +129 -0
  39. package/dist/src/core/encryptedGeminiClientWrapper.js +305 -0
  40. package/dist/src/core/encryptedGeminiClientWrapper.js.map +1 -0
  41. package/dist/src/core/encryptedTurn.d.ts +40 -0
  42. package/dist/src/core/encryptedTurn.js +114 -0
  43. package/dist/src/core/encryptedTurn.js.map +1 -0
  44. package/dist/src/core/logger.d.ts +21 -0
  45. package/dist/src/core/logger.js +110 -0
  46. package/dist/src/core/logger.js.map +1 -1
  47. package/dist/src/core/openaiContentGenerator/constants.d.ts +2 -0
  48. package/dist/src/core/openaiContentGenerator/constants.js +2 -0
  49. package/dist/src/core/openaiContentGenerator/constants.js.map +1 -1
  50. package/dist/src/core/openaiContentGenerator/converter.d.ts +16 -1
  51. package/dist/src/core/openaiContentGenerator/converter.js +135 -4
  52. package/dist/src/core/openaiContentGenerator/converter.js.map +1 -1
  53. package/dist/src/core/openaiContentGenerator/pipeline.js +6 -2
  54. package/dist/src/core/openaiContentGenerator/pipeline.js.map +1 -1
  55. package/dist/src/core/openaiContentGenerator/provider/default.js +10 -1
  56. package/dist/src/core/openaiContentGenerator/provider/default.js.map +1 -1
  57. package/dist/src/core/prompts.d.ts +17 -0
  58. package/dist/src/core/prompts.js +347 -19
  59. package/dist/src/core/prompts.js.map +1 -1
  60. package/dist/src/core/tokenLimits.d.ts +1 -0
  61. package/dist/src/core/tokenLimits.js +37 -2
  62. package/dist/src/core/tokenLimits.js.map +1 -1
  63. package/dist/src/core/tokenLimits.test.js +36 -1
  64. package/dist/src/core/tokenLimits.test.js.map +1 -1
  65. package/dist/src/encrypt/attestation.d.ts +5 -0
  66. package/dist/src/encrypt/attestation.js +100 -0
  67. package/dist/src/encrypt/attestation.js.map +1 -0
  68. package/dist/src/encrypt/client.d.ts +14 -0
  69. package/dist/src/encrypt/client.js +132 -0
  70. package/dist/src/encrypt/client.js.map +1 -0
  71. package/dist/src/encrypt/config.d.ts +22 -0
  72. package/dist/src/encrypt/config.js +43 -0
  73. package/dist/src/encrypt/config.js.map +1 -0
  74. package/dist/src/encrypt/crypto-utils.d.ts +57 -0
  75. package/dist/src/encrypt/crypto-utils.js +257 -0
  76. package/dist/src/encrypt/crypto-utils.js.map +1 -0
  77. package/dist/src/encrypt/history-manager.d.ts +43 -0
  78. package/dist/src/encrypt/history-manager.js +164 -0
  79. package/dist/src/encrypt/history-manager.js.map +1 -0
  80. package/dist/src/encrypt/minimax-template.d.ts +73 -0
  81. package/dist/src/encrypt/minimax-template.js +276 -0
  82. package/dist/src/encrypt/minimax-template.js.map +1 -0
  83. package/dist/src/encrypt/sessions.d.ts +17 -0
  84. package/dist/src/encrypt/sessions.js +221 -0
  85. package/dist/src/encrypt/sessions.js.map +1 -0
  86. package/dist/src/encrypt/streaming-client.d.ts +29 -0
  87. package/dist/src/encrypt/streaming-client.js +232 -0
  88. package/dist/src/encrypt/streaming-client.js.map +1 -0
  89. package/dist/src/encrypt/tool-formatter.d.ts +36 -0
  90. package/dist/src/encrypt/tool-formatter.js +353 -0
  91. package/dist/src/encrypt/tool-formatter.js.map +1 -0
  92. package/dist/src/encrypt/tool-parser.d.ts +93 -0
  93. package/dist/src/encrypt/tool-parser.js +567 -0
  94. package/dist/src/encrypt/tool-parser.js.map +1 -0
  95. package/dist/src/encrypt/types.d.ts +81 -0
  96. package/dist/src/encrypt/types.js +2 -0
  97. package/dist/src/encrypt/types.js.map +1 -0
  98. package/dist/src/generated/git-commit.d.ts +3 -3
  99. package/dist/src/generated/git-commit.js +3 -3
  100. package/dist/src/ide/ide-client.js +9 -19
  101. package/dist/src/ide/ide-client.js.map +1 -1
  102. package/dist/src/index.d.ts +15 -0
  103. package/dist/src/index.js +15 -0
  104. package/dist/src/index.js.map +1 -1
  105. package/dist/src/mcp/oauth-provider.js +2 -6
  106. package/dist/src/mcp/oauth-provider.js.map +1 -1
  107. package/dist/src/mcp/oauth-token-storage.d.ts +7 -0
  108. package/dist/src/mcp/oauth-token-storage.js +24 -0
  109. package/dist/src/mcp/oauth-token-storage.js.map +1 -1
  110. package/dist/src/services/EncryptedChatService.d.ts +80 -0
  111. package/dist/src/services/EncryptedChatService.js +202 -0
  112. package/dist/src/services/EncryptedChatService.js.map +1 -0
  113. package/dist/src/services/StatsHistoryService.d.ts +131 -0
  114. package/dist/src/services/StatsHistoryService.js +427 -0
  115. package/dist/src/services/StatsHistoryService.js.map +1 -0
  116. package/dist/src/services/checkpointApiService.d.ts +101 -0
  117. package/dist/src/services/checkpointApiService.js +215 -0
  118. package/dist/src/services/checkpointApiService.js.map +1 -0
  119. package/dist/src/services/environmentSanitization.d.ts +24 -0
  120. package/dist/src/services/environmentSanitization.js +152 -0
  121. package/dist/src/services/environmentSanitization.js.map +1 -0
  122. package/dist/src/telemetry/blackbox-logger/blackbox-logger.d.ts +2 -6
  123. package/dist/src/telemetry/blackbox-logger/blackbox-logger.js +29 -135
  124. package/dist/src/telemetry/blackbox-logger/blackbox-logger.js.map +1 -1
  125. package/dist/src/telemetry/blackbox-logger/blackbox-logger.test.js +1 -1
  126. package/dist/src/telemetry/blackbox-logger/blackbox-logger.test.js.map +1 -1
  127. package/dist/src/telemetry/uiTelemetry.d.ts +8 -0
  128. package/dist/src/telemetry/uiTelemetry.js +17 -0
  129. package/dist/src/telemetry/uiTelemetry.js.map +1 -1
  130. package/dist/src/tools/browser-interactive.d.ts +63 -0
  131. package/dist/src/tools/browser-interactive.js +394 -0
  132. package/dist/src/tools/browser-interactive.js.map +1 -0
  133. package/dist/src/tools/browser_use.d.ts +22 -1
  134. package/dist/src/tools/browser_use.js +403 -23
  135. package/dist/src/tools/browser_use.js.map +1 -1
  136. package/dist/src/tools/data-file-constants.d.ts +17 -0
  137. package/dist/src/tools/data-file-constants.js +30 -0
  138. package/dist/src/tools/data-file-constants.js.map +1 -0
  139. package/dist/src/tools/edit.js +44 -7
  140. package/dist/src/tools/edit.js.map +1 -1
  141. package/dist/src/tools/ls.js +40 -6
  142. package/dist/src/tools/ls.js.map +1 -1
  143. package/dist/src/tools/ls.test.js +4 -4
  144. package/dist/src/tools/ls.test.js.map +1 -1
  145. package/dist/src/tools/mcp-client-manager.d.ts +28 -2
  146. package/dist/src/tools/mcp-client-manager.js +62 -4
  147. package/dist/src/tools/mcp-client-manager.js.map +1 -1
  148. package/dist/src/tools/mcp-client.d.ts +5 -3
  149. package/dist/src/tools/mcp-client.js +39 -11
  150. package/dist/src/tools/mcp-client.js.map +1 -1
  151. package/dist/src/tools/mcp-tool.d.ts +3 -1
  152. package/dist/src/tools/mcp-tool.js +37 -9
  153. package/dist/src/tools/mcp-tool.js.map +1 -1
  154. package/dist/src/tools/memoryTool.d.ts +14 -4
  155. package/dist/src/tools/memoryTool.js +98 -39
  156. package/dist/src/tools/memoryTool.js.map +1 -1
  157. package/dist/src/tools/read-data-file.d.ts +31 -0
  158. package/dist/src/tools/read-data-file.js +469 -0
  159. package/dist/src/tools/read-data-file.js.map +1 -0
  160. package/dist/src/tools/read-file.js +64 -5
  161. package/dist/src/tools/read-file.js.map +1 -1
  162. package/dist/src/tools/read-file.test.js +40 -6
  163. package/dist/src/tools/read-file.test.js.map +1 -1
  164. package/dist/src/tools/shell.d.ts +3 -1
  165. package/dist/src/tools/shell.js +25 -4
  166. package/dist/src/tools/shell.js.map +1 -1
  167. package/dist/src/tools/skill.d.ts +34 -0
  168. package/dist/src/tools/skill.js +143 -0
  169. package/dist/src/tools/skill.js.map +1 -0
  170. package/dist/src/tools/sql_db.d.ts +101 -0
  171. package/dist/src/tools/sql_db.js +1033 -0
  172. package/dist/src/tools/sql_db.js.map +1 -0
  173. package/dist/src/tools/sql_db_configure.d.ts +18 -0
  174. package/dist/src/tools/sql_db_configure.js +96 -0
  175. package/dist/src/tools/sql_db_configure.js.map +1 -0
  176. package/dist/src/tools/taskCompletion.d.ts +29 -0
  177. package/dist/src/tools/taskCompletion.js +231 -0
  178. package/dist/src/tools/taskCompletion.js.map +1 -0
  179. package/dist/src/tools/tool-error.d.ts +3 -1
  180. package/dist/src/tools/tool-error.js +3 -0
  181. package/dist/src/tools/tool-error.js.map +1 -1
  182. package/dist/src/tools/tool-names.d.ts +8 -0
  183. package/dist/src/tools/tool-names.js +8 -0
  184. package/dist/src/tools/tool-names.js.map +1 -1
  185. package/dist/src/tools/tool-registry.d.ts +22 -0
  186. package/dist/src/tools/tool-registry.js +41 -1
  187. package/dist/src/tools/tool-registry.js.map +1 -1
  188. package/dist/src/tools/tools.d.ts +18 -2
  189. package/dist/src/tools/tools.js +3 -0
  190. package/dist/src/tools/tools.js.map +1 -1
  191. package/dist/src/tools/web-fetch.js +24 -4
  192. package/dist/src/tools/web-fetch.js.map +1 -1
  193. package/dist/src/tools/web-search.js +160 -2
  194. package/dist/src/tools/web-search.js.map +1 -1
  195. package/dist/src/tools/workspace-error-helper.d.ts +9 -0
  196. package/dist/src/tools/workspace-error-helper.js +43 -0
  197. package/dist/src/tools/workspace-error-helper.js.map +1 -0
  198. package/dist/src/tools/workspace-error-helper.test.js +85 -0
  199. package/dist/src/tools/workspace-error-helper.test.js.map +1 -0
  200. package/dist/src/tools/write-file.js +42 -7
  201. package/dist/src/tools/write-file.js.map +1 -1
  202. package/dist/src/utils/environmentContext.js +3 -1
  203. package/dist/src/utils/environmentContext.js.map +1 -1
  204. package/dist/src/utils/environmentContext.test.js +3 -2
  205. package/dist/src/utils/environmentContext.test.js.map +1 -1
  206. package/dist/src/utils/fetch.d.ts +3 -1
  207. package/dist/src/utils/fetch.js +35 -2
  208. package/dist/src/utils/fetch.js.map +1 -1
  209. package/dist/src/utils/fileUtils.js +30 -3
  210. package/dist/src/utils/fileUtils.js.map +1 -1
  211. package/dist/src/utils/filesearch/fileSearch.d.ts +2 -0
  212. package/dist/src/utils/filesearch/fileSearch.js +38 -7
  213. package/dist/src/utils/filesearch/fileSearch.js.map +1 -1
  214. package/dist/src/utils/git-worktree-utils.d.ts +56 -0
  215. package/dist/src/utils/git-worktree-utils.js +176 -0
  216. package/dist/src/utils/git-worktree-utils.js.map +1 -0
  217. package/dist/src/utils/imageCompression.d.ts +34 -0
  218. package/dist/src/utils/imageCompression.js +170 -0
  219. package/dist/src/utils/imageCompression.js.map +1 -0
  220. package/dist/src/utils/messageTruncator.d.ts +51 -0
  221. package/dist/src/utils/messageTruncator.js +346 -0
  222. package/dist/src/utils/messageTruncator.js.map +1 -0
  223. package/dist/src/utils/pathReader.js +26 -6
  224. package/dist/src/utils/pathReader.js.map +1 -1
  225. package/dist/src/utils/skill.d.ts +65 -0
  226. package/dist/src/utils/skill.js +241 -0
  227. package/dist/src/utils/skill.js.map +1 -0
  228. package/dist/src/utils/textCleaning.d.ts +51 -0
  229. package/dist/src/utils/textCleaning.js +327 -0
  230. package/dist/src/utils/textCleaning.js.map +1 -0
  231. package/dist/tsconfig.tsbuildinfo +1 -1
  232. package/package.json +16 -2
  233. package/dist/src/tools/mcp-client-manager.test.js +0 -39
  234. package/dist/src/tools/mcp-client-manager.test.js.map +0 -1
  235. package/dist/src/tools/mcp-client.test.d.ts +0 -6
  236. package/dist/src/tools/mcp-client.test.js +0 -454
  237. package/dist/src/tools/mcp-client.test.js.map +0 -1
  238. package/dist/src/tools/mcp-tool.test.d.ts +0 -6
  239. package/dist/src/tools/mcp-tool.test.js +0 -576
  240. package/dist/src/tools/mcp-tool.test.js.map +0 -1
  241. package/dist/src/tools/memoryTool.test.d.ts +0 -6
  242. package/dist/src/tools/memoryTool.test.js +0 -420
  243. package/dist/src/tools/memoryTool.test.js.map +0 -1
  244. package/dist/src/tools/tool-registry.test.d.ts +0 -6
  245. package/dist/src/tools/tool-registry.test.js +0 -332
  246. package/dist/src/tools/tool-registry.test.js.map +0 -1
  247. /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