@inkeep/agents-cli 0.0.0-dev-20260117013710 → 0.0.0-dev-20260117173149

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/dist/commands/init.js +6 -6
  2. package/dist/commands/pull-v3/component-parser.js +0 -2
  3. package/dist/commands/pull-v3/component-updater.js +122 -64
  4. package/dist/commands/pull-v3/components/agent-generator.js +3 -3
  5. package/dist/commands/pull-v3/components/artifact-component-generator.js +7 -7
  6. package/dist/commands/pull-v3/components/context-config-generator.js +6 -6
  7. package/dist/commands/pull-v3/components/credential-generator.js +4 -4
  8. package/dist/commands/pull-v3/components/data-component-generator.js +4 -4
  9. package/dist/commands/pull-v3/components/environment-generator.js +10 -7
  10. package/dist/commands/pull-v3/components/function-tool-generator.js +5 -7
  11. package/dist/commands/pull-v3/components/mcp-tool-generator.js +5 -5
  12. package/dist/commands/pull-v3/components/project-generator.js +4 -4
  13. package/dist/commands/pull-v3/components/status-component-generator.js +6 -6
  14. package/dist/commands/pull-v3/index.js +22 -27
  15. package/dist/commands/pull-v3/introspect-generator.js +7 -7
  16. package/dist/commands/pull-v3/llm-content-merger.js +1 -1
  17. package/dist/commands/pull-v3/new-component-generator.js +5 -16
  18. package/dist/commands/pull-v3/project-comparator.js +49 -49
  19. package/dist/commands/pull-v3/project-validator.js +5 -4
  20. package/dist/commands/pull-v3/targeted-typescript-placeholders.js +2 -2
  21. package/dist/commands/pull-v3/utils/component-registry.js +4 -7
  22. package/dist/commands/pull-v3/utils/component-tracker.js +1 -1
  23. package/dist/commands/pull-v3/utils/generator-utils.js +2 -2
  24. package/dist/commands/push.js +5 -5
  25. package/dist/utils/ci-environment.js +1 -1
  26. package/dist/utils/config.js +1 -1
  27. package/dist/utils/json-comparison.js +3 -3
  28. package/dist/utils/profile-config.js +1 -1
  29. package/dist/utils/profiles/profile-manager.js +1 -1
  30. package/dist/utils/templates.js +0 -2
  31. package/package.json +6 -4
@@ -20,7 +20,7 @@ function toCamelCase(str) {
20
20
  function formatString(str, quote = "'", multiline = false) {
21
21
  if (!str) return `${quote}${quote}`;
22
22
  if (multiline && (str.includes("\n") || str.length > 80)) return `\`${str.replace(/`/g, "\\`")}\``;
23
- return `${quote}${str.replace(new RegExp(quote, "g"), "\\" + quote)}${quote}`;
23
+ return `${quote}${str.replace(new RegExp(quote, "g"), `\\${quote}`)}${quote}`;
24
24
  }
25
25
  /**
26
26
  * Convert JSON Schema to Zod schema using existing utility
@@ -80,7 +80,7 @@ function generateDataComponentDefinition(componentId, componentData, style = DEF
80
80
  /**
81
81
  * Generate imports needed for a data component file
82
82
  */
83
- function generateDataComponentImports(componentId, componentData, style = DEFAULT_STYLE) {
83
+ function generateDataComponentImports(componentData, style = DEFAULT_STYLE) {
84
84
  const { quotes, semicolons } = style;
85
85
  const q = quotes === "single" ? "'" : "\"";
86
86
  const semi = semicolons ? ";" : "";
@@ -93,9 +93,9 @@ function generateDataComponentImports(componentId, componentData, style = DEFAUL
93
93
  * Generate complete data component file (imports + definition)
94
94
  */
95
95
  function generateDataComponentFile(componentId, componentData, style = DEFAULT_STYLE) {
96
- const imports = generateDataComponentImports(componentId, componentData, style);
96
+ const imports = generateDataComponentImports(componentData, style);
97
97
  const definition = generateDataComponentDefinition(componentId, componentData, style);
98
- return imports.join("\n") + "\n\n" + definition + "\n";
98
+ return `${imports.join("\n")}\n\n${definition}\n`;
99
99
  }
100
100
 
101
101
  //#endregion
@@ -4,10 +4,13 @@ const DEFAULT_STYLE = {
4
4
  semicolons: true,
5
5
  indentation: " "
6
6
  };
7
+ /**
8
+ * Utility functions
9
+ */
7
10
  function formatString(str, quote = "'", multiline = false) {
8
11
  if (!str) return `${quote}${quote}`;
9
12
  if (multiline && (str.includes("\n") || str.length > 80)) return `\`${str.replace(/`/g, "\\`")}\``;
10
- return `${quote}${str.replace(new RegExp(quote, "g"), "\\" + quote)}${quote}`;
13
+ return `${quote}${str.replace(new RegExp(quote, "g"), `\\${quote}`)}${quote}`;
11
14
  }
12
15
  /**
13
16
  * Format credentials object for environment settings
@@ -55,7 +58,7 @@ function formatCredentialsObject(credentials, style, indentLevel) {
55
58
  function generateEnvironmentSettingsDefinition(environmentName, environmentData, style = DEFAULT_STYLE) {
56
59
  if (!environmentName || typeof environmentName !== "string") throw new Error("environmentName is required and must be a string");
57
60
  if (!environmentData || typeof environmentData !== "object") throw new Error(`environmentData is required for environment '${environmentName}'`);
58
- const { quotes, semicolons, indentation } = style;
61
+ const { semicolons, indentation } = style;
59
62
  const semi = semicolons ? ";" : "";
60
63
  const lines = [];
61
64
  lines.push(`export const ${environmentName} = registerEnvironmentSettings({`);
@@ -71,7 +74,7 @@ function generateEnvironmentSettingsDefinition(environmentName, environmentData,
71
74
  * Generate Main Environment Settings Index (index.ts)
72
75
  */
73
76
  function generateEnvironmentIndexDefinition(environments, style = DEFAULT_STYLE) {
74
- const { quotes, semicolons, indentation } = style;
77
+ const { semicolons, indentation } = style;
75
78
  const semi = semicolons ? ";" : "";
76
79
  const lines = [];
77
80
  lines.push(`export const envSettings = createEnvironmentSettings({`);
@@ -83,7 +86,7 @@ function generateEnvironmentIndexDefinition(environments, style = DEFAULT_STYLE)
83
86
  /**
84
87
  * Generate imports for individual environment settings file
85
88
  */
86
- function generateEnvironmentSettingsImports(environmentName, environmentData, style = DEFAULT_STYLE) {
89
+ function generateEnvironmentSettingsImports(environmentData, style = DEFAULT_STYLE) {
87
90
  const { quotes, semicolons } = style;
88
91
  const q = quotes === "single" ? "'" : "\"";
89
92
  const semi = semicolons ? ";" : "";
@@ -112,9 +115,9 @@ function generateEnvironmentIndexImports(environments, style = DEFAULT_STYLE) {
112
115
  * Generate complete environment settings file
113
116
  */
114
117
  function generateEnvironmentSettingsFile(environmentName, environmentData, style = DEFAULT_STYLE) {
115
- const imports = generateEnvironmentSettingsImports(environmentName, environmentData, style);
118
+ const imports = generateEnvironmentSettingsImports(environmentData, style);
116
119
  const definition = generateEnvironmentSettingsDefinition(environmentName, environmentData, style);
117
- return imports.join("\n") + "\n\n" + definition + "\n";
120
+ return `${imports.join("\n")}\n\n${definition}\n`;
118
121
  }
119
122
  /**
120
123
  * Generate complete environment index file
@@ -122,7 +125,7 @@ function generateEnvironmentSettingsFile(environmentName, environmentData, style
122
125
  function generateEnvironmentIndexFile(environments, style = DEFAULT_STYLE) {
123
126
  const imports = generateEnvironmentIndexImports(environments, style);
124
127
  const definition = generateEnvironmentIndexDefinition(environments, style);
125
- return imports.join("\n") + "\n\n" + definition + "\n";
128
+ return `${imports.join("\n")}\n\n${definition}\n`;
126
129
  }
127
130
  /**
128
131
  * Generate environment file (alias for generateEnvironmentSettingsFile)
@@ -1,5 +1,3 @@
1
- import { jsonSchemaToZod } from "json-schema-to-zod";
2
-
3
1
  //#region src/commands/pull-v3/components/function-tool-generator.ts
4
2
  const DEFAULT_STYLE = {
5
3
  quotes: "single",
@@ -15,7 +13,7 @@ function toCamelCase(str) {
15
13
  function formatString(str, quote = "'", multiline = false) {
16
14
  if (!str) return `${quote}${quote}`;
17
15
  if (multiline && (str.includes("\n") || str.length > 80)) return `\`${str.replace(/`/g, "\\`")}\``;
18
- return `${quote}${str.replace(new RegExp(quote, "g"), "\\" + quote)}${quote}`;
16
+ return `${quote}${str.replace(new RegExp(quote, "g"), `\\${quote}`)}${quote}`;
19
17
  }
20
18
  /**
21
19
  * Format JavaScript function code with proper indentation
@@ -54,7 +52,7 @@ function generateFunctionToolDefinition(toolId, toolData, style = DEFAULT_STYLE)
54
52
  if (index === 0) return `${indentation}inputSchema: ${line}`;
55
53
  return `${indentation}${line}`;
56
54
  }).join("\n");
57
- lines.push(formattedSchema + ",");
55
+ lines.push(`${formattedSchema},`);
58
56
  }
59
57
  const executeCode = toolData.executeCode || toolData.execute;
60
58
  if (executeCode) {
@@ -73,7 +71,7 @@ function generateFunctionToolDefinition(toolId, toolData, style = DEFAULT_STYLE)
73
71
  /**
74
72
  * Generate imports needed for a function tool file
75
73
  */
76
- function generateFunctionToolImports(toolId, toolData, style = DEFAULT_STYLE) {
74
+ function generateFunctionToolImports(style = DEFAULT_STYLE) {
77
75
  const { quotes, semicolons } = style;
78
76
  const q = quotes === "single" ? "'" : "\"";
79
77
  const semi = semicolons ? ";" : "";
@@ -85,9 +83,9 @@ function generateFunctionToolImports(toolId, toolData, style = DEFAULT_STYLE) {
85
83
  * Generate complete function tool file (imports + definition)
86
84
  */
87
85
  function generateFunctionToolFile(toolId, toolData, style = DEFAULT_STYLE) {
88
- const imports = generateFunctionToolImports(toolId, toolData, style);
86
+ const imports = generateFunctionToolImports(style);
89
87
  const definition = generateFunctionToolDefinition(toolId, toolData, style);
90
- return imports.join("\n") + "\n\n" + definition + "\n";
88
+ return `${imports.join("\n")}\n\n${definition}\n`;
91
89
  }
92
90
 
93
91
  //#endregion
@@ -13,7 +13,7 @@ function toCamelCase(str) {
13
13
  function formatString(str, quote = "'", multiline = false) {
14
14
  if (!str) return `${quote}${quote}`;
15
15
  if (multiline && (str.includes("\n") || str.length > 80)) return `\`${str.replace(/`/g, "\\`")}\``;
16
- return `${quote}${str.replace(new RegExp(quote, "g"), "\\" + quote)}${quote}`;
16
+ return `${quote}${str.replace(new RegExp(quote, "g"), `\\${quote}`)}${quote}`;
17
17
  }
18
18
  /**
19
19
  * Generate MCP Tool Definition using mcpTool() builder function
@@ -47,7 +47,7 @@ function generateMcpToolDefinition(toolId, toolData, style = DEFAULT_STYLE, regi
47
47
  if (index === 0) return `${indentation}headers: ${line}`;
48
48
  return `${indentation}${line}`;
49
49
  }).join("\n");
50
- lines.push(formattedHeaders + ",");
50
+ lines.push(`${formattedHeaders},`);
51
51
  }
52
52
  if (toolData.credential) if (typeof toolData.credential === "object") {
53
53
  const credentialStr = JSON.stringify(toolData.credential);
@@ -64,7 +64,7 @@ function generateMcpToolDefinition(toolId, toolData, style = DEFAULT_STYLE, regi
64
64
  /**
65
65
  * Generate imports needed for an MCP tool file
66
66
  */
67
- function generateMcpToolImports(toolId, toolData, style = DEFAULT_STYLE) {
67
+ function generateMcpToolImports(toolData, style = DEFAULT_STYLE) {
68
68
  const { quotes, semicolons } = style;
69
69
  const q = quotes === "single" ? "'" : "\"";
70
70
  const semi = semicolons ? ";" : "";
@@ -77,9 +77,9 @@ function generateMcpToolImports(toolId, toolData, style = DEFAULT_STYLE) {
77
77
  * Generate complete MCP tool file (imports + definition)
78
78
  */
79
79
  function generateMcpToolFile(toolId, toolData, style = DEFAULT_STYLE, registry) {
80
- const imports = generateMcpToolImports(toolId, toolData, style);
80
+ const imports = generateMcpToolImports(toolData, style);
81
81
  const definition = generateMcpToolDefinition(toolId, toolData, style, registry);
82
- return imports.join("\n") + "\n\n" + definition + "\n";
82
+ return `${imports.join("\n")}\n\n${definition}\n`;
83
83
  }
84
84
 
85
85
  //#endregion
@@ -62,7 +62,7 @@ function generateProjectDefinition(projectId, projectData, style = DEFAULT_STYLE
62
62
  /**
63
63
  * Generate imports needed for a project file
64
64
  */
65
- function generateProjectImports(projectId, projectData, style = DEFAULT_STYLE, registry) {
65
+ function generateProjectImports(projectData, style = DEFAULT_STYLE, registry) {
66
66
  const imports = [];
67
67
  imports.push(generateImport(["project"], "@inkeep/agents-sdk", style));
68
68
  if (registry) {
@@ -83,8 +83,8 @@ function generateProjectImports(projectId, projectData, style = DEFAULT_STYLE, r
83
83
  else if (typeof projectData.tools === "object") toolIds = Object.keys(projectData.tools);
84
84
  for (const toolId of toolIds) {
85
85
  let componentType = "tools";
86
- if (registry && registry.get(toolId, "functionTools")) componentType = "functionTools";
87
- else if (registry && registry.get(toolId, "tools")) componentType = "tools";
86
+ if (registry?.get(toolId, "functionTools")) componentType = "functionTools";
87
+ else if (registry?.get(toolId, "tools")) componentType = "tools";
88
88
  referencedComponents.push({
89
89
  id: toolId,
90
90
  type: componentType
@@ -138,7 +138,7 @@ function generateProjectImports(projectId, projectData, style = DEFAULT_STYLE, r
138
138
  * Generate complete project file (imports + definition)
139
139
  */
140
140
  function generateProjectFile(projectId, projectData, style = DEFAULT_STYLE, registry) {
141
- return generateFileContent(generateProjectImports(projectId, projectData, style, registry), [generateProjectDefinition(projectId, projectData, style, registry)]);
141
+ return generateFileContent(generateProjectImports(projectData, style, registry), [generateProjectDefinition(projectId, projectData, style, registry)]);
142
142
  }
143
143
 
144
144
  //#endregion
@@ -21,7 +21,7 @@ function toCamelCase(str) {
21
21
  function formatString(str, quote = "'", multiline = false) {
22
22
  if (!str) return `${quote}${quote}`;
23
23
  if (multiline && (str.includes("\n") || str.length > 80)) return `\`${str.replace(/`/g, "\\`")}\``;
24
- return `${quote}${str.replace(new RegExp(quote, "g"), "\\" + quote)}${quote}`;
24
+ return `${quote}${str.replace(new RegExp(quote, "g"), `\\${quote}`)}${quote}`;
25
25
  }
26
26
  /**
27
27
  * Convert JSON Schema to Zod schema using existing utility
@@ -58,9 +58,9 @@ function generateStatusComponentDefinition(componentId, componentData, style = D
58
58
  const schemaLines = zodSchema.split("\n");
59
59
  lines.push(`${indentation}detailsSchema: ${schemaLines[0]}`);
60
60
  schemaLines.slice(1, -1).forEach((line) => {
61
- lines[lines.length - 1] += "\n" + indentation + line;
61
+ lines[lines.length - 1] += `\n${indentation}${line}`;
62
62
  });
63
- lines[lines.length - 1] += "\n" + indentation + schemaLines[schemaLines.length - 1] + ",";
63
+ lines[lines.length - 1] += `\n${indentation}${schemaLines[schemaLines.length - 1]},`;
64
64
  } else lines.push(`${indentation}detailsSchema: ${zodSchema},`);
65
65
  }
66
66
  if (lines.length > 0 && lines[lines.length - 1].endsWith(",")) lines[lines.length - 1] = lines[lines.length - 1].slice(0, -1);
@@ -70,7 +70,7 @@ function generateStatusComponentDefinition(componentId, componentData, style = D
70
70
  /**
71
71
  * Generate imports needed for a status component file
72
72
  */
73
- function generateStatusComponentImports(componentId, componentData, style = DEFAULT_STYLE) {
73
+ function generateStatusComponentImports(componentData, style = DEFAULT_STYLE) {
74
74
  const { quotes, semicolons } = style;
75
75
  const q = quotes === "single" ? "'" : "\"";
76
76
  const semi = semicolons ? ";" : "";
@@ -83,9 +83,9 @@ function generateStatusComponentImports(componentId, componentData, style = DEFA
83
83
  * Generate complete status component file (imports + definition)
84
84
  */
85
85
  function generateStatusComponentFile(componentId, componentData, style = DEFAULT_STYLE) {
86
- const imports = generateStatusComponentImports(componentId, componentData, style);
86
+ const imports = generateStatusComponentImports(componentData, style);
87
87
  const definition = generateStatusComponentDefinition(componentId, componentData, style);
88
- return imports.join("\n") + "\n\n" + definition + "\n";
88
+ return `${imports.join("\n")}\n\n${definition}\n`;
89
89
  }
90
90
 
91
91
  //#endregion
@@ -1,15 +1,13 @@
1
1
  import { ManagementApiClient } from "../../api.js";
2
- import "../../utils/config.js";
3
2
  import { initializeCommand } from "../../utils/cli-pipeline.js";
4
3
  import { performBackgroundVersionCheck } from "../../utils/background-version-check.js";
5
- import "../../utils/json-comparison.js";
6
4
  import { loadProject } from "../../utils/project-loader.js";
7
5
  import { extractSubAgents } from "./utils/component-registry.js";
8
- import { compareProjects } from "./project-comparator.js";
9
6
  import { checkAndPromptForStaleComponentCleanup, cleanupStaleComponents, copyProjectToTemp } from "./component-updater.js";
10
7
  import { introspectGenerate } from "./introspect-generator.js";
8
+ import { compareProjects } from "./project-comparator.js";
11
9
  import { existsSync, mkdirSync } from "node:fs";
12
- import { basename, dirname, join, resolve } from "node:path";
10
+ import { join, resolve } from "node:path";
13
11
  import * as p from "@clack/prompts";
14
12
  import chalk from "chalk";
15
13
  import { EventEmitter } from "node:events";
@@ -38,7 +36,7 @@ function resetStdinState() {
38
36
  /**
39
37
  * Create project directory structure
40
38
  */
41
- function createProjectStructure(projectDir, projectId) {
39
+ function createProjectStructure(projectDir) {
42
40
  const projectRoot = projectDir;
43
41
  const paths = {
44
42
  projectRoot,
@@ -60,11 +58,11 @@ function createProjectStructure(projectDir, projectId) {
60
58
  /**
61
59
  * Enrich canDelegateTo references with component type information
62
60
  */
63
- function enrichCanDelegateToWithTypes(project, debug = false) {
61
+ function enrichCanDelegateToWithTypes(project) {
64
62
  const agentIds = new Set(project.agents ? Object.keys(project.agents) : []);
65
63
  const subAgentIds = new Set(Object.keys(extractSubAgents(project)));
66
64
  const externalAgentIds = new Set(project.externalAgents ? Object.keys(project.externalAgents) : []);
67
- const enrichCanDelegateToArray = (canDelegateTo, context) => {
65
+ const enrichCanDelegateToArray = (canDelegateTo) => {
68
66
  if (!Array.isArray(canDelegateTo)) return;
69
67
  for (let i = 0; i < canDelegateTo.length; i++) {
70
68
  const item = canDelegateTo[i];
@@ -79,15 +77,15 @@ function enrichCanDelegateToWithTypes(project, debug = false) {
79
77
  }
80
78
  };
81
79
  if (project.agents) {
82
- for (const [_, agentData] of Object.entries(project.agents)) if (agentData.subAgents) {
83
- for (const [subAgentId, subAgentData] of Object.entries(agentData.subAgents)) if (subAgentData.canDelegateTo) enrichCanDelegateToArray(subAgentData.canDelegateTo, `subAgent:${subAgentId}`);
80
+ for (const agentData of Object.values(project.agents)) if (agentData.subAgents) {
81
+ for (const subAgentData of Object.values(agentData.subAgents)) if (subAgentData.canDelegateTo) enrichCanDelegateToArray(subAgentData.canDelegateTo);
84
82
  }
85
83
  }
86
84
  }
87
85
  /**
88
86
  * Read existing project from filesystem if it exists
89
87
  */
90
- async function readExistingProject(projectRoot, debug = false) {
88
+ async function readExistingProject(projectRoot) {
91
89
  if (!existsSync(join(projectRoot, "index.ts"))) return null;
92
90
  try {
93
91
  const { loadProject: loadProject$1 } = await import("../../utils/project-loader.js");
@@ -97,9 +95,7 @@ async function readExistingProject(projectRoot, debug = false) {
97
95
  reject(/* @__PURE__ */ new Error("getFullDefinition() timed out after 30 seconds - likely circular reference or infinite loop in local project"));
98
96
  }, 3e4);
99
97
  })]);
100
- } catch (error) {
101
- const errorMessage = error instanceof Error ? error.message : String(error);
102
- errorMessage.includes("Credential") && errorMessage.includes("not found");
98
+ } catch {
103
99
  return null;
104
100
  }
105
101
  }
@@ -125,7 +121,7 @@ async function pullV3Command(options) {
125
121
  else console.log(chalk.gray(" Smart comparison • Detect all changes • Targeted updates"));
126
122
  const s = p.spinner();
127
123
  try {
128
- const { config, profile, isCI } = await initializeCommand({
124
+ const { config, isCI } = await initializeCommand({
129
125
  configPath: options.config,
130
126
  profileName: options.profile,
131
127
  tag: options.tag,
@@ -219,21 +215,20 @@ async function pullV3Command(options) {
219
215
  }
220
216
  if (remoteProject.agents && remoteProject.tools) {
221
217
  const projectToolIds = Object.keys(remoteProject.tools);
222
- for (const [agentId, agentData] of Object.entries(remoteProject.agents)) if (agentData.tools) {
223
- Object.keys(agentData.tools).length;
218
+ for (const agentData of Object.values(remoteProject.agents)) if (agentData.tools) {
224
219
  const agentSpecificTools = Object.fromEntries(Object.entries(agentData.tools).filter(([toolId]) => !projectToolIds.includes(toolId)));
225
220
  if (Object.keys(agentSpecificTools).length > 0) agentData.tools = agentSpecificTools;
226
221
  else delete agentData.tools;
227
222
  }
228
223
  }
229
- enrichCanDelegateToWithTypes(remoteProject, options.debug);
224
+ enrichCanDelegateToWithTypes(remoteProject);
230
225
  s.message("Project data fetched");
231
226
  if (options.json) {
232
227
  console.log(JSON.stringify(remoteProject, null, 2));
233
228
  restoreLogLevel();
234
229
  return;
235
230
  }
236
- const paths = createProjectStructure(projectDir, projectId);
231
+ const paths = createProjectStructure(projectDir);
237
232
  if (options.introspect) {
238
233
  console.log(chalk.yellow("\n🔍 Introspect mode: Regenerating all files from scratch"));
239
234
  s.start("Generating all files deterministically...");
@@ -247,7 +242,7 @@ async function pullV3Command(options) {
247
242
  if (batchMode) return { success: true };
248
243
  process.exit(0);
249
244
  }
250
- const localProject = await readExistingProject(paths.projectRoot, options.debug);
245
+ const localProject = await readExistingProject(paths.projectRoot);
251
246
  if (!localProject) s.message("No existing project found - treating as new project");
252
247
  else s.message("Existing project loaded");
253
248
  s.start("Building component registry from local files...");
@@ -261,7 +256,7 @@ async function pullV3Command(options) {
261
256
  const nameGroups = /* @__PURE__ */ new Map();
262
257
  for (const comp of allComponents) {
263
258
  if (!nameGroups.has(comp.name)) nameGroups.set(comp.name, []);
264
- nameGroups.get(comp.name).push(comp);
259
+ nameGroups.get(comp.name)?.push(comp);
265
260
  }
266
261
  for (const [varName, components] of nameGroups.entries()) if (components.length > 1) {
267
262
  console.log(chalk.red(` ❌ Variable name conflict: "${varName}"`));
@@ -269,7 +264,7 @@ async function pullV3Command(options) {
269
264
  } else console.log(chalk.gray(` ✅ ${varName} (${components[0].type}:${components[0].id})`));
270
265
  }
271
266
  s.start("Comparing projects for changes...");
272
- const comparison = await compareProjects(localProject, remoteProject, localRegistry, options.debug);
267
+ const comparison = await compareProjects(localProject, remoteProject, options.debug);
273
268
  if (!comparison.hasChanges && !options.force) {
274
269
  s.stop();
275
270
  console.log(chalk.green("✅ Project is already up to date"));
@@ -289,7 +284,7 @@ async function pullV3Command(options) {
289
284
  copyProjectToTemp(paths.projectRoot, tempDirName);
290
285
  console.log(chalk.green(`✅ Existing project copied to temp directory`));
291
286
  s.start("Checking for stale components...");
292
- const shouldCleanupStale = await checkAndPromptForStaleComponentCleanup(paths.projectRoot, remoteProject, localRegistry);
287
+ const shouldCleanupStale = await checkAndPromptForStaleComponentCleanup(remoteProject, localRegistry);
293
288
  resetStdinState();
294
289
  if (shouldCleanupStale) {
295
290
  s.start("Cleaning up stale components from temp directory...");
@@ -315,7 +310,7 @@ async function pullV3Command(options) {
315
310
  const nameGroups = /* @__PURE__ */ new Map();
316
311
  for (const comp of allComponents) {
317
312
  if (!nameGroups.has(comp.name)) nameGroups.set(comp.name, []);
318
- nameGroups.get(comp.name).push(comp);
313
+ nameGroups.get(comp.name)?.push(comp);
319
314
  }
320
315
  for (const [varName, components] of nameGroups.entries()) if (components.length > 1) {
321
316
  console.log(chalk.red(` ❌ Variable name conflict: "${varName}"`));
@@ -333,9 +328,9 @@ async function pullV3Command(options) {
333
328
  const newComponentsForContext = newComponentResults && newComponentResults.length > 0 ? newComponentResults.filter((result) => result.success).map((result) => ({
334
329
  componentId: result.componentId,
335
330
  componentType: result.componentType,
336
- filePath: result.filePath.replace(paths.projectRoot + "/", "")
331
+ filePath: result.filePath.replace(`${paths.projectRoot}/`, "")
337
332
  })) : void 0;
338
- await updateModifiedComponents(comparison, remoteProject, localRegistry, paths.projectRoot, options.env || "development", options.debug, tempDirName, newComponentsForContext);
333
+ await updateModifiedComponents(comparison, remoteProject, localRegistry, paths.projectRoot, options.debug, tempDirName, newComponentsForContext);
339
334
  }
340
335
  s.start("Generating project index file in temp directory...");
341
336
  const { generateProjectIndex } = await import("./project-index-generator.js");
@@ -380,7 +375,7 @@ async function pullAllProjects(options) {
380
375
  console.log(chalk.gray(" • Existing projects: Smart comparison + LLM merging + confirmation prompts"));
381
376
  console.log(chalk.gray(" • New projects: Fresh generation with introspect mode\n"));
382
377
  performBackgroundVersionCheck();
383
- const { config, profile, isCI } = await initializeCommand({
378
+ const { config, isCI } = await initializeCommand({
384
379
  configPath: options.config,
385
380
  profileName: options.profile,
386
381
  tag: options.tag,
@@ -487,7 +482,7 @@ async function pullSingleProject(projectId, projectName, options, config, isCI)
487
482
  else delete process.env.LOG_LEVEL;
488
483
  };
489
484
  const remoteProject = await (await ManagementApiClient.create(config.agentsManageApiUrl, options.config, config.tenantId, projectId, isCI, config.agentsManageApiKey)).getFullProject(projectId);
490
- await introspectGenerate(remoteProject, createProjectStructure(targetDir, projectId), options.env || "development", false);
485
+ await introspectGenerate(remoteProject, createProjectStructure(targetDir), options.env || "development", false);
491
486
  restoreLogLevel();
492
487
  return {
493
488
  projectId,
@@ -33,7 +33,7 @@ function ensureDir(filePath) {
33
33
  * Check if an agent is complete enough for code generation
34
34
  * An agent needs a name, defaultSubAgentId, and at least one sub-agent
35
35
  */
36
- function isAgentComplete(agentId, agentData) {
36
+ function isAgentComplete(agentData) {
37
37
  if (!agentData.name) return {
38
38
  complete: false,
39
39
  reason: "missing name"
@@ -102,7 +102,7 @@ async function introspectGenerate(project, paths, environment, debug, options =
102
102
  generatedFiles.push(functionFile);
103
103
  functionToolsGenerated.add(toolId);
104
104
  }
105
- if (project.agents) for (const [agentId, agentData] of Object.entries(project.agents)) {
105
+ if (project.agents) for (const agentData of Object.values(project.agents)) {
106
106
  const agentFunctionTools = agentData.functionTools;
107
107
  const agentFunctions = agentData.functions;
108
108
  if (agentFunctionTools) for (const [toolId, toolData] of Object.entries(agentFunctionTools)) {
@@ -126,7 +126,7 @@ async function introspectGenerate(project, paths, environment, debug, options =
126
126
  }
127
127
  }
128
128
  if (project.functions) {
129
- for (const [funcId, funcData] of Object.entries(project.functions)) if (!functionToolsGenerated.has(funcId)) {
129
+ for (const funcId of Object.keys(project.functions)) if (!functionToolsGenerated.has(funcId)) {
130
130
  if (!(Object.values(project.functionTools || {}).some((ft) => ft.functionId === funcId) || Object.values(project.agents || {}).some((agent) => Object.values(agent.functionTools || {}).some((ft) => ft.functionId === funcId))) && debug) console.log(chalk.yellow(`⚠️ Skipping orphaned function '${funcId}' - no functionTool references it`));
131
131
  }
132
132
  }
@@ -182,7 +182,7 @@ async function introspectGenerate(project, paths, environment, debug, options =
182
182
  }
183
183
  const completeAgentIds = /* @__PURE__ */ new Set();
184
184
  if (project.agents) for (const [agentId, agentData] of Object.entries(project.agents)) {
185
- const completeness = isAgentComplete(agentId, agentData);
185
+ const completeness = isAgentComplete(agentData);
186
186
  if (completeness.complete) completeAgentIds.add(agentId);
187
187
  else {
188
188
  skippedAgents.push({
@@ -196,7 +196,7 @@ async function introspectGenerate(project, paths, environment, debug, options =
196
196
  let totalSubAgents = 0;
197
197
  for (const [agentId, agentData] of Object.entries(project.agents)) {
198
198
  if (!completeAgentIds.has(agentId)) continue;
199
- if (agentData.subAgents) for (const [subAgentId, subAgentData] of Object.entries(agentData.subAgents)) totalSubAgents++;
199
+ if (agentData.subAgents) for (const _subAgentId of Object.keys(agentData.subAgents)) totalSubAgents++;
200
200
  }
201
201
  if (totalSubAgents > 0) for (const [agentId, agentData] of Object.entries(project.agents)) {
202
202
  if (!completeAgentIds.has(agentId)) continue;
@@ -251,7 +251,7 @@ async function introspectGenerate(project, paths, environment, debug, options =
251
251
  */
252
252
  function findContextConfigData(project, contextId) {
253
253
  if (project.agents) {
254
- for (const [agentId, agentData] of Object.entries(project.agents)) if (agentData.contextConfig) {
254
+ for (const agentData of Object.values(project.agents)) if (agentData.contextConfig) {
255
255
  if (agentData.contextConfig.id === contextId) return agentData.contextConfig;
256
256
  }
257
257
  }
@@ -261,7 +261,7 @@ function findContextConfigData(project, contextId) {
261
261
  */
262
262
  function findStatusComponentData(project, statusId) {
263
263
  if (project.agents) {
264
- for (const [agentId, agentData] of Object.entries(project.agents)) if (agentData.statusUpdates && agentData.statusUpdates.statusComponents) for (const statusComp of agentData.statusUpdates.statusComponents) {
264
+ for (const agentData of Object.values(project.agents)) if (agentData.statusUpdates?.statusComponents) for (const statusComp of agentData.statusUpdates.statusComponents) {
265
265
  let compId;
266
266
  if (typeof statusComp === "string") compId = statusComp;
267
267
  else if (typeof statusComp === "object" && statusComp) compId = statusComp.type;
@@ -54,7 +54,7 @@ async function mergeComponentsWithLLM(request) {
54
54
  let relativePath = "";
55
55
  for (let i = 0; i < upLevels; i++) relativePath += "../";
56
56
  relativePath += toParts.slice(commonLength).join("/");
57
- return relativePath.startsWith("../") ? relativePath : "./" + relativePath;
57
+ return relativePath.startsWith("../") ? relativePath : `./${relativePath}`;
58
58
  }
59
59
  const componentsToExportList = componentsToExport && componentsToExport.length > 0 ? componentsToExport.map((c) => `- ${c.variableName} (${c.reason})`).join("\n") : "";
60
60
  const prompt = `You are a TypeScript code expert tasked with intelligently merging component updates.
@@ -75,10 +75,9 @@ function generateComponentContent(componentType, componentId, componentData, com
75
75
  case "functionTools": return generateFunctionToolFile(componentId, componentData, defaultStyle);
76
76
  case "credentials": return generateCredentialFile(componentId, componentData, defaultStyle);
77
77
  case "contextConfigs": {
78
- const agentId = componentData._agentId;
79
78
  const cleanComponentData = { ...componentData };
80
79
  delete cleanComponentData._agentId;
81
- return generateContextConfigFile(componentId, cleanComponentData, defaultStyle, componentRegistry, agentId);
80
+ return generateContextConfigFile(componentId, cleanComponentData, defaultStyle, componentRegistry);
82
81
  }
83
82
  default: throw new Error(`No generator for component type: ${componentType}`);
84
83
  }
@@ -132,7 +131,7 @@ async function createNewComponents(comparison, remoteProject, localRegistry, pat
132
131
  const addedComponents = changes.added || [];
133
132
  for (const componentId of addedComponents) {
134
133
  if (localRegistry.get(componentId, componentType)) continue;
135
- const relativePath = determineNewFilePath(componentType, componentId, targetPaths).replace((tempDirName ? targetPaths.projectRoot : paths.projectRoot) + "/", "");
134
+ const relativePath = determineNewFilePath(componentType, componentId, targetPaths).replace(`${tempDirName ? targetPaths.projectRoot : paths.projectRoot}/`, "");
136
135
  let explicitVariableName;
137
136
  if (componentType === "contextConfigs") {
138
137
  const contextResult = findContextConfigData(remoteProject, componentId);
@@ -192,18 +191,8 @@ async function createNewComponents(comparison, remoteProject, localRegistry, pat
192
191
  });
193
192
  continue;
194
193
  }
195
- try {
196
- mkdirSync(dirname(filePath), { recursive: true });
197
- } catch (dirError) {
198
- throw dirError;
199
- }
200
- let content;
201
- try {
202
- content = generateComponentContent(componentType, componentId, componentData, localRegistry);
203
- } catch (genError) {
204
- throw genError;
205
- }
206
- writeFileSync(filePath, content, "utf8");
194
+ mkdirSync(dirname(filePath), { recursive: true });
195
+ writeFileSync(filePath, generateComponentContent(componentType, componentId, componentData, localRegistry), "utf8");
207
196
  const registryEntry = localRegistry.get(componentId, componentType);
208
197
  if (!registryEntry) throw new Error(`Component ${componentId} (${componentType}) was not registered in the registry`);
209
198
  const variableName = registryEntry.name;
@@ -259,7 +248,7 @@ async function createNewComponents(comparison, remoteProject, localRegistry, pat
259
248
  */
260
249
  function findStatusComponentData(project, statusId) {
261
250
  if (project.agents) {
262
- for (const [agentId, agentData] of Object.entries(project.agents)) if (agentData.statusUpdates && agentData.statusUpdates.statusComponents) for (const statusComp of agentData.statusUpdates.statusComponents) {
251
+ for (const agentData of Object.values(project.agents)) if (agentData.statusUpdates?.statusComponents) for (const statusComp of agentData.statusUpdates.statusComponents) {
263
252
  let compId;
264
253
  if (typeof statusComp === "string") compId = statusComp;
265
254
  else if (typeof statusComp === "object" && statusComp) compId = statusComp.type;