@nanocollective/nanocoder 1.14.3 → 1.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (185) hide show
  1. package/README.md +25 -1
  2. package/dist/ai-sdk-client.d.ts +22 -0
  3. package/dist/ai-sdk-client.d.ts.map +1 -0
  4. package/dist/ai-sdk-client.js +385 -0
  5. package/dist/ai-sdk-client.js.map +1 -0
  6. package/dist/app.d.ts.map +1 -1
  7. package/dist/app.js +1 -1
  8. package/dist/app.js.map +1 -1
  9. package/dist/client-factory.d.ts.map +1 -1
  10. package/dist/client-factory.js +5 -5
  11. package/dist/client-factory.js.map +1 -1
  12. package/dist/commands/index.d.ts +1 -0
  13. package/dist/commands/index.d.ts.map +1 -1
  14. package/dist/commands/index.js +1 -0
  15. package/dist/commands/index.js.map +1 -1
  16. package/dist/commands/recommendations.js +1 -1
  17. package/dist/commands/recommendations.js.map +1 -1
  18. package/dist/commands/streaming.d.ts +3 -0
  19. package/dist/commands/streaming.d.ts.map +1 -0
  20. package/dist/commands/streaming.js +23 -0
  21. package/dist/commands/streaming.js.map +1 -0
  22. package/dist/commands.d.ts.map +1 -1
  23. package/dist/commands.js +17 -3
  24. package/dist/commands.js.map +1 -1
  25. package/dist/components/assistant-message.d.ts +0 -1
  26. package/dist/components/assistant-message.d.ts.map +1 -1
  27. package/dist/components/assistant-message.js +70 -122
  28. package/dist/components/assistant-message.js.map +1 -1
  29. package/dist/components/thinking-indicator.js +1 -1
  30. package/dist/components/thinking-indicator.js.map +1 -1
  31. package/dist/components/user-input.d.ts.map +1 -1
  32. package/dist/components/user-input.js +135 -27
  33. package/dist/components/user-input.js.map +1 -1
  34. package/dist/components/user-message.d.ts.map +1 -1
  35. package/dist/components/user-message.js +34 -1
  36. package/dist/components/user-message.js.map +1 -1
  37. package/dist/config/preferences.d.ts +2 -0
  38. package/dist/config/preferences.d.ts.map +1 -1
  39. package/dist/config/preferences.js +10 -0
  40. package/dist/config/preferences.js.map +1 -1
  41. package/dist/hooks/useAppInitialization.d.ts.map +1 -1
  42. package/dist/hooks/useAppInitialization.js +2 -1
  43. package/dist/hooks/useAppInitialization.js.map +1 -1
  44. package/dist/hooks/useChatHandler.d.ts +2 -0
  45. package/dist/hooks/useChatHandler.d.ts.map +1 -1
  46. package/dist/hooks/useChatHandler.js +59 -9
  47. package/dist/hooks/useChatHandler.js.map +1 -1
  48. package/dist/mcp/mcp-client.d.ts +20 -1
  49. package/dist/mcp/mcp-client.d.ts.map +1 -1
  50. package/dist/mcp/mcp-client.js +57 -0
  51. package/dist/mcp/mcp-client.js.map +1 -1
  52. package/dist/message-handler.d.ts.map +1 -1
  53. package/dist/message-handler.js +7 -2
  54. package/dist/message-handler.js.map +1 -1
  55. package/dist/tool-calling/index.d.ts +1 -1
  56. package/dist/tool-calling/index.d.ts.map +1 -1
  57. package/dist/tool-calling/index.js +1 -1
  58. package/dist/tool-calling/index.js.map +1 -1
  59. package/dist/tool-calling/json-parser.d.ts +19 -2
  60. package/dist/tool-calling/json-parser.d.ts.map +1 -1
  61. package/dist/tool-calling/json-parser.js +65 -28
  62. package/dist/tool-calling/json-parser.js.map +1 -1
  63. package/dist/tool-calling/json-parser.spec.d.ts +2 -0
  64. package/dist/tool-calling/json-parser.spec.d.ts.map +1 -0
  65. package/dist/tool-calling/json-parser.spec.js +518 -0
  66. package/dist/tool-calling/json-parser.spec.js.map +1 -0
  67. package/dist/tool-calling/tool-parser.d.ts +20 -0
  68. package/dist/tool-calling/tool-parser.d.ts.map +1 -0
  69. package/dist/tool-calling/tool-parser.js +58 -0
  70. package/dist/tool-calling/tool-parser.js.map +1 -0
  71. package/dist/tool-calling/tool-parser.spec.d.ts +2 -0
  72. package/dist/tool-calling/tool-parser.spec.d.ts.map +1 -0
  73. package/dist/tool-calling/tool-parser.spec.js +250 -0
  74. package/dist/tool-calling/tool-parser.spec.js.map +1 -0
  75. package/dist/tool-calling/xml-parser.d.ts +17 -0
  76. package/dist/tool-calling/xml-parser.d.ts.map +1 -1
  77. package/dist/tool-calling/xml-parser.js +101 -13
  78. package/dist/tool-calling/xml-parser.js.map +1 -1
  79. package/dist/tool-calling/xml-parser.spec.d.ts +2 -0
  80. package/dist/tool-calling/xml-parser.spec.d.ts.map +1 -0
  81. package/dist/tool-calling/xml-parser.spec.js +437 -0
  82. package/dist/tool-calling/xml-parser.spec.js.map +1 -0
  83. package/dist/tools/create-file.d.ts.map +1 -1
  84. package/dist/tools/create-file.js +26 -23
  85. package/dist/tools/create-file.js.map +1 -1
  86. package/dist/tools/delete-lines.d.ts.map +1 -1
  87. package/dist/tools/delete-lines.js +29 -27
  88. package/dist/tools/delete-lines.js.map +1 -1
  89. package/dist/tools/execute-bash.d.ts.map +1 -1
  90. package/dist/tools/execute-bash.js +21 -19
  91. package/dist/tools/execute-bash.js.map +1 -1
  92. package/dist/tools/fetch-url.d.ts.map +1 -1
  93. package/dist/tools/fetch-url.js +21 -19
  94. package/dist/tools/fetch-url.js.map +1 -1
  95. package/dist/tools/index.d.ts +2 -2
  96. package/dist/tools/index.d.ts.map +1 -1
  97. package/dist/tools/index.js +8 -6
  98. package/dist/tools/index.js.map +1 -1
  99. package/dist/tools/insert-lines.d.ts.map +1 -1
  100. package/dist/tools/insert-lines.js +29 -27
  101. package/dist/tools/insert-lines.js.map +1 -1
  102. package/dist/tools/read-file.d.ts.map +1 -1
  103. package/dist/tools/read-file.js +23 -19
  104. package/dist/tools/read-file.js.map +1 -1
  105. package/dist/tools/read-many-files.d.ts.map +1 -1
  106. package/dist/tools/read-many-files.js +24 -20
  107. package/dist/tools/read-many-files.js.map +1 -1
  108. package/dist/tools/replace-lines.d.ts.map +1 -1
  109. package/dist/tools/replace-lines.js +33 -31
  110. package/dist/tools/replace-lines.js.map +1 -1
  111. package/dist/tools/search-files.d.ts.map +1 -1
  112. package/dist/tools/search-files.js +33 -31
  113. package/dist/tools/search-files.js.map +1 -1
  114. package/dist/tools/tool-manager.d.ts +35 -19
  115. package/dist/tools/tool-manager.d.ts.map +1 -1
  116. package/dist/tools/tool-manager.js +63 -33
  117. package/dist/tools/tool-manager.js.map +1 -1
  118. package/dist/tools/tool-registry.d.ts +121 -0
  119. package/dist/tools/tool-registry.d.ts.map +1 -0
  120. package/dist/tools/tool-registry.js +195 -0
  121. package/dist/tools/tool-registry.js.map +1 -0
  122. package/dist/tools/web-search.d.ts.map +1 -1
  123. package/dist/tools/web-search.js +25 -23
  124. package/dist/tools/web-search.js.map +1 -1
  125. package/dist/types/config.d.ts +2 -1
  126. package/dist/types/config.d.ts.map +1 -1
  127. package/dist/types/core.d.ts +58 -3
  128. package/dist/types/core.d.ts.map +1 -1
  129. package/dist/types/core.js +2 -0
  130. package/dist/types/core.js.map +1 -1
  131. package/dist/utils/file-autocomplete.d.ts +31 -0
  132. package/dist/utils/file-autocomplete.d.ts.map +1 -0
  133. package/dist/utils/file-autocomplete.js +156 -0
  134. package/dist/utils/file-autocomplete.js.map +1 -0
  135. package/dist/utils/file-autocomplete.spec.d.ts +2 -0
  136. package/dist/utils/file-autocomplete.spec.d.ts.map +1 -0
  137. package/dist/utils/file-autocomplete.spec.js +142 -0
  138. package/dist/utils/file-autocomplete.spec.js.map +1 -0
  139. package/dist/utils/file-content-loader.d.ts +31 -0
  140. package/dist/utils/file-content-loader.d.ts.map +1 -0
  141. package/dist/utils/file-content-loader.js +142 -0
  142. package/dist/utils/file-content-loader.js.map +1 -0
  143. package/dist/utils/file-content-loader.spec.d.ts +2 -0
  144. package/dist/utils/file-content-loader.spec.d.ts.map +1 -0
  145. package/dist/utils/file-content-loader.spec.js +140 -0
  146. package/dist/utils/file-content-loader.spec.js.map +1 -0
  147. package/dist/utils/file-mention-handler.d.ts +21 -0
  148. package/dist/utils/file-mention-handler.d.ts.map +1 -0
  149. package/dist/utils/file-mention-handler.js +59 -0
  150. package/dist/utils/file-mention-handler.js.map +1 -0
  151. package/dist/utils/file-mention-handler.spec.d.ts +2 -0
  152. package/dist/utils/file-mention-handler.spec.d.ts.map +1 -0
  153. package/dist/utils/file-mention-handler.spec.js +147 -0
  154. package/dist/utils/file-mention-handler.spec.js.map +1 -0
  155. package/dist/utils/file-mention-parser.d.ts +40 -0
  156. package/dist/utils/file-mention-parser.d.ts.map +1 -0
  157. package/dist/utils/file-mention-parser.js +122 -0
  158. package/dist/utils/file-mention-parser.js.map +1 -0
  159. package/dist/utils/file-mention-parser.spec.d.ts +2 -0
  160. package/dist/utils/file-mention-parser.spec.d.ts.map +1 -0
  161. package/dist/utils/file-mention-parser.spec.js +149 -0
  162. package/dist/utils/file-mention-parser.spec.js.map +1 -0
  163. package/dist/utils/fuzzy-matching.d.ts +13 -0
  164. package/dist/utils/fuzzy-matching.d.ts.map +1 -0
  165. package/dist/utils/fuzzy-matching.js +127 -0
  166. package/dist/utils/fuzzy-matching.js.map +1 -0
  167. package/dist/utils/fuzzy-matching.spec.d.ts +2 -0
  168. package/dist/utils/fuzzy-matching.spec.d.ts.map +1 -0
  169. package/dist/utils/fuzzy-matching.spec.js +123 -0
  170. package/dist/utils/fuzzy-matching.spec.js.map +1 -0
  171. package/dist/utils/prompt-assembly.spec.js +100 -2
  172. package/dist/utils/prompt-assembly.spec.js.map +1 -1
  173. package/dist/utils/prompt-processor.d.ts +2 -2
  174. package/dist/utils/prompt-processor.d.ts.map +1 -1
  175. package/dist/utils/prompt-processor.js +24 -41
  176. package/dist/utils/prompt-processor.js.map +1 -1
  177. package/package.json +7 -4
  178. package/dist/langgraph-client.d.ts +0 -19
  179. package/dist/langgraph-client.d.ts.map +0 -1
  180. package/dist/langgraph-client.js +0 -295
  181. package/dist/langgraph-client.js.map +0 -1
  182. package/dist/mcp/mcp-tool-adapter.d.ts +0 -22
  183. package/dist/mcp/mcp-tool-adapter.d.ts.map +0 -1
  184. package/dist/mcp/mcp-tool-adapter.js +0 -50
  185. package/dist/mcp/mcp-tool-adapter.js.map +0 -1
@@ -0,0 +1,518 @@
1
+ import test from 'ava';
2
+ import { parseJSONToolCalls, cleanJSONToolCalls, detectMalformedJSONToolCall, } from './json-parser.js';
3
+ console.log(`\njson-parser.spec.ts`);
4
+ // Malformed Detection Tests
5
+ test('detectMalformedJSONToolCall: detects missing arguments field', t => {
6
+ const content = `
7
+ {
8
+ "name": "read_file"
9
+ }
10
+ `;
11
+ const result = detectMalformedJSONToolCall(content);
12
+ t.truthy(result);
13
+ if (result) {
14
+ t.regex(result.error, /missing "arguments" field/i);
15
+ t.regex(result.examples, /Correct format/i);
16
+ }
17
+ });
18
+ test('detectMalformedJSONToolCall: detects missing name field', t => {
19
+ const content = `
20
+ {
21
+ "arguments": {
22
+ "path": "/path/to/file.txt"
23
+ }
24
+ }
25
+ `;
26
+ const result = detectMalformedJSONToolCall(content);
27
+ t.truthy(result);
28
+ if (result) {
29
+ t.regex(result.error, /missing "name" field/i);
30
+ t.regex(result.examples, /Correct format/i);
31
+ }
32
+ });
33
+ test('detectMalformedJSONToolCall: detects string arguments instead of object', t => {
34
+ const content = `
35
+ {
36
+ "name": "read_file",
37
+ "arguments": "/path/to/file.txt"
38
+ }
39
+ `;
40
+ const result = detectMalformedJSONToolCall(content);
41
+ t.truthy(result);
42
+ if (result) {
43
+ t.regex(result.error, /"arguments" must be an object/i);
44
+ t.regex(result.examples, /Correct format/i);
45
+ }
46
+ });
47
+ test('detectMalformedJSONToolCall: returns null for valid JSON', t => {
48
+ const content = `
49
+ {
50
+ "name": "read_file",
51
+ "arguments": {
52
+ "path": "/path/to/file.txt"
53
+ }
54
+ }
55
+ `;
56
+ const result = detectMalformedJSONToolCall(content);
57
+ t.is(result, null);
58
+ });
59
+ test('detectMalformedJSONToolCall: returns null for plain text', t => {
60
+ const content = 'Just some plain text without any JSON';
61
+ const result = detectMalformedJSONToolCall(content);
62
+ t.is(result, null);
63
+ });
64
+ test('detectMalformedJSONToolCall: includes helpful examples in error', t => {
65
+ const content = '{"name": "test"}';
66
+ const result = detectMalformedJSONToolCall(content);
67
+ t.truthy(result);
68
+ if (result) {
69
+ t.regex(result.examples, /"name":\s*"tool_name"/);
70
+ t.regex(result.examples, /"arguments":\s*\{/);
71
+ }
72
+ });
73
+ // Parse Tests
74
+ test('parseJSONToolCalls: parses single JSON tool call', t => {
75
+ const content = `
76
+ {
77
+ "name": "read_file",
78
+ "arguments": {
79
+ "path": "/path/to/file.txt"
80
+ }
81
+ }
82
+ `;
83
+ const calls = parseJSONToolCalls(content);
84
+ t.is(calls.length, 1);
85
+ t.is(calls[0].function.name, 'read_file');
86
+ t.deepEqual(calls[0].function.arguments, { path: '/path/to/file.txt' });
87
+ });
88
+ test('parseJSONToolCalls: parses JSON in markdown code block', t => {
89
+ const content = `
90
+ \`\`\`json
91
+ {
92
+ "name": "read_file",
93
+ "arguments": {
94
+ "path": "/path/to/file.txt"
95
+ }
96
+ }
97
+ \`\`\`
98
+ `;
99
+ const calls = parseJSONToolCalls(content);
100
+ t.is(calls.length, 1);
101
+ t.is(calls[0].function.name, 'read_file');
102
+ });
103
+ test('parseJSONToolCalls: parses JSON in code block without language', t => {
104
+ const content = `
105
+ \`\`\`
106
+ {
107
+ "name": "read_file",
108
+ "arguments": {
109
+ "path": "/path/to/file.txt"
110
+ }
111
+ }
112
+ \`\`\`
113
+ `;
114
+ const calls = parseJSONToolCalls(content);
115
+ t.is(calls.length, 1);
116
+ t.is(calls[0].function.name, 'read_file');
117
+ });
118
+ test('parseJSONToolCalls: parses multiple tool calls', t => {
119
+ const content = `
120
+ {
121
+ "name": "read_file",
122
+ "arguments": {
123
+ "path": "/file1.txt"
124
+ }
125
+ }
126
+
127
+ {
128
+ "name": "create_file",
129
+ "arguments": {
130
+ "path": "/file2.txt",
131
+ "content": "Hello"
132
+ }
133
+ }
134
+ `;
135
+ const calls = parseJSONToolCalls(content);
136
+ t.is(calls.length, 2);
137
+ t.is(calls[0].function.name, 'read_file');
138
+ t.is(calls[1].function.name, 'create_file');
139
+ });
140
+ test('parseJSONToolCalls: parses multiline JSON blocks', t => {
141
+ const content = `
142
+ {
143
+ "name": "create_file",
144
+ "arguments": {
145
+ "path": "/path/to/file.txt",
146
+ "content": "Multi\\nline\\ncontent"
147
+ }
148
+ }
149
+ `;
150
+ const calls = parseJSONToolCalls(content);
151
+ t.is(calls.length, 1);
152
+ t.is(calls[0].function.name, 'create_file');
153
+ // The \\n in JSON gets parsed as actual newline characters
154
+ t.true(calls[0].function.arguments.content.includes('\n'));
155
+ });
156
+ test('parseJSONToolCalls: parses inline JSON tool calls', t => {
157
+ const content = 'Here is a tool call: {"name": "read_file", "arguments": {"path": "/test.txt"}} and some more text';
158
+ const calls = parseJSONToolCalls(content);
159
+ t.is(calls.length, 1);
160
+ t.is(calls[0].function.name, 'read_file');
161
+ });
162
+ test('parseJSONToolCalls: handles nested objects in arguments', t => {
163
+ const content = `
164
+ {
165
+ "name": "complex_tool",
166
+ "arguments": {
167
+ "config": {
168
+ "nested": {
169
+ "value": 123
170
+ }
171
+ }
172
+ }
173
+ }
174
+ `;
175
+ const calls = parseJSONToolCalls(content);
176
+ t.is(calls.length, 1);
177
+ t.is(calls[0].function.name, 'complex_tool');
178
+ t.deepEqual(calls[0].function.arguments, {
179
+ config: { nested: { value: 123 } },
180
+ });
181
+ });
182
+ test('parseJSONToolCalls: handles arrays in arguments', t => {
183
+ const content = `
184
+ {
185
+ "name": "batch_tool",
186
+ "arguments": {
187
+ "files": ["file1.txt", "file2.txt", "file3.txt"]
188
+ }
189
+ }
190
+ `;
191
+ const calls = parseJSONToolCalls(content);
192
+ t.is(calls.length, 1);
193
+ t.deepEqual(calls[0].function.arguments, {
194
+ files: ['file1.txt', 'file2.txt', 'file3.txt'],
195
+ });
196
+ });
197
+ test('parseJSONToolCalls: handles empty arguments object', t => {
198
+ const content = `
199
+ {
200
+ "name": "no_args_tool",
201
+ "arguments": {}
202
+ }
203
+ `;
204
+ const calls = parseJSONToolCalls(content);
205
+ t.is(calls.length, 1);
206
+ t.is(calls[0].function.name, 'no_args_tool');
207
+ t.deepEqual(calls[0].function.arguments, {});
208
+ });
209
+ test('parseJSONToolCalls: returns empty array for empty JSON object', t => {
210
+ const content = '{}';
211
+ const calls = parseJSONToolCalls(content);
212
+ t.is(calls.length, 0);
213
+ });
214
+ test('parseJSONToolCalls: returns empty array for plain text', t => {
215
+ const content = 'Just some plain text without any tool calls';
216
+ const calls = parseJSONToolCalls(content);
217
+ t.is(calls.length, 0);
218
+ });
219
+ test('parseJSONToolCalls: returns empty array for empty string', t => {
220
+ const content = '';
221
+ const calls = parseJSONToolCalls(content);
222
+ t.is(calls.length, 0);
223
+ });
224
+ test('parseJSONToolCalls: deduplicates identical tool calls', t => {
225
+ const content = `
226
+ {
227
+ "name": "read_file",
228
+ "arguments": {
229
+ "path": "/test.txt"
230
+ }
231
+ }
232
+
233
+ {
234
+ "name": "read_file",
235
+ "arguments": {
236
+ "path": "/test.txt"
237
+ }
238
+ }
239
+ `;
240
+ const calls = parseJSONToolCalls(content);
241
+ // Should deduplicate to single call
242
+ t.is(calls.length, 1);
243
+ });
244
+ test('parseJSONToolCalls: preserves different tool calls', t => {
245
+ const content = `
246
+ {
247
+ "name": "read_file",
248
+ "arguments": {
249
+ "path": "/file1.txt"
250
+ }
251
+ }
252
+
253
+ {
254
+ "name": "read_file",
255
+ "arguments": {
256
+ "path": "/file2.txt"
257
+ }
258
+ }
259
+ `;
260
+ const calls = parseJSONToolCalls(content);
261
+ // Different arguments, should not deduplicate
262
+ t.is(calls.length, 2);
263
+ });
264
+ test('parseJSONToolCalls: generates unique IDs for tool calls', t => {
265
+ const content = `
266
+ {
267
+ "name": "read_file",
268
+ "arguments": {
269
+ "path": "/file1.txt"
270
+ }
271
+ }
272
+
273
+ {
274
+ "name": "read_file",
275
+ "arguments": {
276
+ "path": "/file2.txt"
277
+ }
278
+ }
279
+ `;
280
+ const calls = parseJSONToolCalls(content);
281
+ t.is(calls.length, 2);
282
+ t.not(calls[0].id, calls[1].id);
283
+ t.truthy(calls[0].id);
284
+ t.truthy(calls[1].id);
285
+ });
286
+ test('parseJSONToolCalls: handles malformed JSON gracefully', t => {
287
+ const content = `
288
+ {
289
+ "name": "read_file",
290
+ "arguments": {
291
+ "path": "/test.txt"
292
+ // missing closing braces
293
+ `;
294
+ const calls = parseJSONToolCalls(content);
295
+ // Should return empty array, not throw
296
+ t.is(calls.length, 0);
297
+ });
298
+ // Clean Content Tests
299
+ test('cleanJSONToolCalls: removes JSON tool call from content', t => {
300
+ const content = `
301
+ Here is some text before.
302
+
303
+ {
304
+ "name": "read_file",
305
+ "arguments": {
306
+ "path": "/test.txt"
307
+ }
308
+ }
309
+
310
+ And some text after.
311
+ `;
312
+ const calls = parseJSONToolCalls(content);
313
+ const cleaned = cleanJSONToolCalls(content, calls);
314
+ t.regex(cleaned, /Here is some text before/);
315
+ t.regex(cleaned, /And some text after/);
316
+ t.notRegex(cleaned, /"name":\s*"read_file"/);
317
+ });
318
+ test('cleanJSONToolCalls: removes code blocks containing tool calls', t => {
319
+ const content = `
320
+ Some text before.
321
+
322
+ \`\`\`json
323
+ {
324
+ "name": "read_file",
325
+ "arguments": {
326
+ "path": "/test.txt"
327
+ }
328
+ }
329
+ \`\`\`
330
+
331
+ Some text after.
332
+ `;
333
+ const calls = parseJSONToolCalls(content);
334
+ const cleaned = cleanJSONToolCalls(content, calls);
335
+ t.regex(cleaned, /Some text before/);
336
+ t.regex(cleaned, /Some text after/);
337
+ t.notRegex(cleaned, /```/);
338
+ t.notRegex(cleaned, /"name":\s*"read_file"/);
339
+ });
340
+ test('cleanJSONToolCalls: keeps code blocks without tool calls', t => {
341
+ const content = `
342
+ Some text before.
343
+
344
+ \`\`\`json
345
+ {
346
+ "someOtherData": "value"
347
+ }
348
+ \`\`\`
349
+
350
+ Some text after.
351
+ `;
352
+ const calls = parseJSONToolCalls(content);
353
+ const cleaned = cleanJSONToolCalls(content, calls);
354
+ // Should keep the code block since it doesn't contain a tool call
355
+ t.regex(cleaned, /```/);
356
+ t.regex(cleaned, /someOtherData/);
357
+ });
358
+ test('cleanJSONToolCalls: removes multiple tool calls', t => {
359
+ const content = `
360
+ {"name": "tool1", "arguments": {"a": 1}}
361
+ Some text in between.
362
+ {"name": "tool2", "arguments": {"b": 2}}
363
+ `;
364
+ const calls = parseJSONToolCalls(content);
365
+ const cleaned = cleanJSONToolCalls(content, calls);
366
+ t.regex(cleaned, /Some text in between/);
367
+ t.notRegex(cleaned, /"name":\s*"tool1"/);
368
+ t.notRegex(cleaned, /"name":\s*"tool2"/);
369
+ });
370
+ test('cleanJSONToolCalls: removes inline tool calls', t => {
371
+ const content = 'Here is text {"name": "read_file", "arguments": {"path": "/test.txt"}} and more text';
372
+ const calls = parseJSONToolCalls(content);
373
+ const cleaned = cleanJSONToolCalls(content, calls);
374
+ t.regex(cleaned, /Here is text/);
375
+ t.regex(cleaned, /and more text/);
376
+ t.notRegex(cleaned, /"name":\s*"read_file"/);
377
+ });
378
+ test('cleanJSONToolCalls: cleans up excessive whitespace', t => {
379
+ const content = `
380
+ Text before.
381
+
382
+
383
+ {
384
+ "name": "read_file",
385
+ "arguments": {
386
+ "path": "/test.txt"
387
+ }
388
+ }
389
+
390
+
391
+
392
+ Text after.
393
+ `;
394
+ const calls = parseJSONToolCalls(content);
395
+ const cleaned = cleanJSONToolCalls(content, calls);
396
+ // Should reduce multiple newlines
397
+ t.notRegex(cleaned, /\n\n\n\n/);
398
+ t.regex(cleaned, /Text before/);
399
+ t.regex(cleaned, /Text after/);
400
+ });
401
+ test('cleanJSONToolCalls: returns original content when no tool calls', t => {
402
+ const content = 'Just some plain text without any tool calls';
403
+ const cleaned = cleanJSONToolCalls(content, []);
404
+ t.is(cleaned, content);
405
+ });
406
+ test('cleanJSONToolCalls: handles empty content', t => {
407
+ const content = '';
408
+ const cleaned = cleanJSONToolCalls(content, []);
409
+ t.is(cleaned, '');
410
+ });
411
+ test('cleanJSONToolCalls: handles content with only tool calls', t => {
412
+ const content = `
413
+ {
414
+ "name": "read_file",
415
+ "arguments": {
416
+ "path": "/test.txt"
417
+ }
418
+ }
419
+ `;
420
+ const calls = parseJSONToolCalls(content);
421
+ const cleaned = cleanJSONToolCalls(content, calls);
422
+ // Should be empty or whitespace only
423
+ t.is(cleaned.trim(), '');
424
+ });
425
+ // Integration Tests
426
+ test('parseJSONToolCalls + cleanJSONToolCalls: full workflow', t => {
427
+ const content = `
428
+ I want to read this file:
429
+
430
+ {
431
+ "name": "read_file",
432
+ "arguments": {
433
+ "path": "/important.txt"
434
+ }
435
+ }
436
+
437
+ And then create a backup:
438
+
439
+ {
440
+ "name": "create_file",
441
+ "arguments": {
442
+ "path": "/backup.txt",
443
+ "content": "backup content"
444
+ }
445
+ }
446
+
447
+ That's all!
448
+ `;
449
+ const calls = parseJSONToolCalls(content);
450
+ const cleaned = cleanJSONToolCalls(content, calls);
451
+ // Verify parsing
452
+ t.is(calls.length, 2);
453
+ t.is(calls[0].function.name, 'read_file');
454
+ t.is(calls[1].function.name, 'create_file');
455
+ // Verify cleaning
456
+ t.regex(cleaned, /I want to read this file/);
457
+ t.regex(cleaned, /And then create a backup/);
458
+ t.regex(cleaned, /That's all!/);
459
+ t.notRegex(cleaned, /"name":\s*"read_file"/);
460
+ t.notRegex(cleaned, /"name":\s*"create_file"/);
461
+ });
462
+ test('parseJSONToolCalls: handles special characters in arguments', t => {
463
+ const content = `
464
+ {
465
+ "name": "create_file",
466
+ "arguments": {
467
+ "path": "/test.txt",
468
+ "content": "Special chars: \\"quotes\\", \\n newlines, \\t tabs"
469
+ }
470
+ }
471
+ `;
472
+ const calls = parseJSONToolCalls(content);
473
+ t.is(calls.length, 1);
474
+ t.is(calls[0].function.name, 'create_file');
475
+ t.truthy(calls[0].function.arguments);
476
+ });
477
+ test('parseJSONToolCalls: handles numbers in arguments', t => {
478
+ const content = `
479
+ {
480
+ "name": "repeat_tool",
481
+ "arguments": {
482
+ "count": 42,
483
+ "delay": 1.5
484
+ }
485
+ }
486
+ `;
487
+ const calls = parseJSONToolCalls(content);
488
+ t.is(calls.length, 1);
489
+ t.deepEqual(calls[0].function.arguments, { count: 42, delay: 1.5 });
490
+ });
491
+ test('parseJSONToolCalls: handles booleans in arguments', t => {
492
+ const content = `
493
+ {
494
+ "name": "config_tool",
495
+ "arguments": {
496
+ "enabled": true,
497
+ "debug": false
498
+ }
499
+ }
500
+ `;
501
+ const calls = parseJSONToolCalls(content);
502
+ t.is(calls.length, 1);
503
+ t.deepEqual(calls[0].function.arguments, { enabled: true, debug: false });
504
+ });
505
+ test('parseJSONToolCalls: handles null in arguments', t => {
506
+ const content = `
507
+ {
508
+ "name": "nullable_tool",
509
+ "arguments": {
510
+ "optionalValue": null
511
+ }
512
+ }
513
+ `;
514
+ const calls = parseJSONToolCalls(content);
515
+ t.is(calls.length, 1);
516
+ t.deepEqual(calls[0].function.arguments, { optionalValue: null });
517
+ });
518
+ //# sourceMappingURL=json-parser.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json-parser.spec.js","sourceRoot":"","sources":["../../source/tool-calling/json-parser.spec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import type { ToolCall } from '../types/index.js';
2
+ /**
3
+ * Result of parsing tool calls from content
4
+ */
5
+ type ParseResult = {
6
+ success: true;
7
+ toolCalls: ToolCall[];
8
+ cleanedContent: string;
9
+ } | {
10
+ success: false;
11
+ error: string;
12
+ examples: string;
13
+ };
14
+ /**
15
+ * Unified tool call parser that tries XML first, then falls back to JSON
16
+ * Returns errors for malformed tool calls instead of silently failing
17
+ */
18
+ export declare function parseToolCalls(content: string): ParseResult;
19
+ export {};
20
+ //# sourceMappingURL=tool-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-parser.d.ts","sourceRoot":"","sources":["../../source/tool-calling/tool-parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,eAAe,CAAC;AAQ5C;;GAEG;AACH,KAAK,WAAW,GACb;IACA,OAAO,EAAE,IAAI,CAAC;IACd,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;CACtB,GACD;IACA,OAAO,EAAE,KAAK,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAChB,CAAC;AAEL;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,CAwD3D"}
@@ -0,0 +1,58 @@
1
+ import { XMLToolCallParser } from '../tool-calling/xml-parser.js';
2
+ import { parseJSONToolCalls, cleanJSONToolCalls, detectMalformedJSONToolCall, } from '../tool-calling/json-parser.js';
3
+ /**
4
+ * Unified tool call parser that tries XML first, then falls back to JSON
5
+ * Returns errors for malformed tool calls instead of silently failing
6
+ */
7
+ export function parseToolCalls(content) {
8
+ // 1. Check for malformed XML patterns first (before validating with hasToolCalls)
9
+ const xmlMalformed = XMLToolCallParser.detectMalformedToolCall(content);
10
+ if (xmlMalformed) {
11
+ return {
12
+ success: false,
13
+ error: xmlMalformed.error,
14
+ examples: xmlMalformed.examples,
15
+ };
16
+ }
17
+ // 2. Try XML parser for valid tool calls
18
+ if (XMLToolCallParser.hasToolCalls(content)) {
19
+ // Parse valid XML tool calls
20
+ const parsedCalls = XMLToolCallParser.parseToolCalls(content);
21
+ const convertedCalls = XMLToolCallParser.convertToToolCalls(parsedCalls);
22
+ if (convertedCalls.length > 0) {
23
+ const cleanedContent = XMLToolCallParser.removeToolCallsFromContent(content);
24
+ return {
25
+ success: true,
26
+ toolCalls: convertedCalls,
27
+ cleanedContent,
28
+ };
29
+ }
30
+ }
31
+ // 3. Fall back to JSON parser
32
+ // Check for malformed JSON tool calls
33
+ const jsonMalformed = detectMalformedJSONToolCall(content);
34
+ if (jsonMalformed) {
35
+ return {
36
+ success: false,
37
+ error: jsonMalformed.error,
38
+ examples: jsonMalformed.examples,
39
+ };
40
+ }
41
+ // Parse valid JSON tool calls
42
+ const jsonCalls = parseJSONToolCalls(content);
43
+ if (jsonCalls.length > 0) {
44
+ const cleanedContent = cleanJSONToolCalls(content, jsonCalls);
45
+ return {
46
+ success: true,
47
+ toolCalls: jsonCalls,
48
+ cleanedContent,
49
+ };
50
+ }
51
+ // 4. No tool calls found - return original content
52
+ return {
53
+ success: true,
54
+ toolCalls: [],
55
+ cleanedContent: content,
56
+ };
57
+ }
58
+ //# sourceMappingURL=tool-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-parser.js","sourceRoot":"","sources":["../../source/tool-calling/tool-parser.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,iBAAiB,EAAC,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EACN,kBAAkB,EAClB,kBAAkB,EAClB,2BAA2B,GAC3B,MAAM,4BAA4B,CAAC;AAiBpC;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,OAAe;IAC7C,kFAAkF;IAClF,MAAM,YAAY,GAAG,iBAAiB,CAAC,uBAAuB,CAAC,OAAO,CAAC,CAAC;IACxE,IAAI,YAAY,EAAE,CAAC;QAClB,OAAO;YACN,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,YAAY,CAAC,KAAK;YACzB,QAAQ,EAAE,YAAY,CAAC,QAAQ;SAC/B,CAAC;IACH,CAAC;IAED,yCAAyC;IACzC,IAAI,iBAAiB,CAAC,YAAY,CAAC,OAAO,CAAC,EAAE,CAAC;QAC7C,6BAA6B;QAC7B,MAAM,WAAW,GAAG,iBAAiB,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QAC9D,MAAM,cAAc,GAAG,iBAAiB,CAAC,kBAAkB,CAAC,WAAW,CAAC,CAAC;QAEzE,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC/B,MAAM,cAAc,GACnB,iBAAiB,CAAC,0BAA0B,CAAC,OAAO,CAAC,CAAC;YACvD,OAAO;gBACN,OAAO,EAAE,IAAI;gBACb,SAAS,EAAE,cAAc;gBACzB,cAAc;aACd,CAAC;QACH,CAAC;IACF,CAAC;IAED,8BAA8B;IAC9B,sCAAsC;IACtC,MAAM,aAAa,GAAG,2BAA2B,CAAC,OAAO,CAAC,CAAC;IAC3D,IAAI,aAAa,EAAE,CAAC;QACnB,OAAO;YACN,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,aAAa,CAAC,KAAK;YAC1B,QAAQ,EAAE,aAAa,CAAC,QAAQ;SAChC,CAAC;IACH,CAAC;IAED,8BAA8B;IAC9B,MAAM,SAAS,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;IAC9C,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,MAAM,cAAc,GAAG,kBAAkB,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QAC9D,OAAO;YACN,OAAO,EAAE,IAAI;YACb,SAAS,EAAE,SAAS;YACpB,cAAc;SACd,CAAC;IACH,CAAC;IAED,mDAAmD;IACnD,OAAO;QACN,OAAO,EAAE,IAAI;QACb,SAAS,EAAE,EAAE;QACb,cAAc,EAAE,OAAO;KACvB,CAAC;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=tool-parser.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-parser.spec.d.ts","sourceRoot":"","sources":["../../source/tool-calling/tool-parser.spec.ts"],"names":[],"mappings":""}