@arcteninc/core 0.0.62 → 0.0.64
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/package.json +7 -8
- package/scripts/arcten-cli.cjs +31 -31
- package/scripts/cli-extract-types-auto-wrapper.js +108 -0
- package/scripts/cli-extract-types-auto.ts +71 -201
- package/scripts/cli-extract-types-auto.js +0 -93
- package/scripts/postinstall-check-version.cjs +0 -157
- package/scripts/update-core.cjs +0 -125
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arcteninc/core",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.64",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.cjs",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -20,21 +20,19 @@
|
|
|
20
20
|
},
|
|
21
21
|
"sideEffects": false,
|
|
22
22
|
"bin": {
|
|
23
|
-
"arcten": "./scripts/arcten-cli.cjs"
|
|
23
|
+
"arcten": "./scripts/arcten-cli.cjs",
|
|
24
|
+
"arcten-extract-types": "./scripts/cli-extract-types-auto-wrapper.js"
|
|
24
25
|
},
|
|
25
26
|
"files": [
|
|
26
27
|
"dist",
|
|
27
28
|
"scripts/cli-extract-types-auto.ts",
|
|
28
|
-
"scripts/cli-extract-types-auto.js",
|
|
29
|
-
"scripts/arcten-cli.cjs"
|
|
30
|
-
"scripts/postinstall-check-version.cjs",
|
|
31
|
-
"scripts/update-core.cjs"
|
|
29
|
+
"scripts/cli-extract-types-auto-wrapper.js",
|
|
30
|
+
"scripts/arcten-cli.cjs"
|
|
32
31
|
],
|
|
33
32
|
"scripts": {
|
|
34
33
|
"dev": "vite build --watch",
|
|
35
34
|
"build": "vite build",
|
|
36
|
-
"prepublishOnly": "bun run build"
|
|
37
|
-
"postinstall": "node scripts/postinstall-check-version.cjs"
|
|
35
|
+
"prepublishOnly": "bun run build"
|
|
38
36
|
},
|
|
39
37
|
"peerDependencies": {
|
|
40
38
|
"ai": "^6.0.0-beta.94",
|
|
@@ -56,6 +54,7 @@
|
|
|
56
54
|
"dependencies": {
|
|
57
55
|
"ts-json-schema-generator": "^2.4.0",
|
|
58
56
|
"typescript": "^5.9.3",
|
|
57
|
+
"tsx": "^4.19.2",
|
|
59
58
|
"@ai-sdk/openai": "^3.0.0-beta.47",
|
|
60
59
|
"@ai-sdk/react": "^3.0.0-beta.92",
|
|
61
60
|
"@emotion/is-prop-valid": "^1.4.0",
|
package/scripts/arcten-cli.cjs
CHANGED
|
@@ -14,9 +14,10 @@ const path = require('path');
|
|
|
14
14
|
const fs = require('fs');
|
|
15
15
|
|
|
16
16
|
const commands = {
|
|
17
|
-
'extract-types':
|
|
18
|
-
'tools':
|
|
19
|
-
'
|
|
17
|
+
'extract-types': 'extract-types',
|
|
18
|
+
'tools': 'extract-types', // Alias
|
|
19
|
+
'setup': 'extract-types', // Alias - better name for extract-types
|
|
20
|
+
'update': 'update',
|
|
20
21
|
'help': showHelp,
|
|
21
22
|
'--help': showHelp,
|
|
22
23
|
'-h': showHelp,
|
|
@@ -29,18 +30,19 @@ function showHelp() {
|
|
|
29
30
|
Usage: arcten <command> [options]
|
|
30
31
|
|
|
31
32
|
Commands:
|
|
32
|
-
extract-types, tools Extract tool metadata from your project
|
|
33
|
-
|
|
33
|
+
extract-types, tools, setup Extract tool metadata from your project
|
|
34
|
+
Aliases: arcten tools, arcten setup
|
|
34
35
|
|
|
35
|
-
update
|
|
36
|
-
|
|
36
|
+
update Update @arcteninc/core to latest version
|
|
37
|
+
Updates package.json and shows next steps
|
|
37
38
|
|
|
38
|
-
help
|
|
39
|
+
help Show this help message
|
|
39
40
|
|
|
40
41
|
Examples:
|
|
41
42
|
arcten tools Extract tool types (same as arcten extract-types)
|
|
42
|
-
arcten
|
|
43
|
-
arcten
|
|
43
|
+
arcten setup Extract tool types (same as arcten extract-types)
|
|
44
|
+
arcten update Update @arcteninc/core to latest version
|
|
45
|
+
arcten help Show help
|
|
44
46
|
|
|
45
47
|
For more information, visit https://github.com/arcteninc/core
|
|
46
48
|
`);
|
|
@@ -66,28 +68,26 @@ function main() {
|
|
|
66
68
|
|
|
67
69
|
try {
|
|
68
70
|
const commandHandler = commands[command];
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
//
|
|
71
|
+
|
|
72
|
+
if (commandHandler === showHelp) {
|
|
73
|
+
// For help command
|
|
74
|
+
commandHandler();
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (typeof commandHandler === 'string') {
|
|
79
|
+
// For commands that need to spawn scripts
|
|
72
80
|
let scriptPath;
|
|
73
81
|
let runner = 'node';
|
|
74
82
|
|
|
75
|
-
if (
|
|
76
|
-
scriptPath = path.join(__dirname, 'update-core.
|
|
83
|
+
if (commandHandler === 'update') {
|
|
84
|
+
scriptPath = path.join(__dirname, 'update-core.js');
|
|
85
|
+
} else if (commandHandler === 'extract-types') {
|
|
86
|
+
// For extract-types/tools/setup, use the wrapper script which handles TypeScript execution
|
|
87
|
+
scriptPath = path.join(__dirname, 'cli-extract-types-auto-wrapper.js');
|
|
77
88
|
} else {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
const tsPath = path.join(__dirname, 'cli-extract-types-auto.ts');
|
|
81
|
-
|
|
82
|
-
if (fs.existsSync(jsPath)) {
|
|
83
|
-
scriptPath = jsPath;
|
|
84
|
-
} else if (fs.existsSync(tsPath)) {
|
|
85
|
-
scriptPath = tsPath;
|
|
86
|
-
runner = 'bun'; // Use bun for TypeScript files
|
|
87
|
-
} else {
|
|
88
|
-
console.error(`❌ Script not found: ${jsPath} or ${tsPath}`);
|
|
89
|
-
process.exit(1);
|
|
90
|
-
}
|
|
89
|
+
console.error(`❌ Unknown command handler: ${commandHandler}`);
|
|
90
|
+
process.exit(1);
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
if (!fs.existsSync(scriptPath)) {
|
|
@@ -106,7 +106,7 @@ function main() {
|
|
|
106
106
|
console.error(`❌ Failed to run command:`, error.message);
|
|
107
107
|
if (runner === 'bun' && error.code === 'ENOENT') {
|
|
108
108
|
console.error(`\n💡 Bun not found. Install it: https://bun.sh`);
|
|
109
|
-
console.error(` Or ensure
|
|
109
|
+
console.error(` Or ensure tsx is available: npm install -g tsx`);
|
|
110
110
|
}
|
|
111
111
|
process.exit(1);
|
|
112
112
|
});
|
|
@@ -115,8 +115,8 @@ function main() {
|
|
|
115
115
|
process.exit(code || 0);
|
|
116
116
|
});
|
|
117
117
|
} else {
|
|
118
|
-
|
|
119
|
-
|
|
118
|
+
console.error(`❌ Invalid command handler for: ${command}`);
|
|
119
|
+
process.exit(1);
|
|
120
120
|
}
|
|
121
121
|
} catch (error) {
|
|
122
122
|
console.error(`❌ Error running command:`, error.message);
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Wrapper script that checks for bun first, then tsx, then falls back to node with tsx
|
|
4
|
+
* This ensures compatibility across different environments
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { spawn } = require('child_process');
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const fs = require('fs');
|
|
10
|
+
|
|
11
|
+
const scriptPath = path.join(__dirname, 'cli-extract-types-auto.ts');
|
|
12
|
+
const args = process.argv.slice(2);
|
|
13
|
+
|
|
14
|
+
// Check if a command is available
|
|
15
|
+
function checkCommand(command) {
|
|
16
|
+
return new Promise((resolve) => {
|
|
17
|
+
const check = spawn(command, ['--version'], {
|
|
18
|
+
stdio: 'ignore',
|
|
19
|
+
shell: true
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
check.on('error', () => resolve(false));
|
|
23
|
+
check.on('close', (code) => resolve(code === 0));
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Check if tsx is available in node_modules
|
|
28
|
+
function findTsxInNodeModules() {
|
|
29
|
+
let currentDir = __dirname;
|
|
30
|
+
while (currentDir !== path.dirname(currentDir)) {
|
|
31
|
+
const tsxPath = path.join(currentDir, 'node_modules', '.bin', 'tsx');
|
|
32
|
+
if (fs.existsSync(tsxPath)) {
|
|
33
|
+
return tsxPath;
|
|
34
|
+
}
|
|
35
|
+
currentDir = path.dirname(currentDir);
|
|
36
|
+
}
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async function run() {
|
|
41
|
+
// Try bun first (faster, native TypeScript support)
|
|
42
|
+
if (await checkCommand('bun')) {
|
|
43
|
+
const proc = spawn('bun', [scriptPath, ...args], {
|
|
44
|
+
stdio: 'inherit',
|
|
45
|
+
shell: true
|
|
46
|
+
});
|
|
47
|
+
proc.on('error', (err) => {
|
|
48
|
+
console.error('Error running with bun:', err.message);
|
|
49
|
+
process.exit(1);
|
|
50
|
+
});
|
|
51
|
+
proc.on('exit', (code) => {
|
|
52
|
+
process.exit(code || 0);
|
|
53
|
+
});
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Try tsx from node_modules first (if installed as dependency)
|
|
58
|
+
const tsxPath = findTsxInNodeModules();
|
|
59
|
+
if (tsxPath) {
|
|
60
|
+
const proc = spawn(tsxPath, [scriptPath, ...args], {
|
|
61
|
+
stdio: 'inherit',
|
|
62
|
+
shell: true
|
|
63
|
+
});
|
|
64
|
+
proc.on('error', (err) => {
|
|
65
|
+
console.error('Error running with tsx:', err.message);
|
|
66
|
+
process.exit(1);
|
|
67
|
+
});
|
|
68
|
+
proc.on('exit', (code) => {
|
|
69
|
+
process.exit(code || 0);
|
|
70
|
+
});
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Try global tsx
|
|
75
|
+
if (await checkCommand('tsx')) {
|
|
76
|
+
const proc = spawn('tsx', [scriptPath, ...args], {
|
|
77
|
+
stdio: 'inherit',
|
|
78
|
+
shell: true
|
|
79
|
+
});
|
|
80
|
+
proc.on('error', (err) => {
|
|
81
|
+
console.error('Error running with tsx:', err.message);
|
|
82
|
+
process.exit(1);
|
|
83
|
+
});
|
|
84
|
+
proc.on('exit', (code) => {
|
|
85
|
+
process.exit(code || 0);
|
|
86
|
+
});
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Try npx tsx as last resort (will download tsx if needed)
|
|
91
|
+
const proc = spawn('npx', ['--yes', 'tsx', scriptPath, ...args], {
|
|
92
|
+
stdio: 'inherit',
|
|
93
|
+
shell: true
|
|
94
|
+
});
|
|
95
|
+
proc.on('error', (err) => {
|
|
96
|
+
console.error('Error running with npx tsx:', err.message);
|
|
97
|
+
console.error('\nPlease install one of the following:');
|
|
98
|
+
console.error(' - bun: https://bun.sh');
|
|
99
|
+
console.error(' - tsx: npm install -g tsx (or it will be installed via npx)');
|
|
100
|
+
process.exit(1);
|
|
101
|
+
});
|
|
102
|
+
proc.on('exit', (code) => {
|
|
103
|
+
process.exit(code || 0);
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
run();
|
|
108
|
+
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#!/usr/bin/env
|
|
1
|
+
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
3
|
* Automatically discover and extract types for tools used in ArctenAgent/useAgent
|
|
4
4
|
* Scans the project, finds all tool usages, and generates metadata only for used tools
|
|
@@ -83,6 +83,7 @@ async function findToolUsageFiles(projectRoot: string): Promise<string[]> {
|
|
|
83
83
|
ignore: ['**/node_modules/**', '**/dist/**', '**/.next/**', '**/build/**'],
|
|
84
84
|
});
|
|
85
85
|
|
|
86
|
+
console.log(`📂 Found ${files.length} TypeScript files to scan`);
|
|
86
87
|
return files;
|
|
87
88
|
}
|
|
88
89
|
|
|
@@ -92,8 +93,7 @@ async function findToolUsageFiles(projectRoot: string): Promise<string[]> {
|
|
|
92
93
|
function extractToolNamesFromExpression(
|
|
93
94
|
expr: ts.Expression,
|
|
94
95
|
sourceFile: ts.SourceFile,
|
|
95
|
-
variableMap: Map<string, ts.Expression
|
|
96
|
-
program?: ts.Program
|
|
96
|
+
variableMap: Map<string, ts.Expression>
|
|
97
97
|
): { names: Set<string>; order: string[] } {
|
|
98
98
|
const toolNames = new Set<string>();
|
|
99
99
|
const toolOrder: string[] = []; // Preserve order
|
|
@@ -129,12 +129,9 @@ function extractToolNamesFromExpression(
|
|
|
129
129
|
// Property access: tools.getOrders -> extract "getOrders"
|
|
130
130
|
const propName = element.name.text;
|
|
131
131
|
if (propName) {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
if (!toolNames.has(finalName)) {
|
|
136
|
-
toolNames.add(finalName);
|
|
137
|
-
toolOrder.push(finalName); // Preserve order
|
|
132
|
+
if (!toolNames.has(propName)) {
|
|
133
|
+
toolNames.add(propName);
|
|
134
|
+
toolOrder.push(propName); // Preserve order
|
|
138
135
|
}
|
|
139
136
|
}
|
|
140
137
|
} else if (ts.isElementAccessExpression(element)) {
|
|
@@ -143,12 +140,9 @@ function extractToolNamesFromExpression(
|
|
|
143
140
|
if (ts.isStringLiteral(indexExpr) || ts.isNumericLiteral(indexExpr)) {
|
|
144
141
|
const name = indexExpr.text;
|
|
145
142
|
if (name && name !== 'undefined' && name !== 'null') {
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
if (!toolNames.has(finalName)) {
|
|
150
|
-
toolNames.add(finalName);
|
|
151
|
-
toolOrder.push(finalName); // Preserve order
|
|
143
|
+
if (!toolNames.has(name)) {
|
|
144
|
+
toolNames.add(name);
|
|
145
|
+
toolOrder.push(name); // Preserve order
|
|
152
146
|
}
|
|
153
147
|
}
|
|
154
148
|
} else {
|
|
@@ -183,15 +177,12 @@ function extractToolNamesFromExpression(
|
|
|
183
177
|
return;
|
|
184
178
|
}
|
|
185
179
|
|
|
186
|
-
// Property access: wrappedTools.getRAGInfo
|
|
180
|
+
// Property access: wrappedTools.getRAGInfo
|
|
187
181
|
if (ts.isPropertyAccessExpression(node)) {
|
|
188
182
|
const propName = node.name.text;
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
if (!toolNames.has(finalName)) {
|
|
193
|
-
toolNames.add(finalName);
|
|
194
|
-
toolOrder.push(finalName);
|
|
183
|
+
if (!toolNames.has(propName)) {
|
|
184
|
+
toolNames.add(propName);
|
|
185
|
+
toolOrder.push(propName);
|
|
195
186
|
}
|
|
196
187
|
return;
|
|
197
188
|
}
|
|
@@ -201,20 +192,26 @@ function extractToolNamesFromExpression(
|
|
|
201
192
|
const callExpr = node.expression;
|
|
202
193
|
if (ts.isIdentifier(callExpr)) {
|
|
203
194
|
const funcName = callExpr.text;
|
|
204
|
-
if (funcName === 'useMemo') {
|
|
205
|
-
const
|
|
206
|
-
|
|
207
|
-
|
|
195
|
+
if (funcName === 'useMemo' && node.arguments.length > 0) {
|
|
196
|
+
const firstArg = node.arguments[0];
|
|
197
|
+
// Arrow function: () => [...]
|
|
198
|
+
if (ts.isArrowFunction(firstArg) && firstArg.body) {
|
|
199
|
+
if (ts.isBlock(firstArg.body)) {
|
|
200
|
+
// Block body: () => { return [...] }
|
|
201
|
+
for (const stmt of firstArg.body.statements) {
|
|
202
|
+
if (ts.isReturnStatement(stmt) && stmt.expression) {
|
|
203
|
+
extractFromExpr(stmt.expression);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
} else {
|
|
207
|
+
// Expression body: () => [...]
|
|
208
|
+
extractFromExpr(firstArg.body);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
// Regular function call: useMemo(fn, [])
|
|
212
|
+
else if (ts.isFunctionExpression(firstArg) || ts.isArrowFunction(firstArg)) {
|
|
213
|
+
// Can't easily extract from function body without more analysis
|
|
208
214
|
}
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
// Also handle other function calls that might return arrays
|
|
212
|
-
// For example: someFunction() that returns an array of tools
|
|
213
|
-
if (node.arguments.length === 0) {
|
|
214
|
-
// Check if this call might be a variable reference
|
|
215
|
-
const varExpr = variableMap.get(callExpr.getText(sourceFile));
|
|
216
|
-
if (varExpr) {
|
|
217
|
-
extractFromExpr(varExpr);
|
|
218
215
|
}
|
|
219
216
|
}
|
|
220
217
|
return;
|
|
@@ -231,60 +228,8 @@ function extractToolNamesFromExpression(
|
|
|
231
228
|
return { names: toolNames, order: toolOrder };
|
|
232
229
|
}
|
|
233
230
|
|
|
234
|
-
/**
|
|
235
|
-
* Resolve property access like tools.getLocation to find the actual function name
|
|
236
|
-
* Returns the resolved name if found, or null if couldn't resolve
|
|
237
|
-
*/
|
|
238
|
-
function resolvePropertyAccess(
|
|
239
|
-
expr: ts.PropertyAccessExpression,
|
|
240
|
-
sourceFile: ts.SourceFile,
|
|
241
|
-
program?: ts.Program
|
|
242
|
-
): string | null {
|
|
243
|
-
if (!program) return null;
|
|
244
|
-
|
|
245
|
-
const checker = program.getTypeChecker();
|
|
246
|
-
const symbol = checker.getSymbolAtLocation(expr);
|
|
247
|
-
|
|
248
|
-
if (symbol) {
|
|
249
|
-
// Get the name of the property (e.g., "getLocation")
|
|
250
|
-
return symbol.getName();
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
// Fallback: try to resolve the object (e.g., "tools")
|
|
254
|
-
const objectExpr = expr.expression;
|
|
255
|
-
if (ts.isIdentifier(objectExpr)) {
|
|
256
|
-
const objectName = objectExpr.text;
|
|
257
|
-
// Check if this is an imported module (e.g., import * as tools from "./tools")
|
|
258
|
-
// We'll handle this in the import resolution
|
|
259
|
-
return null;
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
return null;
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
/**
|
|
266
|
-
* Resolve element access like tools['getLocation'] to find the actual function name
|
|
267
|
-
*/
|
|
268
|
-
function resolveElementAccess(
|
|
269
|
-
expr: ts.ElementAccessExpression,
|
|
270
|
-
sourceFile: ts.SourceFile,
|
|
271
|
-
program?: ts.Program
|
|
272
|
-
): string | null {
|
|
273
|
-
if (!program) return null;
|
|
274
|
-
|
|
275
|
-
const checker = program.getTypeChecker();
|
|
276
|
-
const symbol = checker.getSymbolAtLocation(expr);
|
|
277
|
-
|
|
278
|
-
if (symbol) {
|
|
279
|
-
return symbol.getName();
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
return null;
|
|
283
|
-
}
|
|
284
|
-
|
|
285
231
|
/**
|
|
286
232
|
* Build a map of variable declarations in the file
|
|
287
|
-
* Handles: const x = [...], const x = useMemo(...), etc.
|
|
288
233
|
*/
|
|
289
234
|
function buildVariableMap(sourceFile: ts.SourceFile): Map<string, ts.Expression> {
|
|
290
235
|
const variableMap = new Map<string, ts.Expression>();
|
|
@@ -313,46 +258,6 @@ function buildVariableMap(sourceFile: ts.SourceFile): Map<string, ts.Expression>
|
|
|
313
258
|
return variableMap;
|
|
314
259
|
}
|
|
315
260
|
|
|
316
|
-
/**
|
|
317
|
-
* Extract tools from useMemo callback, handling both arrow functions and regular functions
|
|
318
|
-
*/
|
|
319
|
-
function extractToolsFromUseMemo(
|
|
320
|
-
useMemoCall: ts.CallExpression,
|
|
321
|
-
sourceFile: ts.SourceFile,
|
|
322
|
-
variableMap: Map<string, ts.Expression>
|
|
323
|
-
): ts.Expression | null {
|
|
324
|
-
if (useMemoCall.arguments.length === 0) return null;
|
|
325
|
-
|
|
326
|
-
const firstArg = useMemoCall.arguments[0];
|
|
327
|
-
|
|
328
|
-
// Arrow function: () => [...]
|
|
329
|
-
if (ts.isArrowFunction(firstArg)) {
|
|
330
|
-
if (firstArg.body) {
|
|
331
|
-
if (ts.isBlock(firstArg.body)) {
|
|
332
|
-
// Block body: () => { return [...] }
|
|
333
|
-
for (const stmt of firstArg.body.statements) {
|
|
334
|
-
if (ts.isReturnStatement(stmt) && stmt.expression) {
|
|
335
|
-
return stmt.expression;
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
} else {
|
|
339
|
-
// Expression body: () => [...]
|
|
340
|
-
return firstArg.body;
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
// Regular function: function() { return [...] }
|
|
345
|
-
else if (ts.isFunctionExpression(firstArg) && firstArg.body) {
|
|
346
|
-
for (const stmt of firstArg.body.statements) {
|
|
347
|
-
if (ts.isReturnStatement(stmt) && stmt.expression) {
|
|
348
|
-
return stmt.expression;
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
return null;
|
|
354
|
-
}
|
|
355
|
-
|
|
356
261
|
/**
|
|
357
262
|
* Extract tool names from ArctenAgent or useAgent usage
|
|
358
263
|
*/
|
|
@@ -383,7 +288,7 @@ function extractToolNamesFromFile(
|
|
|
383
288
|
if (attr.initializer && ts.isJsxExpression(attr.initializer)) {
|
|
384
289
|
const expr = attr.initializer.expression;
|
|
385
290
|
if (expr) {
|
|
386
|
-
const extracted = extractToolNamesFromExpression(expr, sourceFile, variableMap
|
|
291
|
+
const extracted = extractToolNamesFromExpression(expr, sourceFile, variableMap);
|
|
387
292
|
extracted.names.forEach(name => toolNames.add(name));
|
|
388
293
|
}
|
|
389
294
|
}
|
|
@@ -401,7 +306,7 @@ function extractToolNamesFromFile(
|
|
|
401
306
|
if (attr.initializer && ts.isJsxExpression(attr.initializer)) {
|
|
402
307
|
const expr = attr.initializer.expression;
|
|
403
308
|
if (expr) {
|
|
404
|
-
const extracted = extractToolNamesFromExpression(expr, sourceFile, variableMap
|
|
309
|
+
const extracted = extractToolNamesFromExpression(expr, sourceFile, variableMap);
|
|
405
310
|
allToolOrder.push(...extracted.order);
|
|
406
311
|
}
|
|
407
312
|
}
|
|
@@ -435,8 +340,7 @@ function extractToolNamesFromFile(
|
|
|
435
340
|
const extracted = extractToolNamesFromExpression(
|
|
436
341
|
prop.initializer,
|
|
437
342
|
sourceFile,
|
|
438
|
-
variableMap
|
|
439
|
-
program
|
|
343
|
+
variableMap
|
|
440
344
|
);
|
|
441
345
|
extracted.names.forEach(name => toolNames.add(name));
|
|
442
346
|
}
|
|
@@ -458,8 +362,7 @@ function extractToolNamesFromFile(
|
|
|
458
362
|
const extracted = extractToolNamesFromExpression(
|
|
459
363
|
prop.initializer,
|
|
460
364
|
sourceFile,
|
|
461
|
-
variableMap
|
|
462
|
-
program
|
|
365
|
+
variableMap
|
|
463
366
|
);
|
|
464
367
|
allToolOrder.push(...extracted.order);
|
|
465
368
|
}
|
|
@@ -535,31 +438,30 @@ function findFunctionDefinition(
|
|
|
535
438
|
return { sourceFile, node: foundNode };
|
|
536
439
|
}
|
|
537
440
|
|
|
538
|
-
// If not found, check imports
|
|
539
|
-
const imports: { name: string; from: string; isNamespace
|
|
441
|
+
// If not found, check imports (both named and namespace imports)
|
|
442
|
+
const imports: { name: string; from: string; isNamespace: boolean }[] = [];
|
|
540
443
|
|
|
541
444
|
function visitForImports(node: ts.Node) {
|
|
542
445
|
if (ts.isImportDeclaration(node)) {
|
|
543
446
|
const importClause = node.importClause;
|
|
544
|
-
const modulePath = (node.moduleSpecifier as ts.StringLiteral).text;
|
|
545
|
-
|
|
546
447
|
if (importClause) {
|
|
547
448
|
const namedBindings = importClause.namedBindings;
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
else if (namedBindings && ts.isNamedImports(namedBindings)) {
|
|
558
|
-
for (const element of namedBindings.elements) {
|
|
559
|
-
const importedName = element.name.getText(sourceFile);
|
|
560
|
-
if (importedName === functionName) {
|
|
561
|
-
imports.push({ name: importedName, from: modulePath });
|
|
449
|
+
if (namedBindings) {
|
|
450
|
+
if (ts.isNamedImports(namedBindings)) {
|
|
451
|
+
// Named imports: import { getLocation, resetPassword } from './tools'
|
|
452
|
+
for (const element of namedBindings.elements) {
|
|
453
|
+
const importedName = element.name.getText(sourceFile);
|
|
454
|
+
if (importedName === functionName) {
|
|
455
|
+
const modulePath = (node.moduleSpecifier as ts.StringLiteral).text;
|
|
456
|
+
imports.push({ name: importedName, from: modulePath, isNamespace: false });
|
|
457
|
+
}
|
|
562
458
|
}
|
|
459
|
+
} else if (ts.isNamespaceImport(namedBindings)) {
|
|
460
|
+
// Namespace import: import * as tools from './tools'
|
|
461
|
+
// When we have tools.getLocation, we need to search in the imported module
|
|
462
|
+
const namespaceName = namedBindings.name.getText(sourceFile);
|
|
463
|
+
const modulePath = (node.moduleSpecifier as ts.StringLiteral).text;
|
|
464
|
+
imports.push({ name: namespaceName, from: modulePath, isNamespace: true });
|
|
563
465
|
}
|
|
564
466
|
}
|
|
565
467
|
}
|
|
@@ -575,16 +477,16 @@ function findFunctionDefinition(
|
|
|
575
477
|
if (resolvedPath) {
|
|
576
478
|
const importedSourceFile = program.getSourceFile(resolvedPath);
|
|
577
479
|
if (importedSourceFile) {
|
|
578
|
-
// For namespace imports, search for the function name in the imported module
|
|
579
480
|
if (imp.isNamespace) {
|
|
580
|
-
//
|
|
481
|
+
// For namespace imports, search for the function name directly in the module
|
|
482
|
+
// (e.g., tools.getLocation -> search for "getLocation" in the tools module)
|
|
581
483
|
const result = findFunctionDefinition(functionName, importedSourceFile, program);
|
|
582
484
|
if (result) {
|
|
583
485
|
return result;
|
|
584
486
|
}
|
|
585
487
|
} else {
|
|
586
|
-
// For named imports, the name matches
|
|
587
|
-
const result = findFunctionDefinition(
|
|
488
|
+
// For named imports, the imported name matches the function name
|
|
489
|
+
const result = findFunctionDefinition(imp.name, importedSourceFile, program);
|
|
588
490
|
if (result) {
|
|
589
491
|
return result;
|
|
590
492
|
}
|
|
@@ -1473,11 +1375,10 @@ async function extractFunctionMetadata(
|
|
|
1473
1375
|
* Main function
|
|
1474
1376
|
*/
|
|
1475
1377
|
async function autoDiscoverAndExtract(projectRoot: string, outputPath: string) {
|
|
1476
|
-
console.log(`\n🔍
|
|
1378
|
+
console.log(`\n🔍 Auto-discovering tools in: ${projectRoot}\n`);
|
|
1477
1379
|
|
|
1478
1380
|
// Find all TypeScript files
|
|
1479
1381
|
const files = await findToolUsageFiles(projectRoot);
|
|
1480
|
-
console.log(`📂 Scanning ${files.length} TypeScript file${files.length !== 1 ? 's' : ''}...`);
|
|
1481
1382
|
|
|
1482
1383
|
// Read tsconfig
|
|
1483
1384
|
const configPath = ts.findConfigFile(projectRoot, ts.sys.fileExists, 'tsconfig.json');
|
|
@@ -1512,34 +1413,19 @@ async function autoDiscoverAndExtract(projectRoot: string, outputPath: string) {
|
|
|
1512
1413
|
}
|
|
1513
1414
|
}
|
|
1514
1415
|
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
console.log(
|
|
1518
|
-
console.log(`
|
|
1519
|
-
console.log(` or`);
|
|
1520
|
-
console.log(` useAgent({ safeTools: [getLocation, resetPassword] })\n`);
|
|
1521
|
-
return;
|
|
1522
|
-
}
|
|
1523
|
-
|
|
1524
|
-
console.log(`\n✨ Found ${allToolUsages.length} usage site${allToolUsages.length !== 1 ? 's' : ''} with ${allToolNames.size} unique tool${allToolNames.size !== 1 ? 's' : ''}:`);
|
|
1525
|
-
allToolUsages.forEach((usage, idx) => {
|
|
1526
|
-
const relativePath = path.relative(projectRoot, usage.file);
|
|
1527
|
-
const tools = Array.from(usage.toolNames);
|
|
1528
|
-
console.log(`\n ${idx + 1}. ${usage.component} in ${relativePath}`);
|
|
1529
|
-
console.log(` Tools: ${tools.map(t => `\x1b[36m${t}\x1b[0m`).join(', ')}`);
|
|
1416
|
+
console.log(`✓ Found ${allToolUsages.length} usage site(s) with ${allToolNames.size} unique tool(s)`);
|
|
1417
|
+
allToolUsages.forEach(usage => {
|
|
1418
|
+
console.log(` - ${usage.component} in ${path.relative(projectRoot, usage.file)}`);
|
|
1419
|
+
console.log(` Tools: ${Array.from(usage.toolNames).join(', ')}`);
|
|
1530
1420
|
});
|
|
1531
1421
|
|
|
1532
1422
|
// Extract metadata for discovered tools
|
|
1533
|
-
console.log(`\n📝 Extracting
|
|
1423
|
+
console.log(`\n📝 Extracting types for discovered tools...\n`);
|
|
1534
1424
|
|
|
1535
1425
|
const functionsMap: Record<string, FunctionMetadata> = {};
|
|
1536
1426
|
const discoveredFrom: string[] = [];
|
|
1537
1427
|
|
|
1538
|
-
const
|
|
1539
|
-
let successCount = 0;
|
|
1540
|
-
let warningCount = 0;
|
|
1541
|
-
|
|
1542
|
-
for (const toolName of toolNamesArray) {
|
|
1428
|
+
for (const toolName of allToolNames) {
|
|
1543
1429
|
let found = false;
|
|
1544
1430
|
|
|
1545
1431
|
// Search in all files for the definition
|
|
@@ -1552,10 +1438,8 @@ async function autoDiscoverAndExtract(projectRoot: string, outputPath: string) {
|
|
|
1552
1438
|
if (metadata) {
|
|
1553
1439
|
functionsMap[toolName] = metadata;
|
|
1554
1440
|
discoveredFrom.push(path.relative(projectRoot, result.sourceFile.fileName));
|
|
1555
|
-
|
|
1556
|
-
console.log(` ✓ \x1b[32m${toolName}\x1b[0m \x1b[90m(${relativePath})\x1b[0m`);
|
|
1441
|
+
console.log(` ✓ ${toolName} (from ${path.relative(projectRoot, result.sourceFile.fileName)})`);
|
|
1557
1442
|
found = true;
|
|
1558
|
-
successCount++;
|
|
1559
1443
|
break;
|
|
1560
1444
|
}
|
|
1561
1445
|
}
|
|
@@ -1563,8 +1447,7 @@ async function autoDiscoverAndExtract(projectRoot: string, outputPath: string) {
|
|
|
1563
1447
|
}
|
|
1564
1448
|
|
|
1565
1449
|
if (!found) {
|
|
1566
|
-
console.log(`
|
|
1567
|
-
warningCount++;
|
|
1450
|
+
console.log(` ⚠ ${toolName} (definition not found)`);
|
|
1568
1451
|
}
|
|
1569
1452
|
}
|
|
1570
1453
|
|
|
@@ -1615,24 +1498,11 @@ export const toolMetadata = ${JSON.stringify(output, null, 2)} as const;
|
|
|
1615
1498
|
`;
|
|
1616
1499
|
|
|
1617
1500
|
fs.writeFileSync(outputPath, tsContent);
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
console.log(
|
|
1622
|
-
|
|
1623
|
-
console.log(`✅ Successfully extracted ${successCount} tool${successCount !== 1 ? 's' : ''}`);
|
|
1624
|
-
}
|
|
1625
|
-
if (warningCount > 0) {
|
|
1626
|
-
console.log(`⚠️ ${warningCount} tool${warningCount !== 1 ? 's' : ''} not found (check function names)`);
|
|
1627
|
-
}
|
|
1628
|
-
console.log(`📁 Output: \x1b[36m${relativeOutput}\x1b[0m`);
|
|
1629
|
-
console.log(`${'='.repeat(60)}\n`);
|
|
1630
|
-
|
|
1631
|
-
if (successCount > 0) {
|
|
1632
|
-
console.log(`💡 Usage in your component:`);
|
|
1633
|
-
console.log(` import { toolMetadata } from './.arcten/tool-metadata';`);
|
|
1634
|
-
console.log(` useAgent({ tools: [...], toolMetadata: toolMetadata.functions })\n`);
|
|
1635
|
-
}
|
|
1501
|
+
console.log(`\n✅ Generated metadata for ${Object.keys(functionsMap).length} tool(s)`);
|
|
1502
|
+
console.log(`📁 Output: ${outputPath}`);
|
|
1503
|
+
console.log(`\n💡 Usage in your component:`);
|
|
1504
|
+
console.log(` import { toolMetadata } from './.arcten/tool-metadata';`);
|
|
1505
|
+
console.log(` useAgent({ tools: [...], toolMetadata: toolMetadata.functions })\n`);
|
|
1636
1506
|
}
|
|
1637
1507
|
|
|
1638
1508
|
// CLI
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Wrapper script to run the TypeScript CLI
|
|
4
|
-
* Works with Node.js - no bun required!
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { spawn } from 'child_process';
|
|
8
|
-
import { fileURLToPath } from 'url';
|
|
9
|
-
import { dirname, resolve } from 'path';
|
|
10
|
-
import { existsSync } from 'fs';
|
|
11
|
-
|
|
12
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
13
|
-
const __dirname = dirname(__filename);
|
|
14
|
-
|
|
15
|
-
// Path to the TypeScript script - resolve relative to this wrapper
|
|
16
|
-
const tsScript = resolve(__dirname, 'cli-extract-types-auto.ts');
|
|
17
|
-
|
|
18
|
-
// Check if a command is available
|
|
19
|
-
function checkCommand(cmd) {
|
|
20
|
-
return new Promise((resolve) => {
|
|
21
|
-
const check = spawn(cmd, ['--version'], { stdio: 'ignore', shell: true });
|
|
22
|
-
check.on('close', (code) => {
|
|
23
|
-
resolve(code === 0);
|
|
24
|
-
});
|
|
25
|
-
check.on('error', () => {
|
|
26
|
-
resolve(false);
|
|
27
|
-
});
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
async function main() {
|
|
32
|
-
if (!existsSync(tsScript)) {
|
|
33
|
-
console.error(`❌ Error: Script not found at ${tsScript}`);
|
|
34
|
-
process.exit(1);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const args = process.argv.slice(2);
|
|
38
|
-
|
|
39
|
-
// Check for bun first (faster and preferred if available)
|
|
40
|
-
const hasBun = await checkCommand('bun');
|
|
41
|
-
|
|
42
|
-
if (hasBun) {
|
|
43
|
-
// Use bun directly - it's faster and can run TypeScript natively
|
|
44
|
-
const bunProcess = spawn('bun', [tsScript, ...args], {
|
|
45
|
-
stdio: 'inherit',
|
|
46
|
-
shell: true
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
bunProcess.on('close', (code) => {
|
|
50
|
-
process.exit(code || 0);
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
bunProcess.on('error', (err) => {
|
|
54
|
-
// If bun fails, try tsx as fallback
|
|
55
|
-
tryTsxFallback(args);
|
|
56
|
-
});
|
|
57
|
-
} else {
|
|
58
|
-
// Fallback to tsx via npx if bun isn't available
|
|
59
|
-
tryTsxFallback(args);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
async function tryTsxFallback(args) {
|
|
64
|
-
const hasNpx = await checkCommand('npx');
|
|
65
|
-
|
|
66
|
-
if (hasNpx) {
|
|
67
|
-
// Use tsx via npx - it's lightweight and works great with Node.js
|
|
68
|
-
const tsxProcess = spawn('npx', ['-y', 'tsx', tsScript, ...args], {
|
|
69
|
-
stdio: 'inherit',
|
|
70
|
-
shell: true
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
tsxProcess.on('close', (code) => {
|
|
74
|
-
process.exit(code || 0);
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
tsxProcess.on('error', (err) => {
|
|
78
|
-
console.error('❌ Error: Could not run script');
|
|
79
|
-
console.error('Please ensure you have Node.js (with npx) or bun installed');
|
|
80
|
-
process.exit(1);
|
|
81
|
-
});
|
|
82
|
-
} else {
|
|
83
|
-
console.error('❌ Error: Could not find a TypeScript runner');
|
|
84
|
-
console.error('');
|
|
85
|
-
console.error('Please install one of the following:');
|
|
86
|
-
console.error(' - bun: curl -fsSL https://bun.sh/install | bash (recommended)');
|
|
87
|
-
console.error(' - Node.js (comes with npx)');
|
|
88
|
-
process.exit(1);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
main();
|
|
93
|
-
|
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Postinstall script to check and optionally update @arcteninc/core version
|
|
4
|
-
* This helps users stay on the latest version without manually updating package.json
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
const fs = require('fs');
|
|
8
|
-
const path = require('path');
|
|
9
|
-
const { execSync } = require('child_process');
|
|
10
|
-
|
|
11
|
-
function findPackageJson(startPath = process.cwd()) {
|
|
12
|
-
let currentPath = startPath;
|
|
13
|
-
|
|
14
|
-
// Start from current directory and walk up to find package.json
|
|
15
|
-
// Skip node_modules directories
|
|
16
|
-
while (currentPath !== path.dirname(currentPath)) {
|
|
17
|
-
// Skip if we're in a node_modules directory
|
|
18
|
-
if (currentPath.includes('node_modules')) {
|
|
19
|
-
currentPath = path.dirname(currentPath);
|
|
20
|
-
continue;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const packageJsonPath = path.join(currentPath, 'package.json');
|
|
24
|
-
if (fs.existsSync(packageJsonPath)) {
|
|
25
|
-
// Make sure this isn't @arcteninc/core's own package.json
|
|
26
|
-
try {
|
|
27
|
-
const pkg = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
|
|
28
|
-
if (pkg.name === '@arcteninc/core') {
|
|
29
|
-
// This is the core package itself, go up one level
|
|
30
|
-
currentPath = path.dirname(currentPath);
|
|
31
|
-
continue;
|
|
32
|
-
}
|
|
33
|
-
} catch (e) {
|
|
34
|
-
// Invalid JSON, skip
|
|
35
|
-
currentPath = path.dirname(currentPath);
|
|
36
|
-
continue;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
return packageJsonPath;
|
|
40
|
-
}
|
|
41
|
-
currentPath = path.dirname(currentPath);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
return null;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
function getLatestVersion() {
|
|
48
|
-
try {
|
|
49
|
-
const output = execSync('npm view @arcteninc/core version', { encoding: 'utf-8', stdio: 'pipe' });
|
|
50
|
-
return output.trim();
|
|
51
|
-
} catch (error) {
|
|
52
|
-
console.warn('⚠️ Could not check latest version:', error.message);
|
|
53
|
-
return null;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
function getInstalledVersion() {
|
|
58
|
-
try {
|
|
59
|
-
const packageJsonPath = findPackageJson();
|
|
60
|
-
if (!packageJsonPath) {
|
|
61
|
-
return null;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
|
|
65
|
-
const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };
|
|
66
|
-
const version = deps['@arcteninc/core'];
|
|
67
|
-
|
|
68
|
-
return version ? { version, packageJsonPath, packageJson } : null;
|
|
69
|
-
} catch (error) {
|
|
70
|
-
return null;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// Removed auto-update function - users should update manually
|
|
75
|
-
|
|
76
|
-
function main() {
|
|
77
|
-
// Find the user's project root (not node_modules/@arcteninc/core)
|
|
78
|
-
// Walk up from current directory to find package.json that uses @arcteninc/core
|
|
79
|
-
let projectRoot = process.cwd();
|
|
80
|
-
|
|
81
|
-
// If we're in node_modules/@arcteninc/core, go up to project root
|
|
82
|
-
if (projectRoot.includes('node_modules')) {
|
|
83
|
-
// Find the project root by looking for package.json that's not @arcteninc/core
|
|
84
|
-
const parts = projectRoot.split(path.sep);
|
|
85
|
-
const nodeModulesIndex = parts.indexOf('node_modules');
|
|
86
|
-
if (nodeModulesIndex !== -1) {
|
|
87
|
-
projectRoot = parts.slice(0, nodeModulesIndex).join(path.sep);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// Change to project root to find package.json
|
|
92
|
-
const originalCwd = process.cwd();
|
|
93
|
-
try {
|
|
94
|
-
process.chdir(projectRoot);
|
|
95
|
-
} catch (e) {
|
|
96
|
-
// Can't change directory, use original
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// Only run if we're in a project that uses @arcteninc/core
|
|
100
|
-
const installed = getInstalledVersion();
|
|
101
|
-
if (!installed) {
|
|
102
|
-
process.chdir(originalCwd);
|
|
103
|
-
return; // Not installed, nothing to do
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
const latestVersion = getLatestVersion();
|
|
107
|
-
if (!latestVersion) {
|
|
108
|
-
try {
|
|
109
|
-
process.chdir(originalCwd);
|
|
110
|
-
} catch (e) {
|
|
111
|
-
// Ignore
|
|
112
|
-
}
|
|
113
|
-
return; // Couldn't check, skip
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// Extract current version number (remove ^, ~, etc.)
|
|
117
|
-
const currentVersionMatch = installed.version.match(/(\d+\.\d+\.\d+)/);
|
|
118
|
-
if (!currentVersionMatch) {
|
|
119
|
-
try {
|
|
120
|
-
process.chdir(originalCwd);
|
|
121
|
-
} catch (e) {
|
|
122
|
-
// Ignore
|
|
123
|
-
}
|
|
124
|
-
return; // Invalid version format
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
const currentVersion = currentVersionMatch[1];
|
|
128
|
-
|
|
129
|
-
if (currentVersion !== latestVersion) {
|
|
130
|
-
console.log(`\n📦 @arcteninc/core update available:`);
|
|
131
|
-
console.log(` Current: ${currentVersion}`);
|
|
132
|
-
console.log(` Latest: ${latestVersion}`);
|
|
133
|
-
|
|
134
|
-
if (installed.version.startsWith('^') || installed.version.startsWith('~')) {
|
|
135
|
-
console.log(` Run 'npm update @arcteninc/core' to update within your version range`);
|
|
136
|
-
} else {
|
|
137
|
-
console.log(` Consider updating to '^${latestVersion}' in package.json`);
|
|
138
|
-
console.log(` Then run 'npm install' to get the latest version`);
|
|
139
|
-
}
|
|
140
|
-
console.log(` Or use: \x1b[36mnpx arcten update\x1b[0m`);
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
// Restore original directory
|
|
144
|
-
try {
|
|
145
|
-
process.chdir(originalCwd);
|
|
146
|
-
} catch (e) {
|
|
147
|
-
// Ignore
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
// Only run if called directly (not when required)
|
|
152
|
-
if (require.main === module) {
|
|
153
|
-
main();
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
module.exports = { main, getLatestVersion, getInstalledVersion, findPackageJson };
|
|
157
|
-
|
package/scripts/update-core.cjs
DELETED
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Manual update command for @arcteninc/core
|
|
4
|
-
* Usage: arcten update
|
|
5
|
-
*
|
|
6
|
-
* This allows users to explicitly update their package.json
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
const fs = require('fs');
|
|
10
|
-
const path = require('path');
|
|
11
|
-
const { execSync } = require('child_process');
|
|
12
|
-
const { findPackageJson } = require('./postinstall-check-version.cjs');
|
|
13
|
-
|
|
14
|
-
function findPackageJsonLocal(startPath = process.cwd()) {
|
|
15
|
-
let currentPath = startPath;
|
|
16
|
-
|
|
17
|
-
while (currentPath !== path.dirname(currentPath)) {
|
|
18
|
-
if (currentPath.includes('node_modules')) {
|
|
19
|
-
currentPath = path.dirname(currentPath);
|
|
20
|
-
continue;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const packageJsonPath = path.join(currentPath, 'package.json');
|
|
24
|
-
if (fs.existsSync(packageJsonPath)) {
|
|
25
|
-
try {
|
|
26
|
-
const pkg = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
|
|
27
|
-
if (pkg.name === '@arcteninc/core') {
|
|
28
|
-
currentPath = path.dirname(currentPath);
|
|
29
|
-
continue;
|
|
30
|
-
}
|
|
31
|
-
} catch (e) {
|
|
32
|
-
currentPath = path.dirname(currentPath);
|
|
33
|
-
continue;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
return packageJsonPath;
|
|
37
|
-
}
|
|
38
|
-
currentPath = path.dirname(currentPath);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
return null;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
function getLatestVersion() {
|
|
45
|
-
try {
|
|
46
|
-
const output = execSync('npm view @arcteninc/core version', { encoding: 'utf-8', stdio: 'pipe' });
|
|
47
|
-
return output.trim();
|
|
48
|
-
} catch (error) {
|
|
49
|
-
console.error('❌ Could not check latest version:', error.message);
|
|
50
|
-
return null;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
function updateVersion(packageJsonPath, packageJson, latestVersion) {
|
|
55
|
-
let updated = false;
|
|
56
|
-
|
|
57
|
-
if (packageJson.dependencies && packageJson.dependencies['@arcteninc/core']) {
|
|
58
|
-
packageJson.dependencies['@arcteninc/core'] = `^${latestVersion}`;
|
|
59
|
-
updated = true;
|
|
60
|
-
}
|
|
61
|
-
if (packageJson.devDependencies && packageJson.devDependencies['@arcteninc/core']) {
|
|
62
|
-
packageJson.devDependencies['@arcteninc/core'] = `^${latestVersion}`;
|
|
63
|
-
updated = true;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
if (updated) {
|
|
67
|
-
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2) + '\n');
|
|
68
|
-
console.log(`✅ Updated to \x1b[32m^${latestVersion}\x1b[0m in package.json\n`);
|
|
69
|
-
return true;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
return false;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
function main() {
|
|
76
|
-
const packageJsonPath = findPackageJson();
|
|
77
|
-
if (!packageJsonPath) {
|
|
78
|
-
console.error('❌ Could not find package.json');
|
|
79
|
-
process.exit(1);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
|
|
83
|
-
const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };
|
|
84
|
-
const currentVersion = deps['@arcteninc/core'];
|
|
85
|
-
|
|
86
|
-
if (!currentVersion) {
|
|
87
|
-
console.error('❌ @arcteninc/core not found in dependencies');
|
|
88
|
-
process.exit(1);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
const latestVersion = getLatestVersion();
|
|
92
|
-
if (!latestVersion) {
|
|
93
|
-
process.exit(1);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
const currentVersionMatch = currentVersion.match(/(\d+\.\d+\.\d+)/);
|
|
97
|
-
if (!currentVersionMatch) {
|
|
98
|
-
console.error('❌ Invalid version format:', currentVersion);
|
|
99
|
-
process.exit(1);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
const current = currentVersionMatch[1];
|
|
103
|
-
|
|
104
|
-
if (current === latestVersion) {
|
|
105
|
-
console.log(`\n✅ Already on latest version: \x1b[32m${latestVersion}\x1b[0m\n`);
|
|
106
|
-
return;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
console.log(`\n📦 Updating @arcteninc/core\n`);
|
|
110
|
-
console.log(` Current: \x1b[33m${current}\x1b[0m`);
|
|
111
|
-
console.log(` Latest: \x1b[32m${latestVersion}\x1b[0m\n`);
|
|
112
|
-
|
|
113
|
-
if (updateVersion(packageJsonPath, packageJson, latestVersion)) {
|
|
114
|
-
console.log(`💡 Next steps:`);
|
|
115
|
-
console.log(` 1. Review the changes in package.json`);
|
|
116
|
-
console.log(` 2. Run \x1b[36mnpm install\x1b[0m to install the update\n`);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
if (require.main === module) {
|
|
121
|
-
main();
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
module.exports = { main };
|
|
125
|
-
|