@arcteninc/core 0.0.16 ā 0.0.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +50 -4
- package/dist/components/ArctenAgent.d.ts.map +1 -0
- package/dist/components/ai-elements/prompt-input.d.ts.map +1 -0
- package/dist/components/ai-elements/reasoning.d.ts.map +1 -0
- package/dist/components/ai-elements/response.d.ts.map +1 -0
- package/dist/components/ai-elements/shimmer.d.ts.map +1 -0
- package/dist/components/tool-call-approval.d.ts.map +1 -0
- package/dist/components/tool-call-result.d.ts.map +1 -0
- package/dist/components/ui/autotextarea.d.ts.map +1 -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.map +1 -0
- package/dist/components/ui/command.d.ts.map +1 -0
- package/dist/components/ui/dialog.d.ts.map +1 -0
- package/dist/components/ui/dropdown-menu.d.ts.map +1 -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.map +1 -0
- package/dist/components/ui/kbd.d.ts.map +1 -0
- package/dist/components/ui/select.d.ts.map +1 -0
- package/dist/components/ui/textarea.d.ts.map +1 -0
- package/dist/components/ui/tooltip.d.ts.map +1 -0
- package/dist/core.css +1 -1
- package/dist/index.cjs +7 -7
- package/dist/index.d.ts.map +1 -0
- package/dist/index.mjs +2372 -2226
- package/dist/lib/useAgent.d.ts.map +1 -0
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/types/tool-description.d.ts.map +1 -0
- package/dist/types/use-agent.d.ts.map +1 -0
- package/dist/utils/extract-tool-metadata.d.ts +25 -0
- package/dist/utils/extract-tool-metadata.d.ts.map +1 -0
- package/dist/verifyToken.d.ts.map +1 -0
- package/package.json +11 -13
- package/scripts/cli-extract-types-auto.ts +542 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useAgent.d.ts","sourceRoot":"","sources":["../../src/lib/useAgent.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,eAAe,EACf,cAAc,EAGf,MAAM,oBAAoB,CAAC;AAE5B,wBAAgB,QAAQ,CAAC,EACvB,UAAqC,EACrC,aAAmC,EACnC,WAAW,EAAE,aAAa,EAC1B,cAAsB,EACtB,IAAI,EACJ,KAAU,EACV,SAAc,EACd,YAAiB,EACjB,eAAoB,EACpB,cAAc,EAAE,qBAAqB,EACrC,UAAU,EACV,QAAQ,EACR,UAAU,GACX,GAAE,eAAoB,GAAG,cAAc,CAkZvC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/lib/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,KAAK,UAAU,EAAE,MAAM,MAAM,CAAA;AAG5C,wBAAgB,EAAE,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE,UAEzC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,YAAY,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-description.d.ts","sourceRoot":"","sources":["../../src/types/tool-description.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,uBAAuB;IACtC,KAAK,EAAE,eAAe,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,KAAK,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;KACd,CAAC,CAAC;CACJ"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-agent.d.ts","sourceRoot":"","sources":["../../src/types/use-agent.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export interface ToolMetadata {
|
|
3
|
+
name: string;
|
|
4
|
+
description: string;
|
|
5
|
+
parameters: z.ZodObject<any>;
|
|
6
|
+
parametersDef: Record<string, {
|
|
7
|
+
type: string;
|
|
8
|
+
description: string;
|
|
9
|
+
required: boolean;
|
|
10
|
+
}>;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Extract tool metadata from a function
|
|
14
|
+
* Reads function name, JSDoc comments, and infers parameter schema
|
|
15
|
+
*
|
|
16
|
+
* Priority:
|
|
17
|
+
* 1. Build-time extracted metadata (if available)
|
|
18
|
+
* 2. Runtime inference (fallback)
|
|
19
|
+
*/
|
|
20
|
+
export declare function extractToolMetadata(fn: Function): ToolMetadata;
|
|
21
|
+
/**
|
|
22
|
+
* Extract tool metadata from multiple functions
|
|
23
|
+
*/
|
|
24
|
+
export declare function extractToolsMetadata(functions: Function[]): ToolMetadata[];
|
|
25
|
+
//# sourceMappingURL=extract-tool-metadata.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extract-tool-metadata.d.ts","sourceRoot":"","sources":["../../src/utils/extract-tool-metadata.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IAC7B,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CACzF;AAwID;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,QAAQ,GAAG,YAAY,CAsB9D;AAuRD;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,QAAQ,EAAE,GAAG,YAAY,EAAE,CAE1E"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verifyToken.d.ts","sourceRoot":"","sources":["../src/verifyToken.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KAAE,CAAC;IAC1C,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAsB,WAAW,CAC/B,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,aAAa,CAAC,CA0BxB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arcteninc/core",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.17",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.cjs",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -15,19 +15,19 @@
|
|
|
15
15
|
"types": "./dist/server.d.ts",
|
|
16
16
|
"import": "./dist/server.mjs",
|
|
17
17
|
"require": "./dist/server.cjs"
|
|
18
|
-
}
|
|
19
|
-
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"sideEffects": false,
|
|
21
|
+
"bin": {
|
|
22
|
+
"arcten-extract-types": "./scripts/cli-extract-types-auto.ts"
|
|
20
23
|
},
|
|
21
|
-
"sideEffects": [
|
|
22
|
-
"*.css",
|
|
23
|
-
"./dist/core.css"
|
|
24
|
-
],
|
|
25
24
|
"files": [
|
|
26
|
-
"dist"
|
|
25
|
+
"dist",
|
|
26
|
+
"scripts/cli-extract-types-auto.ts"
|
|
27
27
|
],
|
|
28
28
|
"scripts": {
|
|
29
29
|
"dev": "vite build --watch",
|
|
30
|
-
"build": "vite build && bunx tsc
|
|
30
|
+
"build": "vite build && bunx tsc -p tsconfig.build.json",
|
|
31
31
|
"prepublishOnly": "bun run build"
|
|
32
32
|
},
|
|
33
33
|
"peerDependencies": {
|
|
@@ -41,8 +41,6 @@
|
|
|
41
41
|
"@types/node": "^24.9.2",
|
|
42
42
|
"@types/react": "^19.2.2",
|
|
43
43
|
"@types/react-dom": "^19.2.2",
|
|
44
|
-
"autoprefixer": "^10.4.21",
|
|
45
|
-
"postcss": "^8.5.6",
|
|
46
44
|
"react": "^19.2.0",
|
|
47
45
|
"react-dom": "^19.2.0",
|
|
48
46
|
"typescript": "^5.9.3",
|
|
@@ -60,12 +58,13 @@
|
|
|
60
58
|
"@radix-ui/react-slot": "^1.2.3",
|
|
61
59
|
"@radix-ui/react-tooltip": "^1.2.8",
|
|
62
60
|
"@radix-ui/react-use-controllable-state": "^1.2.2",
|
|
63
|
-
"@tailwindcss/vite": "^4.1.16",
|
|
64
61
|
"@use-gesture/react": "^10.3.1",
|
|
62
|
+
"acorn": "^8.15.0",
|
|
65
63
|
"ai": "^6.0.0-beta.94",
|
|
66
64
|
"class-variance-authority": "^0.7.1",
|
|
67
65
|
"clsx": "^2.1.1",
|
|
68
66
|
"cmdk": "^1.1.1",
|
|
67
|
+
"glob": "^11.0.3",
|
|
69
68
|
"lucide-react": "^0.552.0",
|
|
70
69
|
"motion": "^12.23.24",
|
|
71
70
|
"nanoid": "^5.1.6",
|
|
@@ -74,7 +73,6 @@
|
|
|
74
73
|
"shadcn": "^3.5.0",
|
|
75
74
|
"streamdown": "^1.4.0",
|
|
76
75
|
"tailwind-merge": "^3.3.1",
|
|
77
|
-
"tailwindcss": "^4.1.16",
|
|
78
76
|
"tw-animate-css": "^1.4.0",
|
|
79
77
|
"zod": "^3.24.1"
|
|
80
78
|
}
|
|
@@ -0,0 +1,542 @@
|
|
|
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
|
+
interface TypeMetadata {
|
|
13
|
+
type: string;
|
|
14
|
+
description?: string;
|
|
15
|
+
required: boolean;
|
|
16
|
+
default?: string;
|
|
17
|
+
values?: string[];
|
|
18
|
+
arrayItemType?: TypeMetadata;
|
|
19
|
+
properties?: Record<string, TypeMetadata>;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
interface FunctionMetadata {
|
|
23
|
+
name: string;
|
|
24
|
+
description: string;
|
|
25
|
+
parameters: Record<string, TypeMetadata>;
|
|
26
|
+
returnType?: string;
|
|
27
|
+
isAsync?: boolean;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
interface GeneratedMetadata {
|
|
31
|
+
generated: string;
|
|
32
|
+
discoveredFrom: string[];
|
|
33
|
+
functions: Record<string, FunctionMetadata>;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
interface ToolUsage {
|
|
37
|
+
toolNames: Set<string>;
|
|
38
|
+
file: string;
|
|
39
|
+
component: 'ArctenAgent' | 'useAgent';
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Find all files that use ArctenAgent or useAgent
|
|
44
|
+
*/
|
|
45
|
+
async function findToolUsageFiles(projectRoot: string): Promise<string[]> {
|
|
46
|
+
const pattern = path.join(projectRoot, '**/*.{ts,tsx}').replace(/\\/g, '/');
|
|
47
|
+
const files = await glob(pattern, {
|
|
48
|
+
ignore: ['**/node_modules/**', '**/dist/**', '**/.next/**', '**/build/**'],
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
console.log(`š Found ${files.length} TypeScript files to scan`);
|
|
52
|
+
return files;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Extract tool names from ArctenAgent or useAgent usage
|
|
57
|
+
*/
|
|
58
|
+
function extractToolNamesFromFile(sourceFile: ts.SourceFile): ToolUsage[] {
|
|
59
|
+
const usages: ToolUsage[] = [];
|
|
60
|
+
|
|
61
|
+
function visit(node: ts.Node) {
|
|
62
|
+
// Check for <ArctenAgent tools={[...]} safeTools={[...]} />
|
|
63
|
+
if (ts.isJsxElement(node) || ts.isJsxSelfClosingElement(node)) {
|
|
64
|
+
const tagName = ts.isJsxElement(node)
|
|
65
|
+
? node.openingElement.tagName.getText(sourceFile)
|
|
66
|
+
: node.tagName.getText(sourceFile);
|
|
67
|
+
|
|
68
|
+
if (tagName === 'ArctenAgent') {
|
|
69
|
+
const toolNames = new Set<string>();
|
|
70
|
+
const attributes = ts.isJsxElement(node)
|
|
71
|
+
? node.openingElement.attributes.properties
|
|
72
|
+
: node.attributes.properties;
|
|
73
|
+
|
|
74
|
+
for (const attr of attributes) {
|
|
75
|
+
if (ts.isJsxAttribute(attr)) {
|
|
76
|
+
const attrName = attr.name.getText(sourceFile);
|
|
77
|
+
if (attrName === 'tools' || attrName === 'safeTools') {
|
|
78
|
+
if (attr.initializer && ts.isJsxExpression(attr.initializer)) {
|
|
79
|
+
const expr = attr.initializer.expression;
|
|
80
|
+
if (expr && ts.isArrayLiteralExpression(expr)) {
|
|
81
|
+
for (const element of expr.elements) {
|
|
82
|
+
const name = element.getText(sourceFile).trim();
|
|
83
|
+
// Remove any object property access (e.g., tools.getOrders -> getOrders)
|
|
84
|
+
const simpleName = name.split('.').pop() || name;
|
|
85
|
+
toolNames.add(simpleName);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (toolNames.size > 0) {
|
|
94
|
+
usages.push({
|
|
95
|
+
toolNames,
|
|
96
|
+
file: sourceFile.fileName,
|
|
97
|
+
component: 'ArctenAgent',
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Check for useAgent({ tools: [...], safeTools: [...] })
|
|
104
|
+
if (ts.isCallExpression(node)) {
|
|
105
|
+
const expr = node.expression;
|
|
106
|
+
if (ts.isIdentifier(expr) && expr.getText(sourceFile) === 'useAgent') {
|
|
107
|
+
const toolNames = new Set<string>();
|
|
108
|
+
|
|
109
|
+
if (node.arguments.length > 0) {
|
|
110
|
+
const arg = node.arguments[0];
|
|
111
|
+
if (ts.isObjectLiteralExpression(arg)) {
|
|
112
|
+
for (const prop of arg.properties) {
|
|
113
|
+
if (ts.isPropertyAssignment(prop)) {
|
|
114
|
+
const propName = prop.name.getText(sourceFile);
|
|
115
|
+
if (propName === 'tools' || propName === 'safeTools') {
|
|
116
|
+
if (ts.isArrayLiteralExpression(prop.initializer)) {
|
|
117
|
+
for (const element of prop.initializer.elements) {
|
|
118
|
+
const name = element.getText(sourceFile).trim();
|
|
119
|
+
const simpleName = name.split('.').pop() || name;
|
|
120
|
+
toolNames.add(simpleName);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (toolNames.size > 0) {
|
|
130
|
+
usages.push({
|
|
131
|
+
toolNames,
|
|
132
|
+
file: sourceFile.fileName,
|
|
133
|
+
component: 'useAgent',
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
ts.forEachChild(node, visit);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
visit(sourceFile);
|
|
143
|
+
return usages;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Find where a tool function is defined
|
|
148
|
+
*/
|
|
149
|
+
function findFunctionDefinition(
|
|
150
|
+
functionName: string,
|
|
151
|
+
sourceFile: ts.SourceFile,
|
|
152
|
+
program: ts.Program
|
|
153
|
+
): { sourceFile: ts.SourceFile; node: ts.FunctionDeclaration } | null {
|
|
154
|
+
// First, check if it's defined in the current file
|
|
155
|
+
let foundNode: ts.FunctionDeclaration | null = null;
|
|
156
|
+
|
|
157
|
+
function visitForDefinition(node: ts.Node) {
|
|
158
|
+
if (ts.isFunctionDeclaration(node) && node.name) {
|
|
159
|
+
if (node.name.getText(sourceFile) === functionName) {
|
|
160
|
+
foundNode = node;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
if (!foundNode) {
|
|
164
|
+
ts.forEachChild(node, visitForDefinition);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
visitForDefinition(sourceFile);
|
|
169
|
+
|
|
170
|
+
if (foundNode) {
|
|
171
|
+
return { sourceFile, node: foundNode };
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// If not found, check imports
|
|
175
|
+
const imports: { name: string; from: string }[] = [];
|
|
176
|
+
|
|
177
|
+
function visitForImports(node: ts.Node) {
|
|
178
|
+
if (ts.isImportDeclaration(node)) {
|
|
179
|
+
const moduleSpecifier = node.moduleClause;
|
|
180
|
+
if (moduleSpecifier && ts.isImportClause(moduleSpecifier)) {
|
|
181
|
+
const namedBindings = moduleSpecifier.namedBindings;
|
|
182
|
+
if (namedBindings && ts.isNamedImports(namedBindings)) {
|
|
183
|
+
for (const element of namedBindings.elements) {
|
|
184
|
+
const importedName = element.name.getText(sourceFile);
|
|
185
|
+
if (importedName === functionName) {
|
|
186
|
+
const modulePath = (node.moduleSpecifier as ts.StringLiteral).text;
|
|
187
|
+
imports.push({ name: importedName, from: modulePath });
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
ts.forEachChild(node, visitForImports);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
visitForImports(sourceFile);
|
|
197
|
+
|
|
198
|
+
// Follow imports to find definition
|
|
199
|
+
for (const imp of imports) {
|
|
200
|
+
const resolvedPath = resolveImportPath(imp.from, sourceFile.fileName);
|
|
201
|
+
if (resolvedPath) {
|
|
202
|
+
const importedSourceFile = program.getSourceFile(resolvedPath);
|
|
203
|
+
if (importedSourceFile) {
|
|
204
|
+
const result = findFunctionDefinition(functionName, importedSourceFile, program);
|
|
205
|
+
if (result) {
|
|
206
|
+
return result;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
return null;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Resolve import path to actual file path
|
|
217
|
+
*/
|
|
218
|
+
function resolveImportPath(importPath: string, fromFile: string): string | null {
|
|
219
|
+
if (importPath.startsWith('.')) {
|
|
220
|
+
// Relative import
|
|
221
|
+
const dir = path.dirname(fromFile);
|
|
222
|
+
const resolved = path.resolve(dir, importPath);
|
|
223
|
+
|
|
224
|
+
// Try common extensions
|
|
225
|
+
const extensions = ['.ts', '.tsx', '.js', '.jsx'];
|
|
226
|
+
for (const ext of extensions) {
|
|
227
|
+
const withExt = resolved + ext;
|
|
228
|
+
if (fs.existsSync(withExt)) {
|
|
229
|
+
return withExt;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// Try index files
|
|
234
|
+
for (const ext of extensions) {
|
|
235
|
+
const indexPath = path.join(resolved, `index${ext}`);
|
|
236
|
+
if (fs.existsSync(indexPath)) {
|
|
237
|
+
return indexPath;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
return resolved;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// Node modules - we'll skip for now
|
|
245
|
+
return null;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Serialize a TypeScript type (same as previous implementation)
|
|
250
|
+
*/
|
|
251
|
+
function serializeType(
|
|
252
|
+
type: ts.Type,
|
|
253
|
+
checker: ts.TypeChecker,
|
|
254
|
+
visited = new Set<number>(),
|
|
255
|
+
depth = 0
|
|
256
|
+
): TypeMetadata {
|
|
257
|
+
const typeString = checker.typeToString(type);
|
|
258
|
+
|
|
259
|
+
if (depth > 10) {
|
|
260
|
+
return { type: 'any', required: true };
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
const typeId = (type as any).id;
|
|
264
|
+
if (typeId !== undefined && visited.has(typeId)) {
|
|
265
|
+
return { type: 'any', required: true };
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
if (type.flags & ts.TypeFlags.String) {
|
|
269
|
+
return { type: 'string', required: true };
|
|
270
|
+
}
|
|
271
|
+
if (type.flags & ts.TypeFlags.Number) {
|
|
272
|
+
return { type: 'number', required: true };
|
|
273
|
+
}
|
|
274
|
+
if (type.flags & ts.TypeFlags.Boolean) {
|
|
275
|
+
return { type: 'boolean', required: true };
|
|
276
|
+
}
|
|
277
|
+
if (type.flags & ts.TypeFlags.Undefined || type.flags & ts.TypeFlags.Void) {
|
|
278
|
+
return { type: 'undefined', required: false };
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
if (type.isUnion()) {
|
|
282
|
+
const types = type.types;
|
|
283
|
+
const stringLiterals = types
|
|
284
|
+
.filter(t => t.flags & ts.TypeFlags.StringLiteral)
|
|
285
|
+
.map(t => (t as ts.StringLiteralType).value);
|
|
286
|
+
|
|
287
|
+
if (stringLiterals.length === types.length) {
|
|
288
|
+
return { type: 'enum', values: stringLiterals, required: true };
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
const hasUndefined = types.some(t => t.flags & ts.TypeFlags.Undefined);
|
|
292
|
+
const nonUndefinedTypes = types.filter(t => !(t.flags & ts.TypeFlags.Undefined));
|
|
293
|
+
|
|
294
|
+
if (hasUndefined && nonUndefinedTypes.length === 1) {
|
|
295
|
+
const metadata = serializeType(nonUndefinedTypes[0], checker, visited, depth + 1);
|
|
296
|
+
metadata.required = false;
|
|
297
|
+
return metadata;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
return {
|
|
301
|
+
type: types.map(t => checker.typeToString(t)).join(' | '),
|
|
302
|
+
required: true,
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
if (checker.isArrayType(type)) {
|
|
307
|
+
const typeArgs = (type as ts.TypeReference).typeArguments;
|
|
308
|
+
if (typeArgs && typeArgs.length > 0) {
|
|
309
|
+
return {
|
|
310
|
+
type: 'array',
|
|
311
|
+
arrayItemType: serializeType(typeArgs[0], checker, visited, depth + 1),
|
|
312
|
+
required: true,
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
return { type: 'array', required: true };
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
if (type.flags & ts.TypeFlags.Object) {
|
|
319
|
+
if (typeId !== undefined) {
|
|
320
|
+
visited.add(typeId);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
const properties: Record<string, TypeMetadata> = {};
|
|
324
|
+
const props = checker.getPropertiesOfType(type);
|
|
325
|
+
|
|
326
|
+
if (props.length > 0) {
|
|
327
|
+
for (const prop of props) {
|
|
328
|
+
const propDeclaration = prop.valueDeclaration || prop.declarations?.[0];
|
|
329
|
+
|
|
330
|
+
if (propDeclaration) {
|
|
331
|
+
const propType = checker.getTypeOfSymbolAtLocation(prop, propDeclaration);
|
|
332
|
+
const isOptional = (prop.flags & ts.SymbolFlags.Optional) !== 0;
|
|
333
|
+
|
|
334
|
+
const propMetadata = serializeType(propType, checker, visited, depth + 1);
|
|
335
|
+
propMetadata.required = !isOptional;
|
|
336
|
+
|
|
337
|
+
properties[prop.name] = propMetadata;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
return { type: 'object', properties, required: true };
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
return {
|
|
346
|
+
type: typeString.length < 100 ? typeString : 'any',
|
|
347
|
+
required: true,
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/**
|
|
352
|
+
* Extract metadata from a function
|
|
353
|
+
*/
|
|
354
|
+
function extractFunctionMetadata(
|
|
355
|
+
node: ts.FunctionDeclaration,
|
|
356
|
+
checker: ts.TypeChecker,
|
|
357
|
+
sourceFile: ts.SourceFile
|
|
358
|
+
): FunctionMetadata | null {
|
|
359
|
+
if (!node.name) {
|
|
360
|
+
return null;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
const functionName = node.name.getText(sourceFile);
|
|
364
|
+
|
|
365
|
+
const jsDocTags = ts.getJSDocTags(node);
|
|
366
|
+
const jsDocComments = ts.getJSDocCommentsAndTags(node);
|
|
367
|
+
|
|
368
|
+
let description = `Execute ${functionName}`;
|
|
369
|
+
for (const comment of jsDocComments) {
|
|
370
|
+
if (ts.isJSDoc(comment) && comment.comment) {
|
|
371
|
+
if (typeof comment.comment === 'string') {
|
|
372
|
+
description = comment.comment.trim();
|
|
373
|
+
}
|
|
374
|
+
break;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
const paramDescriptions = new Map<string, string>();
|
|
379
|
+
for (const tag of jsDocTags) {
|
|
380
|
+
if (tag.tagName.text === 'param' && ts.isJSDocParameterTag(tag)) {
|
|
381
|
+
const paramName = tag.name?.getText(sourceFile);
|
|
382
|
+
const paramDesc = typeof tag.comment === 'string' ? tag.comment.trim() : '';
|
|
383
|
+
if (paramName && paramDesc) {
|
|
384
|
+
paramDescriptions.set(paramName, paramDesc);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
const parameters: Record<string, TypeMetadata> = {};
|
|
390
|
+
const isAsync = node.modifiers?.some(m => m.kind === ts.SyntaxKind.AsyncKeyword) || false;
|
|
391
|
+
|
|
392
|
+
for (const param of node.parameters) {
|
|
393
|
+
const paramName = param.name.getText(sourceFile);
|
|
394
|
+
const hasDefault = param.initializer !== undefined;
|
|
395
|
+
|
|
396
|
+
let typeMetadata: TypeMetadata;
|
|
397
|
+
if (param.type) {
|
|
398
|
+
const type = checker.getTypeFromTypeNode(param.type);
|
|
399
|
+
typeMetadata = serializeType(type, checker);
|
|
400
|
+
} else {
|
|
401
|
+
typeMetadata = { type: 'any', required: true };
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
const isOptional = param.questionToken !== undefined || hasDefault;
|
|
405
|
+
if (isOptional) {
|
|
406
|
+
typeMetadata.required = false;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
if (hasDefault) {
|
|
410
|
+
typeMetadata.default = param.initializer!.getText(sourceFile);
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
if (paramDescriptions.has(paramName)) {
|
|
414
|
+
typeMetadata.description = paramDescriptions.get(paramName);
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
parameters[paramName] = typeMetadata;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
let returnType = 'any';
|
|
421
|
+
if (node.type) {
|
|
422
|
+
returnType = node.type.getText(sourceFile);
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
return {
|
|
426
|
+
name: functionName,
|
|
427
|
+
description,
|
|
428
|
+
parameters,
|
|
429
|
+
returnType,
|
|
430
|
+
isAsync,
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
/**
|
|
435
|
+
* Main function
|
|
436
|
+
*/
|
|
437
|
+
async function autoDiscoverAndExtract(projectRoot: string, outputPath: string) {
|
|
438
|
+
console.log(`\nš Auto-discovering tools in: ${projectRoot}\n`);
|
|
439
|
+
|
|
440
|
+
// Find all TypeScript files
|
|
441
|
+
const files = await findToolUsageFiles(projectRoot);
|
|
442
|
+
|
|
443
|
+
// Read tsconfig
|
|
444
|
+
const configPath = ts.findConfigFile(projectRoot, ts.sys.fileExists, 'tsconfig.json');
|
|
445
|
+
let compilerOptions: ts.CompilerOptions = {
|
|
446
|
+
target: ts.ScriptTarget.ESNext,
|
|
447
|
+
module: ts.ModuleKind.ESNext,
|
|
448
|
+
jsx: ts.JsxEmit.React,
|
|
449
|
+
};
|
|
450
|
+
|
|
451
|
+
if (configPath) {
|
|
452
|
+
const config = ts.readConfigFile(configPath, ts.sys.readFile);
|
|
453
|
+
const parsed = ts.parseJsonConfigFileContent(config.config, ts.sys, path.dirname(configPath));
|
|
454
|
+
compilerOptions = parsed.options;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
// Create program with all files
|
|
458
|
+
const program = ts.createProgram(files, compilerOptions);
|
|
459
|
+
const checker = program.getTypeChecker();
|
|
460
|
+
|
|
461
|
+
// Scan for tool usages
|
|
462
|
+
const allToolUsages: ToolUsage[] = [];
|
|
463
|
+
const allToolNames = new Set<string>();
|
|
464
|
+
|
|
465
|
+
for (const file of files) {
|
|
466
|
+
const sourceFile = program.getSourceFile(file);
|
|
467
|
+
if (sourceFile) {
|
|
468
|
+
const usages = extractToolNamesFromFile(sourceFile);
|
|
469
|
+
if (usages.length > 0) {
|
|
470
|
+
allToolUsages.push(...usages);
|
|
471
|
+
usages.forEach(u => u.toolNames.forEach(name => allToolNames.add(name)));
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
console.log(`ā Found ${allToolUsages.length} usage site(s) with ${allToolNames.size} unique tool(s)`);
|
|
477
|
+
allToolUsages.forEach(usage => {
|
|
478
|
+
console.log(` - ${usage.component} in ${path.relative(projectRoot, usage.file)}`);
|
|
479
|
+
console.log(` Tools: ${Array.from(usage.toolNames).join(', ')}`);
|
|
480
|
+
});
|
|
481
|
+
|
|
482
|
+
// Extract metadata for discovered tools
|
|
483
|
+
console.log(`\nš Extracting types for discovered tools...\n`);
|
|
484
|
+
|
|
485
|
+
const functionsMap: Record<string, FunctionMetadata> = {};
|
|
486
|
+
const discoveredFrom: string[] = [];
|
|
487
|
+
|
|
488
|
+
for (const toolName of allToolNames) {
|
|
489
|
+
let found = false;
|
|
490
|
+
|
|
491
|
+
// Search in all files for the definition
|
|
492
|
+
for (const file of files) {
|
|
493
|
+
const sourceFile = program.getSourceFile(file);
|
|
494
|
+
if (sourceFile) {
|
|
495
|
+
const result = findFunctionDefinition(toolName, sourceFile, program);
|
|
496
|
+
if (result) {
|
|
497
|
+
const metadata = extractFunctionMetadata(result.node, checker, result.sourceFile);
|
|
498
|
+
if (metadata) {
|
|
499
|
+
functionsMap[toolName] = metadata;
|
|
500
|
+
discoveredFrom.push(path.relative(projectRoot, result.sourceFile.fileName));
|
|
501
|
+
console.log(` ā ${toolName} (from ${path.relative(projectRoot, result.sourceFile.fileName)})`);
|
|
502
|
+
found = true;
|
|
503
|
+
break;
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
if (!found) {
|
|
510
|
+
console.log(` ā ${toolName} (definition not found)`);
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
// Generate output
|
|
515
|
+
const output: GeneratedMetadata = {
|
|
516
|
+
generated: new Date().toISOString(),
|
|
517
|
+
discoveredFrom: Array.from(new Set(discoveredFrom)),
|
|
518
|
+
functions: functionsMap,
|
|
519
|
+
};
|
|
520
|
+
|
|
521
|
+
const outputDir = path.dirname(outputPath);
|
|
522
|
+
if (!fs.existsSync(outputDir)) {
|
|
523
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
fs.writeFileSync(outputPath, JSON.stringify(output, null, 2));
|
|
527
|
+
console.log(`\nā
Generated metadata for ${Object.keys(functionsMap).length} tool(s)`);
|
|
528
|
+
console.log(`š Output: ${outputPath}\n`);
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
// CLI
|
|
532
|
+
if (import.meta.main) {
|
|
533
|
+
const args = process.argv.slice(2);
|
|
534
|
+
const projectRoot = args[0] ? path.resolve(args[0]) : process.cwd();
|
|
535
|
+
const outputPath = args[1]
|
|
536
|
+
? path.resolve(args[1])
|
|
537
|
+
: path.join(projectRoot, '.arcten', 'tool-types.json');
|
|
538
|
+
|
|
539
|
+
autoDiscoverAndExtract(projectRoot, outputPath);
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
export { autoDiscoverAndExtract };
|