@arcteninc/core 0.0.21 ā 0.0.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/ArctenAgent.d.ts +25 -0
- package/dist/components/ArctenAgent.d.ts.map +1 -1
- package/dist/components/ai-elements/prompt-input.d.ts +187 -0
- package/dist/components/ai-elements/prompt-input.d.ts.map +1 -0
- package/dist/components/ai-elements/reasoning.d.ts +17 -0
- package/dist/components/ai-elements/reasoning.d.ts.map +1 -0
- package/dist/components/ai-elements/response.d.ts +8 -0
- package/dist/components/ai-elements/response.d.ts.map +1 -0
- package/dist/components/ai-elements/shimmer.d.ts +10 -0
- package/dist/components/ai-elements/shimmer.d.ts.map +1 -0
- package/dist/components/tool-call-approval.d.ts +9 -0
- package/dist/components/tool-call-approval.d.ts.map +1 -0
- package/dist/components/tool-call-result.d.ts +8 -0
- package/dist/components/tool-call-result.d.ts.map +1 -0
- package/dist/components/ui/autotextarea.d.ts +19 -0
- package/dist/components/ui/autotextarea.d.ts.map +1 -0
- package/dist/components/ui/badge.d.ts +10 -0
- package/dist/components/ui/badge.d.ts.map +1 -0
- package/dist/components/ui/button.d.ts +14 -0
- package/dist/components/ui/button.d.ts.map +1 -0
- package/dist/components/ui/collapsible.d.ts +6 -0
- package/dist/components/ui/collapsible.d.ts.map +1 -0
- package/dist/components/ui/command.d.ts +19 -0
- package/dist/components/ui/command.d.ts.map +1 -0
- package/dist/components/ui/dialog.d.ts +16 -0
- package/dist/components/ui/dialog.d.ts.map +1 -0
- package/dist/components/ui/dropdown-menu.d.ts +26 -0
- package/dist/components/ui/dropdown-menu.d.ts.map +1 -0
- package/dist/components/ui/hover-card.d.ts +7 -0
- package/dist/components/ui/hover-card.d.ts.map +1 -0
- package/dist/components/ui/input-group.d.ts +17 -0
- package/dist/components/ui/input-group.d.ts.map +1 -0
- package/dist/components/ui/input.d.ts +4 -0
- package/dist/components/ui/input.d.ts.map +1 -0
- package/dist/components/ui/kbd.d.ts +4 -0
- package/dist/components/ui/kbd.d.ts.map +1 -0
- package/dist/components/ui/select.d.ts +16 -0
- package/dist/components/ui/select.d.ts.map +1 -0
- package/dist/components/ui/textarea.d.ts +4 -0
- package/dist/components/ui/textarea.d.ts.map +1 -0
- package/dist/components/ui/tooltip.d.ts +8 -0
- package/dist/components/ui/tooltip.d.ts.map +1 -0
- package/dist/index.cjs +20 -7
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.mjs +2361 -2537
- package/dist/lib/useAgent.d.ts +3 -0
- package/dist/lib/useAgent.d.ts.map +1 -0
- package/dist/lib/utils.d.ts +3 -0
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/server.d.ts +9 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/types/tool-description.d.ts +18 -0
- package/dist/types/tool-description.d.ts.map +1 -0
- package/dist/types/use-agent.d.ts +73 -0
- package/dist/types/use-agent.d.ts.map +1 -0
- package/dist/utils/extract-tool-metadata.d.ts +26 -0
- package/dist/utils/extract-tool-metadata.d.ts.map +1 -0
- package/dist/verifyToken.d.ts +19 -0
- package/dist/verifyToken.d.ts.map +1 -0
- package/package.json +7 -4
- package/scripts/cli-extract-types-auto.ts +598 -541
|
@@ -1,542 +1,599 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
|
-
/**
|
|
3
|
-
* Automatically discover and extract types for tools used in ArctenAgent/useAgent
|
|
4
|
-
* Scans the project, finds all tool usages, and generates metadata only for used tools
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import * as ts from 'typescript';
|
|
8
|
-
import * as fs from 'fs';
|
|
9
|
-
import * as path from 'path';
|
|
10
|
-
import { glob } from 'glob';
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
default?: string;
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
properties?: Record<string,
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
if (
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
const
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
if (type.
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
if (
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
const
|
|
534
|
-
|
|
535
|
-
const
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
2
|
+
/**
|
|
3
|
+
* Automatically discover and extract types for tools used in ArctenAgent/useAgent
|
|
4
|
+
* Scans the project, finds all tool usages, and generates metadata only for used tools
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import * as ts from 'typescript';
|
|
8
|
+
import * as fs from 'fs';
|
|
9
|
+
import * as path from 'path';
|
|
10
|
+
import { glob } from 'glob';
|
|
11
|
+
|
|
12
|
+
// JSON Schema compatible format
|
|
13
|
+
interface JsonSchemaProperty {
|
|
14
|
+
type: string;
|
|
15
|
+
description?: string;
|
|
16
|
+
default?: string;
|
|
17
|
+
enum?: string[]; // For enum types
|
|
18
|
+
items?: JsonSchemaProperty; // For array types
|
|
19
|
+
properties?: Record<string, JsonSchemaProperty>; // For object types
|
|
20
|
+
required?: string[]; // For nested objects
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
interface FunctionMetadata {
|
|
24
|
+
name: string;
|
|
25
|
+
description: string;
|
|
26
|
+
parameters: {
|
|
27
|
+
type: 'object';
|
|
28
|
+
properties: Record<string, JsonSchemaProperty>;
|
|
29
|
+
required?: string[]; // Array of required parameter names
|
|
30
|
+
};
|
|
31
|
+
returnType?: string;
|
|
32
|
+
isAsync?: boolean;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
interface GeneratedMetadata {
|
|
36
|
+
generated: string;
|
|
37
|
+
discoveredFrom: string[];
|
|
38
|
+
functions: Record<string, FunctionMetadata>;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
interface ToolUsage {
|
|
42
|
+
toolNames: Set<string>;
|
|
43
|
+
file: string;
|
|
44
|
+
component: 'ArctenAgent' | 'useAgent';
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Find all files that use ArctenAgent or useAgent
|
|
49
|
+
*/
|
|
50
|
+
async function findToolUsageFiles(projectRoot: string): Promise<string[]> {
|
|
51
|
+
const pattern = path.join(projectRoot, '**/*.{ts,tsx}').replace(/\\/g, '/');
|
|
52
|
+
const files = await glob(pattern, {
|
|
53
|
+
ignore: ['**/node_modules/**', '**/dist/**', '**/.next/**', '**/build/**'],
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
console.log(`š Found ${files.length} TypeScript files to scan`);
|
|
57
|
+
return files;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Extract tool names from ArctenAgent or useAgent usage
|
|
62
|
+
*/
|
|
63
|
+
function extractToolNamesFromFile(sourceFile: ts.SourceFile): ToolUsage[] {
|
|
64
|
+
const usages: ToolUsage[] = [];
|
|
65
|
+
|
|
66
|
+
function visit(node: ts.Node) {
|
|
67
|
+
// Check for <ArctenAgent tools={[...]} safeTools={[...]} />
|
|
68
|
+
if (ts.isJsxElement(node) || ts.isJsxSelfClosingElement(node)) {
|
|
69
|
+
const tagName = ts.isJsxElement(node)
|
|
70
|
+
? node.openingElement.tagName.getText(sourceFile)
|
|
71
|
+
: node.tagName.getText(sourceFile);
|
|
72
|
+
|
|
73
|
+
if (tagName === 'ArctenAgent') {
|
|
74
|
+
const toolNames = new Set<string>();
|
|
75
|
+
const attributes = ts.isJsxElement(node)
|
|
76
|
+
? node.openingElement.attributes.properties
|
|
77
|
+
: node.attributes.properties;
|
|
78
|
+
|
|
79
|
+
for (const attr of attributes) {
|
|
80
|
+
if (ts.isJsxAttribute(attr)) {
|
|
81
|
+
const attrName = attr.name.getText(sourceFile);
|
|
82
|
+
if (attrName === 'tools' || attrName === 'safeTools') {
|
|
83
|
+
if (attr.initializer && ts.isJsxExpression(attr.initializer)) {
|
|
84
|
+
const expr = attr.initializer.expression;
|
|
85
|
+
if (expr && ts.isArrayLiteralExpression(expr)) {
|
|
86
|
+
for (const element of expr.elements) {
|
|
87
|
+
const name = element.getText(sourceFile).trim();
|
|
88
|
+
// Remove any object property access (e.g., tools.getOrders -> getOrders)
|
|
89
|
+
const simpleName = name.split('.').pop() || name;
|
|
90
|
+
toolNames.add(simpleName);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (toolNames.size > 0) {
|
|
99
|
+
usages.push({
|
|
100
|
+
toolNames,
|
|
101
|
+
file: sourceFile.fileName,
|
|
102
|
+
component: 'ArctenAgent',
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Check for useAgent({ tools: [...], safeTools: [...] })
|
|
109
|
+
if (ts.isCallExpression(node)) {
|
|
110
|
+
const expr = node.expression;
|
|
111
|
+
if (ts.isIdentifier(expr) && expr.getText(sourceFile) === 'useAgent') {
|
|
112
|
+
const toolNames = new Set<string>();
|
|
113
|
+
|
|
114
|
+
if (node.arguments.length > 0) {
|
|
115
|
+
const arg = node.arguments[0];
|
|
116
|
+
if (ts.isObjectLiteralExpression(arg)) {
|
|
117
|
+
for (const prop of arg.properties) {
|
|
118
|
+
if (ts.isPropertyAssignment(prop)) {
|
|
119
|
+
const propName = prop.name.getText(sourceFile);
|
|
120
|
+
if (propName === 'tools' || propName === 'safeTools') {
|
|
121
|
+
if (ts.isArrayLiteralExpression(prop.initializer)) {
|
|
122
|
+
for (const element of prop.initializer.elements) {
|
|
123
|
+
const name = element.getText(sourceFile).trim();
|
|
124
|
+
const simpleName = name.split('.').pop() || name;
|
|
125
|
+
toolNames.add(simpleName);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (toolNames.size > 0) {
|
|
135
|
+
usages.push({
|
|
136
|
+
toolNames,
|
|
137
|
+
file: sourceFile.fileName,
|
|
138
|
+
component: 'useAgent',
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
ts.forEachChild(node, visit);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
visit(sourceFile);
|
|
148
|
+
return usages;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Find where a tool function is defined
|
|
153
|
+
*/
|
|
154
|
+
function findFunctionDefinition(
|
|
155
|
+
functionName: string,
|
|
156
|
+
sourceFile: ts.SourceFile,
|
|
157
|
+
program: ts.Program
|
|
158
|
+
): { sourceFile: ts.SourceFile; node: ts.FunctionDeclaration } | null {
|
|
159
|
+
// First, check if it's defined in the current file
|
|
160
|
+
let foundNode: ts.FunctionDeclaration | null = null;
|
|
161
|
+
|
|
162
|
+
function visitForDefinition(node: ts.Node) {
|
|
163
|
+
if (ts.isFunctionDeclaration(node) && node.name) {
|
|
164
|
+
if (node.name.getText(sourceFile) === functionName) {
|
|
165
|
+
foundNode = node;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
if (!foundNode) {
|
|
169
|
+
ts.forEachChild(node, visitForDefinition);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
visitForDefinition(sourceFile);
|
|
174
|
+
|
|
175
|
+
if (foundNode) {
|
|
176
|
+
return { sourceFile, node: foundNode };
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// If not found, check imports
|
|
180
|
+
const imports: { name: string; from: string }[] = [];
|
|
181
|
+
|
|
182
|
+
function visitForImports(node: ts.Node) {
|
|
183
|
+
if (ts.isImportDeclaration(node)) {
|
|
184
|
+
const moduleSpecifier = node.moduleClause;
|
|
185
|
+
if (moduleSpecifier && ts.isImportClause(moduleSpecifier)) {
|
|
186
|
+
const namedBindings = moduleSpecifier.namedBindings;
|
|
187
|
+
if (namedBindings && ts.isNamedImports(namedBindings)) {
|
|
188
|
+
for (const element of namedBindings.elements) {
|
|
189
|
+
const importedName = element.name.getText(sourceFile);
|
|
190
|
+
if (importedName === functionName) {
|
|
191
|
+
const modulePath = (node.moduleSpecifier as ts.StringLiteral).text;
|
|
192
|
+
imports.push({ name: importedName, from: modulePath });
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
ts.forEachChild(node, visitForImports);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
visitForImports(sourceFile);
|
|
202
|
+
|
|
203
|
+
// Follow imports to find definition
|
|
204
|
+
for (const imp of imports) {
|
|
205
|
+
const resolvedPath = resolveImportPath(imp.from, sourceFile.fileName);
|
|
206
|
+
if (resolvedPath) {
|
|
207
|
+
const importedSourceFile = program.getSourceFile(resolvedPath);
|
|
208
|
+
if (importedSourceFile) {
|
|
209
|
+
const result = findFunctionDefinition(functionName, importedSourceFile, program);
|
|
210
|
+
if (result) {
|
|
211
|
+
return result;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
return null;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Resolve import path to actual file path
|
|
222
|
+
*/
|
|
223
|
+
function resolveImportPath(importPath: string, fromFile: string): string | null {
|
|
224
|
+
if (importPath.startsWith('.')) {
|
|
225
|
+
// Relative import
|
|
226
|
+
const dir = path.dirname(fromFile);
|
|
227
|
+
const resolved = path.resolve(dir, importPath);
|
|
228
|
+
|
|
229
|
+
// Try common extensions
|
|
230
|
+
const extensions = ['.ts', '.tsx', '.js', '.jsx'];
|
|
231
|
+
for (const ext of extensions) {
|
|
232
|
+
const withExt = resolved + ext;
|
|
233
|
+
if (fs.existsSync(withExt)) {
|
|
234
|
+
return withExt;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// Try index files
|
|
239
|
+
for (const ext of extensions) {
|
|
240
|
+
const indexPath = path.join(resolved, `index${ext}`);
|
|
241
|
+
if (fs.existsSync(indexPath)) {
|
|
242
|
+
return indexPath;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
return resolved;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// Node modules - we'll skip for now
|
|
250
|
+
return null;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Serialize a TypeScript type to JSON Schema format
|
|
255
|
+
* Returns: { isOptional, schema }
|
|
256
|
+
*/
|
|
257
|
+
function serializeType(
|
|
258
|
+
type: ts.Type,
|
|
259
|
+
checker: ts.TypeChecker,
|
|
260
|
+
visited = new Set<number>(),
|
|
261
|
+
depth = 0
|
|
262
|
+
): { isOptional: boolean; schema: JsonSchemaProperty } {
|
|
263
|
+
const typeString = checker.typeToString(type);
|
|
264
|
+
|
|
265
|
+
if (depth > 10) {
|
|
266
|
+
return { isOptional: false, schema: { type: 'any' } };
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
const typeId = (type as any).id;
|
|
270
|
+
if (typeId !== undefined && visited.has(typeId)) {
|
|
271
|
+
return { isOptional: false, schema: { type: 'any' } };
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// Handle primitives
|
|
275
|
+
if (type.flags & ts.TypeFlags.String) {
|
|
276
|
+
return { isOptional: false, schema: { type: 'string' } };
|
|
277
|
+
}
|
|
278
|
+
if (type.flags & ts.TypeFlags.Number) {
|
|
279
|
+
return { isOptional: false, schema: { type: 'number' } };
|
|
280
|
+
}
|
|
281
|
+
if (type.flags & ts.TypeFlags.Boolean) {
|
|
282
|
+
return { isOptional: false, schema: { type: 'boolean' } };
|
|
283
|
+
}
|
|
284
|
+
if (type.flags & ts.TypeFlags.Undefined || type.flags & ts.TypeFlags.Void) {
|
|
285
|
+
return { isOptional: true, schema: { type: 'null' } };
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// Handle union types
|
|
289
|
+
if (type.isUnion()) {
|
|
290
|
+
const types = type.types;
|
|
291
|
+
|
|
292
|
+
// Check if it's a string literal union (enum)
|
|
293
|
+
const stringLiterals = types
|
|
294
|
+
.filter(t => t.flags & ts.TypeFlags.StringLiteral)
|
|
295
|
+
.map(t => (t as ts.StringLiteralType).value);
|
|
296
|
+
|
|
297
|
+
if (stringLiterals.length === types.length) {
|
|
298
|
+
return {
|
|
299
|
+
isOptional: false,
|
|
300
|
+
schema: { type: 'string', enum: stringLiterals }
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// Check for optional (T | undefined)
|
|
305
|
+
const hasUndefined = types.some(t => t.flags & ts.TypeFlags.Undefined);
|
|
306
|
+
const nonUndefinedTypes = types.filter(t => !(t.flags & ts.TypeFlags.Undefined));
|
|
307
|
+
|
|
308
|
+
if (hasUndefined && nonUndefinedTypes.length === 1) {
|
|
309
|
+
const result = serializeType(nonUndefinedTypes[0], checker, visited, depth + 1);
|
|
310
|
+
return { isOptional: true, schema: result.schema };
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// Generic union - just use string representation
|
|
314
|
+
return {
|
|
315
|
+
isOptional: false,
|
|
316
|
+
schema: { type: types.map(t => checker.typeToString(t)).join(' | ') }
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// Handle arrays
|
|
321
|
+
if (checker.isArrayType(type)) {
|
|
322
|
+
const typeArgs = (type as ts.TypeReference).typeArguments;
|
|
323
|
+
if (typeArgs && typeArgs.length > 0) {
|
|
324
|
+
const itemResult = serializeType(typeArgs[0], checker, visited, depth + 1);
|
|
325
|
+
return {
|
|
326
|
+
isOptional: false,
|
|
327
|
+
schema: { type: 'array', items: itemResult.schema }
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
return { isOptional: false, schema: { type: 'array' } };
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// Handle objects
|
|
334
|
+
if (type.flags & ts.TypeFlags.Object) {
|
|
335
|
+
if (typeId !== undefined) {
|
|
336
|
+
visited.add(typeId);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
const properties: Record<string, JsonSchemaProperty> = {};
|
|
340
|
+
const required: string[] = [];
|
|
341
|
+
const props = checker.getPropertiesOfType(type);
|
|
342
|
+
|
|
343
|
+
if (props.length > 0) {
|
|
344
|
+
for (const prop of props) {
|
|
345
|
+
const propDeclaration = prop.valueDeclaration || prop.declarations?.[0];
|
|
346
|
+
|
|
347
|
+
if (propDeclaration) {
|
|
348
|
+
const propType = checker.getTypeOfSymbolAtLocation(prop, propDeclaration);
|
|
349
|
+
const isOptional = (prop.flags & ts.SymbolFlags.Optional) !== 0;
|
|
350
|
+
|
|
351
|
+
const propResult = serializeType(propType, checker, visited, depth + 1);
|
|
352
|
+
properties[prop.name] = propResult.schema;
|
|
353
|
+
|
|
354
|
+
// Track required properties
|
|
355
|
+
if (!isOptional && !propResult.isOptional) {
|
|
356
|
+
required.push(prop.name);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
const schema: JsonSchemaProperty = {
|
|
362
|
+
type: 'object',
|
|
363
|
+
properties
|
|
364
|
+
};
|
|
365
|
+
|
|
366
|
+
if (required.length > 0) {
|
|
367
|
+
schema.required = required;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
return { isOptional: false, schema };
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
// Fallback
|
|
375
|
+
return {
|
|
376
|
+
isOptional: false,
|
|
377
|
+
schema: { type: typeString.length < 100 ? typeString : 'any' }
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* Extract metadata from a function
|
|
383
|
+
*/
|
|
384
|
+
function extractFunctionMetadata(
|
|
385
|
+
node: ts.FunctionDeclaration,
|
|
386
|
+
checker: ts.TypeChecker,
|
|
387
|
+
sourceFile: ts.SourceFile
|
|
388
|
+
): FunctionMetadata | null {
|
|
389
|
+
if (!node.name) {
|
|
390
|
+
return null;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
const functionName = node.name.getText(sourceFile);
|
|
394
|
+
|
|
395
|
+
const jsDocTags = ts.getJSDocTags(node);
|
|
396
|
+
const jsDocComments = ts.getJSDocCommentsAndTags(node);
|
|
397
|
+
|
|
398
|
+
let description = `Execute ${functionName}`;
|
|
399
|
+
for (const comment of jsDocComments) {
|
|
400
|
+
if (ts.isJSDoc(comment) && comment.comment) {
|
|
401
|
+
if (typeof comment.comment === 'string') {
|
|
402
|
+
description = comment.comment.trim();
|
|
403
|
+
}
|
|
404
|
+
break;
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
const paramDescriptions = new Map<string, string>();
|
|
409
|
+
for (const tag of jsDocTags) {
|
|
410
|
+
if (tag.tagName.text === 'param' && ts.isJSDocParameterTag(tag)) {
|
|
411
|
+
const paramName = tag.name?.getText(sourceFile);
|
|
412
|
+
const paramDesc = typeof tag.comment === 'string' ? tag.comment.trim() : '';
|
|
413
|
+
if (paramName && paramDesc) {
|
|
414
|
+
paramDescriptions.set(paramName, paramDesc);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
const properties: Record<string, JsonSchemaProperty> = {};
|
|
420
|
+
const required: string[] = [];
|
|
421
|
+
const isAsync = node.modifiers?.some(m => m.kind === ts.SyntaxKind.AsyncKeyword) || false;
|
|
422
|
+
|
|
423
|
+
for (const param of node.parameters) {
|
|
424
|
+
const paramName = param.name.getText(sourceFile);
|
|
425
|
+
const hasDefault = param.initializer !== undefined;
|
|
426
|
+
|
|
427
|
+
let propSchema: JsonSchemaProperty;
|
|
428
|
+
let isOptional = false;
|
|
429
|
+
|
|
430
|
+
if (param.type) {
|
|
431
|
+
const type = checker.getTypeFromTypeNode(param.type);
|
|
432
|
+
const result = serializeType(type, checker);
|
|
433
|
+
propSchema = result.schema;
|
|
434
|
+
isOptional = result.isOptional;
|
|
435
|
+
} else {
|
|
436
|
+
propSchema = { type: 'any' };
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
// Check if parameter has default value or question mark
|
|
440
|
+
const hasQuestionMark = param.questionToken !== undefined;
|
|
441
|
+
if (hasDefault || hasQuestionMark) {
|
|
442
|
+
isOptional = true;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
// Add default value if present
|
|
446
|
+
if (hasDefault) {
|
|
447
|
+
propSchema.default = param.initializer!.getText(sourceFile);
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
// Add description from JSDoc
|
|
451
|
+
if (paramDescriptions.has(paramName)) {
|
|
452
|
+
propSchema.description = paramDescriptions.get(paramName);
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
properties[paramName] = propSchema;
|
|
456
|
+
|
|
457
|
+
// Track required params
|
|
458
|
+
if (!isOptional) {
|
|
459
|
+
required.push(paramName);
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
let returnType = 'any';
|
|
464
|
+
if (node.type) {
|
|
465
|
+
returnType = node.type.getText(sourceFile);
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
return {
|
|
469
|
+
name: functionName,
|
|
470
|
+
description,
|
|
471
|
+
parameters: {
|
|
472
|
+
type: 'object',
|
|
473
|
+
properties,
|
|
474
|
+
required: required.length > 0 ? required : undefined
|
|
475
|
+
},
|
|
476
|
+
returnType,
|
|
477
|
+
isAsync,
|
|
478
|
+
};
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
/**
|
|
482
|
+
* Main function
|
|
483
|
+
*/
|
|
484
|
+
async function autoDiscoverAndExtract(projectRoot: string, outputPath: string) {
|
|
485
|
+
console.log(`\nš Auto-discovering tools in: ${projectRoot}\n`);
|
|
486
|
+
|
|
487
|
+
// Find all TypeScript files
|
|
488
|
+
const files = await findToolUsageFiles(projectRoot);
|
|
489
|
+
|
|
490
|
+
// Read tsconfig
|
|
491
|
+
const configPath = ts.findConfigFile(projectRoot, ts.sys.fileExists, 'tsconfig.json');
|
|
492
|
+
let compilerOptions: ts.CompilerOptions = {
|
|
493
|
+
target: ts.ScriptTarget.ESNext,
|
|
494
|
+
module: ts.ModuleKind.ESNext,
|
|
495
|
+
jsx: ts.JsxEmit.React,
|
|
496
|
+
};
|
|
497
|
+
|
|
498
|
+
if (configPath) {
|
|
499
|
+
const config = ts.readConfigFile(configPath, ts.sys.readFile);
|
|
500
|
+
const parsed = ts.parseJsonConfigFileContent(config.config, ts.sys, path.dirname(configPath));
|
|
501
|
+
compilerOptions = parsed.options;
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
// Create program with all files
|
|
505
|
+
const program = ts.createProgram(files, compilerOptions);
|
|
506
|
+
const checker = program.getTypeChecker();
|
|
507
|
+
|
|
508
|
+
// Scan for tool usages
|
|
509
|
+
const allToolUsages: ToolUsage[] = [];
|
|
510
|
+
const allToolNames = new Set<string>();
|
|
511
|
+
|
|
512
|
+
for (const file of files) {
|
|
513
|
+
const sourceFile = program.getSourceFile(file);
|
|
514
|
+
if (sourceFile) {
|
|
515
|
+
const usages = extractToolNamesFromFile(sourceFile);
|
|
516
|
+
if (usages.length > 0) {
|
|
517
|
+
allToolUsages.push(...usages);
|
|
518
|
+
usages.forEach(u => u.toolNames.forEach(name => allToolNames.add(name)));
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
console.log(`ā Found ${allToolUsages.length} usage site(s) with ${allToolNames.size} unique tool(s)`);
|
|
524
|
+
allToolUsages.forEach(usage => {
|
|
525
|
+
console.log(` - ${usage.component} in ${path.relative(projectRoot, usage.file)}`);
|
|
526
|
+
console.log(` Tools: ${Array.from(usage.toolNames).join(', ')}`);
|
|
527
|
+
});
|
|
528
|
+
|
|
529
|
+
// Extract metadata for discovered tools
|
|
530
|
+
console.log(`\nš Extracting types for discovered tools...\n`);
|
|
531
|
+
|
|
532
|
+
const functionsMap: Record<string, FunctionMetadata> = {};
|
|
533
|
+
const discoveredFrom: string[] = [];
|
|
534
|
+
|
|
535
|
+
for (const toolName of allToolNames) {
|
|
536
|
+
let found = false;
|
|
537
|
+
|
|
538
|
+
// Search in all files for the definition
|
|
539
|
+
for (const file of files) {
|
|
540
|
+
const sourceFile = program.getSourceFile(file);
|
|
541
|
+
if (sourceFile) {
|
|
542
|
+
const result = findFunctionDefinition(toolName, sourceFile, program);
|
|
543
|
+
if (result) {
|
|
544
|
+
const metadata = extractFunctionMetadata(result.node, checker, result.sourceFile);
|
|
545
|
+
if (metadata) {
|
|
546
|
+
functionsMap[toolName] = metadata;
|
|
547
|
+
discoveredFrom.push(path.relative(projectRoot, result.sourceFile.fileName));
|
|
548
|
+
console.log(` ā ${toolName} (from ${path.relative(projectRoot, result.sourceFile.fileName)})`);
|
|
549
|
+
found = true;
|
|
550
|
+
break;
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
if (!found) {
|
|
557
|
+
console.log(` ā ${toolName} (definition not found)`);
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
// Generate output
|
|
562
|
+
const output: GeneratedMetadata = {
|
|
563
|
+
generated: new Date().toISOString(),
|
|
564
|
+
discoveredFrom: Array.from(new Set(discoveredFrom)),
|
|
565
|
+
functions: functionsMap,
|
|
566
|
+
};
|
|
567
|
+
|
|
568
|
+
const outputDir = path.dirname(outputPath);
|
|
569
|
+
if (!fs.existsSync(outputDir)) {
|
|
570
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
// Generate TypeScript module instead of JSON for easier bundler integration
|
|
574
|
+
const tsContent = `// Auto-generated by arcten-extract-types
|
|
575
|
+
// Do not edit this file manually
|
|
576
|
+
|
|
577
|
+
export const toolMetadata = ${JSON.stringify(output, null, 2)} as const;
|
|
578
|
+
`;
|
|
579
|
+
|
|
580
|
+
fs.writeFileSync(outputPath, tsContent);
|
|
581
|
+
console.log(`\nā
Generated metadata for ${Object.keys(functionsMap).length} tool(s)`);
|
|
582
|
+
console.log(`š Output: ${outputPath}`);
|
|
583
|
+
console.log(`\nš” Usage in your component:`);
|
|
584
|
+
console.log(` import { toolMetadata } from './.arcten/tool-metadata';`);
|
|
585
|
+
console.log(` useAgent({ tools: [...], toolMetadata: toolMetadata.functions })\n`);
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
// CLI
|
|
589
|
+
if (import.meta.main) {
|
|
590
|
+
const args = process.argv.slice(2);
|
|
591
|
+
const projectRoot = args[0] ? path.resolve(args[0]) : process.cwd();
|
|
592
|
+
const outputPath = args[1]
|
|
593
|
+
? path.resolve(args[1])
|
|
594
|
+
: path.join(projectRoot, '.arcten', 'tool-metadata.ts');
|
|
595
|
+
|
|
596
|
+
autoDiscoverAndExtract(projectRoot, outputPath);
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
export { autoDiscoverAndExtract };
|