@arcteninc/core 0.0.22 → 0.0.23

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arcteninc/core",
3
- "version": "0.0.22",
3
+ "version": "0.0.23",
4
4
  "type": "module",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.mjs",
@@ -57,11 +57,136 @@ async function findToolUsageFiles(projectRoot: string): Promise<string[]> {
57
57
  return files;
58
58
  }
59
59
 
60
+ /**
61
+ * Extract tool names from an expression (handles arrays, variables, useMemo, etc.)
62
+ */
63
+ function extractToolNamesFromExpression(
64
+ expr: ts.Expression,
65
+ sourceFile: ts.SourceFile,
66
+ variableMap: Map<string, ts.Expression>
67
+ ): Set<string> {
68
+ const toolNames = new Set<string>();
69
+ const visited = new Set<ts.Node>();
70
+
71
+ function extractFromExpr(node: ts.Node): void {
72
+ if (visited.has(node)) return;
73
+ visited.add(node);
74
+
75
+ // Direct array literal: [tool1, tool2]
76
+ if (ts.isArrayLiteralExpression(node)) {
77
+ for (const element of node.elements) {
78
+ if (ts.isSpreadElement(element)) {
79
+ // Handle spread: [...someArray]
80
+ extractFromExpr(element.expression);
81
+ } else {
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
+ if (simpleName && simpleName !== 'undefined' && simpleName !== 'null') {
86
+ toolNames.add(simpleName);
87
+ }
88
+ }
89
+ }
90
+ return;
91
+ }
92
+
93
+ // Variable reference: toolsList
94
+ if (ts.isIdentifier(node)) {
95
+ const varName = node.getText(sourceFile);
96
+ const varExpr = variableMap.get(varName);
97
+ if (varExpr) {
98
+ extractFromExpr(varExpr);
99
+ }
100
+ return;
101
+ }
102
+
103
+ // Property access: wrappedTools.getRAGInfo
104
+ if (ts.isPropertyAccessExpression(node)) {
105
+ const propName = node.name.getText(sourceFile);
106
+ toolNames.add(propName);
107
+ return;
108
+ }
109
+
110
+ // useMemo(() => [...], [])
111
+ if (ts.isCallExpression(node)) {
112
+ const callExpr = node.expression;
113
+ if (ts.isIdentifier(callExpr)) {
114
+ const funcName = callExpr.getText(sourceFile);
115
+ if (funcName === 'useMemo' && node.arguments.length > 0) {
116
+ const firstArg = node.arguments[0];
117
+ // Arrow function: () => [...]
118
+ if (ts.isArrowFunction(firstArg) && firstArg.body) {
119
+ if (ts.isBlock(firstArg.body)) {
120
+ // Block body: () => { return [...] }
121
+ for (const stmt of firstArg.body.statements) {
122
+ if (ts.isReturnStatement(stmt) && stmt.expression) {
123
+ extractFromExpr(stmt.expression);
124
+ }
125
+ }
126
+ } else {
127
+ // Expression body: () => [...]
128
+ extractFromExpr(firstArg.body);
129
+ }
130
+ }
131
+ // Regular function call: useMemo(fn, [])
132
+ else if (ts.isFunctionExpression(firstArg) || ts.isArrowFunction(firstArg)) {
133
+ // Can't easily extract from function body without more analysis
134
+ }
135
+ }
136
+ }
137
+ return;
138
+ }
139
+
140
+ // Parenthesized: (toolsList)
141
+ if (ts.isParenthesizedExpression(node)) {
142
+ extractFromExpr(node.expression);
143
+ return;
144
+ }
145
+ }
146
+
147
+ extractFromExpr(expr);
148
+ return toolNames;
149
+ }
150
+
151
+ /**
152
+ * Build a map of variable declarations in the file
153
+ */
154
+ function buildVariableMap(sourceFile: ts.SourceFile): Map<string, ts.Expression> {
155
+ const variableMap = new Map<string, ts.Expression>();
156
+
157
+ function visit(node: ts.Node) {
158
+ // const toolsList = [...] or const { tools } = something
159
+ if (ts.isVariableStatement(node)) {
160
+ for (const declaration of node.declarationList.declarations) {
161
+ if (ts.isIdentifier(declaration.name)) {
162
+ const varName = declaration.name.getText(sourceFile);
163
+ if (declaration.initializer) {
164
+ variableMap.set(varName, declaration.initializer);
165
+ }
166
+ }
167
+ // Handle destructuring: const { tools } = something
168
+ else if (ts.isObjectBindingPattern(declaration.name)) {
169
+ // For now, skip destructuring - can be enhanced later
170
+ }
171
+ }
172
+ }
173
+
174
+ ts.forEachChild(node, visit);
175
+ }
176
+
177
+ visit(sourceFile);
178
+ return variableMap;
179
+ }
180
+
60
181
  /**
61
182
  * Extract tool names from ArctenAgent or useAgent usage
62
183
  */
63
- function extractToolNamesFromFile(sourceFile: ts.SourceFile): ToolUsage[] {
184
+ function extractToolNamesFromFile(
185
+ sourceFile: ts.SourceFile,
186
+ program?: ts.Program
187
+ ): ToolUsage[] {
64
188
  const usages: ToolUsage[] = [];
189
+ const variableMap = buildVariableMap(sourceFile);
65
190
 
66
191
  function visit(node: ts.Node) {
67
192
  // Check for <ArctenAgent tools={[...]} safeTools={[...]} />
@@ -82,13 +207,9 @@ function extractToolNamesFromFile(sourceFile: ts.SourceFile): ToolUsage[] {
82
207
  if (attrName === 'tools' || attrName === 'safeTools') {
83
208
  if (attr.initializer && ts.isJsxExpression(attr.initializer)) {
84
209
  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
- }
210
+ if (expr) {
211
+ const extracted = extractToolNamesFromExpression(expr, sourceFile, variableMap);
212
+ extracted.forEach(name => toolNames.add(name));
92
213
  }
93
214
  }
94
215
  }
@@ -118,13 +239,12 @@ function extractToolNamesFromFile(sourceFile: ts.SourceFile): ToolUsage[] {
118
239
  if (ts.isPropertyAssignment(prop)) {
119
240
  const propName = prop.name.getText(sourceFile);
120
241
  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
- }
242
+ const extracted = extractToolNamesFromExpression(
243
+ prop.initializer,
244
+ sourceFile,
245
+ variableMap
246
+ );
247
+ extracted.forEach(name => toolNames.add(name));
128
248
  }
129
249
  }
130
250
  }
@@ -512,7 +632,7 @@ async function autoDiscoverAndExtract(projectRoot: string, outputPath: string) {
512
632
  for (const file of files) {
513
633
  const sourceFile = program.getSourceFile(file);
514
634
  if (sourceFile) {
515
- const usages = extractToolNamesFromFile(sourceFile);
635
+ const usages = extractToolNamesFromFile(sourceFile, program);
516
636
  if (usages.length > 0) {
517
637
  allToolUsages.push(...usages);
518
638
  usages.forEach(u => u.toolNames.forEach(name => allToolNames.add(name)));