@inkeep/agents-cli 0.39.4 → 0.40.0

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 (80) hide show
  1. package/dist/_virtual/rolldown_runtime.js +7 -0
  2. package/dist/api.js +185 -0
  3. package/dist/commands/add.js +139 -0
  4. package/dist/commands/config.js +86 -0
  5. package/dist/commands/dev.js +259 -0
  6. package/dist/commands/init.js +360 -0
  7. package/dist/commands/list-agents.js +56 -0
  8. package/dist/commands/login.js +179 -0
  9. package/dist/commands/logout.js +56 -0
  10. package/dist/commands/profile.js +276 -0
  11. package/dist/{component-parser2.js → commands/pull-v3/component-parser.js} +16 -3
  12. package/dist/commands/pull-v3/component-updater.js +710 -0
  13. package/dist/commands/pull-v3/components/agent-generator.js +241 -0
  14. package/dist/commands/pull-v3/components/artifact-component-generator.js +127 -0
  15. package/dist/commands/pull-v3/components/context-config-generator.js +190 -0
  16. package/dist/commands/pull-v3/components/credential-generator.js +89 -0
  17. package/dist/commands/pull-v3/components/data-component-generator.js +102 -0
  18. package/dist/commands/pull-v3/components/environment-generator.js +170 -0
  19. package/dist/commands/pull-v3/components/external-agent-generator.js +75 -0
  20. package/dist/commands/pull-v3/components/function-tool-generator.js +94 -0
  21. package/dist/commands/pull-v3/components/mcp-tool-generator.js +86 -0
  22. package/dist/commands/pull-v3/components/project-generator.js +145 -0
  23. package/dist/commands/pull-v3/components/status-component-generator.js +92 -0
  24. package/dist/commands/pull-v3/components/sub-agent-generator.js +285 -0
  25. package/dist/commands/pull-v3/index.js +510 -0
  26. package/dist/commands/pull-v3/introspect-generator.js +278 -0
  27. package/dist/commands/pull-v3/llm-content-merger.js +192 -0
  28. package/dist/{new-component-generator.js → commands/pull-v3/new-component-generator.js} +14 -3
  29. package/dist/commands/pull-v3/project-comparator.js +914 -0
  30. package/dist/{project-index-generator.js → commands/pull-v3/project-index-generator.js} +1 -2
  31. package/dist/{project-validator.js → commands/pull-v3/project-validator.js} +4 -4
  32. package/dist/commands/pull-v3/targeted-typescript-placeholders.js +173 -0
  33. package/dist/commands/pull-v3/utils/component-registry.js +369 -0
  34. package/dist/commands/pull-v3/utils/component-tracker.js +165 -0
  35. package/dist/commands/pull-v3/utils/generator-utils.js +146 -0
  36. package/dist/commands/pull-v3/utils/model-provider-detector.js +44 -0
  37. package/dist/commands/push.js +326 -0
  38. package/dist/commands/status.js +89 -0
  39. package/dist/commands/update.js +97 -0
  40. package/dist/commands/whoami.js +38 -0
  41. package/dist/config.js +0 -1
  42. package/dist/env.js +30 -0
  43. package/dist/exports.js +3 -0
  44. package/dist/index.js +28 -196514
  45. package/dist/instrumentation.js +47 -0
  46. package/dist/types/agent.js +1 -0
  47. package/dist/types/tsx.d.d.ts +1 -0
  48. package/dist/utils/background-version-check.js +19 -0
  49. package/dist/utils/ci-environment.js +87 -0
  50. package/dist/utils/cli-pipeline.js +158 -0
  51. package/dist/utils/config.js +290 -0
  52. package/dist/utils/credentials.js +132 -0
  53. package/dist/utils/environment-loader.js +28 -0
  54. package/dist/utils/file-finder.js +62 -0
  55. package/dist/utils/json-comparator.js +185 -0
  56. package/dist/utils/json-comparison.js +232 -0
  57. package/dist/utils/mcp-runner.js +120 -0
  58. package/dist/utils/model-config.js +182 -0
  59. package/dist/utils/package-manager.js +58 -0
  60. package/dist/utils/profile-config.js +85 -0
  61. package/dist/utils/profiles/index.js +4 -0
  62. package/dist/utils/profiles/profile-manager.js +219 -0
  63. package/dist/utils/profiles/types.js +62 -0
  64. package/dist/utils/project-directory.js +33 -0
  65. package/dist/utils/project-loader.js +29 -0
  66. package/dist/utils/schema-introspection.js +44 -0
  67. package/dist/utils/templates.js +198 -0
  68. package/dist/utils/tsx-loader.js +27 -0
  69. package/dist/utils/url.js +26 -0
  70. package/dist/utils/version-check.js +79 -0
  71. package/package.json +4 -19
  72. package/dist/component-parser.js +0 -4
  73. package/dist/component-updater.js +0 -4
  74. package/dist/config2.js +0 -4
  75. package/dist/credential-stores.js +0 -4
  76. package/dist/environment-generator.js +0 -4
  77. package/dist/nodefs.js +0 -27
  78. package/dist/opfs-ahp.js +0 -368
  79. package/dist/project-loader.js +0 -4
  80. package/dist/tsx-loader.js +0 -4
@@ -0,0 +1,278 @@
1
+ import { DEFAULT_STYLE } from "./utils/generator-utils.js";
2
+ import { generateAgentFile } from "./components/agent-generator.js";
3
+ import { generateArtifactComponentFile } from "./components/artifact-component-generator.js";
4
+ import { generateContextConfigFile } from "./components/context-config-generator.js";
5
+ import { generateCredentialFile } from "./components/credential-generator.js";
6
+ import { generateDataComponentFile } from "./components/data-component-generator.js";
7
+ import { generateEnvironmentFile, generateEnvironmentIndexFile } from "./components/environment-generator.js";
8
+ import { generateExternalAgentFile } from "./components/external-agent-generator.js";
9
+ import { generateFunctionToolFile } from "./components/function-tool-generator.js";
10
+ import { generateMcpToolFile } from "./components/mcp-tool-generator.js";
11
+ import { generateProjectFile } from "./components/project-generator.js";
12
+ import { generateStatusComponentFile } from "./components/status-component-generator.js";
13
+ import { generateSubAgentFile } from "./components/sub-agent-generator.js";
14
+ import { ComponentRegistry, registerAllComponents } from "./utils/component-registry.js";
15
+ import { mkdirSync, writeFileSync } from "node:fs";
16
+ import { dirname, join } from "node:path";
17
+ import chalk from "chalk";
18
+
19
+ //#region src/commands/pull-v3/introspect-generator.ts
20
+ /**
21
+ * Introspect Generator - Complete project regeneration
22
+ *
23
+ * This module handles the --introspect mode which regenerates all files
24
+ * from scratch without any comparison or diffing logic.
25
+ */
26
+ /**
27
+ * Helper function to ensure directory exists
28
+ */
29
+ function ensureDir(filePath) {
30
+ mkdirSync(dirname(filePath), { recursive: true });
31
+ }
32
+ /**
33
+ * Check if an agent is complete enough for code generation
34
+ * An agent needs a name, defaultSubAgentId, and at least one sub-agent
35
+ */
36
+ function isAgentComplete(agentId, agentData) {
37
+ if (!agentData.name) return {
38
+ complete: false,
39
+ reason: "missing name"
40
+ };
41
+ if (!agentData.defaultSubAgentId) return {
42
+ complete: false,
43
+ reason: "missing defaultSubAgentId (no sub-agents configured)"
44
+ };
45
+ if (!agentData.subAgents || Object.keys(agentData.subAgents).length === 0) return {
46
+ complete: false,
47
+ reason: "no sub-agents defined"
48
+ };
49
+ return { complete: true };
50
+ }
51
+ /**
52
+ * Generate all files from scratch using deterministic generation
53
+ */
54
+ async function introspectGenerate(project, paths, environment, debug, options = {}) {
55
+ if (debug) console.log(chalk.gray("🔍 Regenerating all project files..."));
56
+ const generatedFiles = [];
57
+ const style = {
58
+ ...DEFAULT_STYLE,
59
+ ...options.codeStyle
60
+ };
61
+ const skippedAgents = [];
62
+ const registry = new ComponentRegistry();
63
+ try {
64
+ registerAllComponents(project, registry);
65
+ if (project.credentialReferences) for (const [credId, credData] of Object.entries(project.credentialReferences)) {
66
+ const credentialFile = join(paths.credentialsDir, `${credId}.ts`);
67
+ const credentialContent = generateCredentialFile(credId, credData, style);
68
+ ensureDir(credentialFile);
69
+ writeFileSync(credentialFile, credentialContent, "utf-8");
70
+ generatedFiles.push(credentialFile);
71
+ }
72
+ const envFile = join(paths.environmentsDir, `${environment}.env.ts`);
73
+ const envContent = generateEnvironmentFile(environment, {
74
+ name: `${environment} Environment`,
75
+ description: `Environment configuration for ${environment}`,
76
+ credentials: project.credentialReferences ? Object.keys(project.credentialReferences) : []
77
+ }, style, registry);
78
+ ensureDir(envFile);
79
+ writeFileSync(envFile, envContent, "utf-8");
80
+ generatedFiles.push(envFile);
81
+ const envIndexFile = join(paths.environmentsDir, "index.ts");
82
+ const envIndexContent = generateEnvironmentIndexFile([environment], style);
83
+ ensureDir(envIndexFile);
84
+ writeFileSync(envIndexFile, envIndexContent, "utf-8");
85
+ generatedFiles.push(envIndexFile);
86
+ const functionToolsGenerated = /* @__PURE__ */ new Set();
87
+ if (project.functionTools) for (const [toolId, toolData] of Object.entries(project.functionTools)) {
88
+ const functionId = toolData.functionId;
89
+ const funcData = functionId ? project.functions?.[functionId] : void 0;
90
+ const mergedData = {
91
+ name: toolData.name,
92
+ description: toolData.description,
93
+ inputSchema: funcData?.inputSchema,
94
+ executeCode: funcData?.executeCode,
95
+ execute: funcData?.executeCode,
96
+ dependencies: funcData?.dependencies
97
+ };
98
+ const functionFile = join(paths.toolsDir, "functions", `${toolId}.ts`);
99
+ const functionContent = generateFunctionToolFile(toolId, mergedData, style);
100
+ ensureDir(functionFile);
101
+ writeFileSync(functionFile, functionContent, "utf-8");
102
+ generatedFiles.push(functionFile);
103
+ functionToolsGenerated.add(toolId);
104
+ }
105
+ if (project.agents) for (const [agentId, agentData] of Object.entries(project.agents)) {
106
+ const agentFunctionTools = agentData.functionTools;
107
+ const agentFunctions = agentData.functions;
108
+ if (agentFunctionTools) for (const [toolId, toolData] of Object.entries(agentFunctionTools)) {
109
+ if (functionToolsGenerated.has(toolId)) continue;
110
+ const functionId = toolData.functionId;
111
+ const funcData = functionId ? agentFunctions?.[functionId] || project.functions?.[functionId] : void 0;
112
+ const mergedData = {
113
+ name: toolData.name,
114
+ description: toolData.description,
115
+ inputSchema: funcData?.inputSchema,
116
+ executeCode: funcData?.executeCode,
117
+ execute: funcData?.executeCode,
118
+ dependencies: funcData?.dependencies
119
+ };
120
+ const functionFile = join(paths.toolsDir, "functions", `${toolId}.ts`);
121
+ const functionContent = generateFunctionToolFile(toolId, mergedData, style);
122
+ ensureDir(functionFile);
123
+ writeFileSync(functionFile, functionContent, "utf-8");
124
+ generatedFiles.push(functionFile);
125
+ functionToolsGenerated.add(toolId);
126
+ }
127
+ }
128
+ if (project.functions) {
129
+ for (const [funcId, funcData] of Object.entries(project.functions)) if (!functionToolsGenerated.has(funcId)) {
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
+ }
132
+ }
133
+ if (project.tools) for (const [toolId, toolData] of Object.entries(project.tools)) {
134
+ const toolFile = join(paths.toolsDir, `${toolId}.ts`);
135
+ const toolContent = generateMcpToolFile(toolId, toolData, style, registry);
136
+ ensureDir(toolFile);
137
+ writeFileSync(toolFile, toolContent, "utf-8");
138
+ generatedFiles.push(toolFile);
139
+ }
140
+ if (project.dataComponents) for (const [dataId, dataData] of Object.entries(project.dataComponents)) {
141
+ const dataFile = join(paths.dataComponentsDir, `${dataId}.ts`);
142
+ const dataContent = generateDataComponentFile(dataId, dataData, style);
143
+ ensureDir(dataFile);
144
+ writeFileSync(dataFile, dataContent, "utf-8");
145
+ generatedFiles.push(dataFile);
146
+ }
147
+ if (project.artifactComponents) for (const [artifactId, artifactData] of Object.entries(project.artifactComponents)) {
148
+ const artifactFile = join(paths.artifactComponentsDir, `${artifactId}.ts`);
149
+ const artifactContent = generateArtifactComponentFile(artifactId, artifactData, style);
150
+ ensureDir(artifactFile);
151
+ writeFileSync(artifactFile, artifactContent, "utf-8");
152
+ generatedFiles.push(artifactFile);
153
+ }
154
+ const registeredStatusComponents = registry.getAllComponents().filter((c) => c.type === "statusComponents");
155
+ if (registeredStatusComponents.length > 0) for (const statusComp of registeredStatusComponents) {
156
+ const statusData = findStatusComponentData(project, statusComp.id);
157
+ if (statusData) {
158
+ const statusFile = join(paths.statusComponentsDir, `${statusComp.id}.ts`);
159
+ const statusContent = generateStatusComponentFile(statusComp.id, statusData, style);
160
+ ensureDir(statusFile);
161
+ writeFileSync(statusFile, statusContent, "utf-8");
162
+ generatedFiles.push(statusFile);
163
+ }
164
+ }
165
+ if (project.externalAgents) for (const [extAgentId, extAgentData] of Object.entries(project.externalAgents)) {
166
+ const extAgentFile = join(paths.externalAgentsDir, `${extAgentId}.ts`);
167
+ const extAgentContent = generateExternalAgentFile(extAgentId, extAgentData, style, registry);
168
+ ensureDir(extAgentFile);
169
+ writeFileSync(extAgentFile, extAgentContent, "utf-8");
170
+ generatedFiles.push(extAgentFile);
171
+ }
172
+ const registeredContextConfigs = registry.getAllComponents().filter((c) => c.type === "contextConfigs");
173
+ if (registeredContextConfigs.length > 0) for (const contextComp of registeredContextConfigs) {
174
+ const contextData = findContextConfigData(project, contextComp.id);
175
+ if (contextData) {
176
+ const contextFile = join(paths.contextConfigsDir, `${contextComp.id}.ts`);
177
+ const contextContent = generateContextConfigFile(contextComp.id, contextData, style, registry);
178
+ ensureDir(contextFile);
179
+ writeFileSync(contextFile, contextContent, "utf-8");
180
+ generatedFiles.push(contextFile);
181
+ }
182
+ }
183
+ const completeAgentIds = /* @__PURE__ */ new Set();
184
+ if (project.agents) for (const [agentId, agentData] of Object.entries(project.agents)) {
185
+ const completeness = isAgentComplete(agentId, agentData);
186
+ if (completeness.complete) completeAgentIds.add(agentId);
187
+ else {
188
+ skippedAgents.push({
189
+ id: agentId,
190
+ reason: completeness.reason || "incomplete"
191
+ });
192
+ if (debug) console.log(chalk.yellow(`⚠️ Skipping incomplete agent '${agentId}': ${completeness.reason}`));
193
+ }
194
+ }
195
+ if (project.agents && Object.keys(project.agents).length > 0) {
196
+ let totalSubAgents = 0;
197
+ for (const [agentId, agentData] of Object.entries(project.agents)) {
198
+ if (!completeAgentIds.has(agentId)) continue;
199
+ if (agentData.subAgents) for (const [subAgentId, subAgentData] of Object.entries(agentData.subAgents)) totalSubAgents++;
200
+ }
201
+ if (totalSubAgents > 0) for (const [agentId, agentData] of Object.entries(project.agents)) {
202
+ if (!completeAgentIds.has(agentId)) continue;
203
+ if (agentData.subAgents) {
204
+ const contextConfigData = agentData.contextConfig?.id ? findContextConfigData(project, agentData.contextConfig.id) : void 0;
205
+ for (const [subAgentId, subAgentData] of Object.entries(agentData.subAgents)) {
206
+ const subAgentFile = join(paths.agentsDir, "sub-agents", `${subAgentId}.ts`);
207
+ const subAgentContent = generateSubAgentFile(subAgentId, subAgentData, style, registry, agentId, contextConfigData, agentData.models || project.models);
208
+ ensureDir(subAgentFile);
209
+ writeFileSync(subAgentFile, subAgentContent, "utf-8");
210
+ generatedFiles.push(subAgentFile);
211
+ }
212
+ }
213
+ }
214
+ }
215
+ if (project.agents) for (const [agentId, agentData] of Object.entries(project.agents)) {
216
+ if (!completeAgentIds.has(agentId)) continue;
217
+ const agentFile = join(paths.agentsDir, `${agentId}.ts`);
218
+ const agentContent = generateAgentFile(agentId, agentData, style, registry, agentData.contextConfig?.id ? findContextConfigData(project, agentData.contextConfig.id) : void 0, project.models);
219
+ ensureDir(agentFile);
220
+ writeFileSync(agentFile, agentContent, "utf-8");
221
+ generatedFiles.push(agentFile);
222
+ }
223
+ const projectDataForGenerator = {
224
+ ...project,
225
+ agents: project.agents ? Object.keys(project.agents).filter((id) => completeAgentIds.has(id)) : [],
226
+ tools: project.tools ? Object.keys(project.tools) : [],
227
+ externalAgents: project.externalAgents ? Object.keys(project.externalAgents) : [],
228
+ dataComponents: project.dataComponents ? Object.keys(project.dataComponents) : [],
229
+ artifactComponents: project.artifactComponents ? Object.keys(project.artifactComponents) : [],
230
+ credentialReferences: project.credentialReferences ? Object.keys(project.credentialReferences) : []
231
+ };
232
+ const projectFile = join(paths.projectRoot, "index.ts");
233
+ const projectContent = generateProjectFile(project.id, projectDataForGenerator, style, registry);
234
+ ensureDir(projectFile);
235
+ writeFileSync(projectFile, projectContent, "utf-8");
236
+ generatedFiles.push(projectFile);
237
+ if (debug) console.log(chalk.green(`✅ Generated ${generatedFiles.length} files`));
238
+ if (skippedAgents.length > 0) {
239
+ console.log(chalk.yellow(`\n⚠️ Skipped ${skippedAgents.length} incomplete agent(s):`));
240
+ for (const { id, reason } of skippedAgents) console.log(chalk.yellow(` • ${id}: ${reason}`));
241
+ console.log(chalk.gray(" To fix: Add at least one sub-agent to each agent in the UI and set it as default."));
242
+ }
243
+ } catch (error) {
244
+ console.error(chalk.red("\n❌ Introspect regeneration failed:"));
245
+ console.error(chalk.red(` Error: ${error instanceof Error ? error.message : "Unknown error"}`));
246
+ throw error;
247
+ }
248
+ }
249
+ /**
250
+ * Find context config data by agent-based ID from project agents
251
+ */
252
+ function findContextConfigData(project, contextId) {
253
+ if (project.agents) {
254
+ for (const [agentId, agentData] of Object.entries(project.agents)) if (agentData.contextConfig) {
255
+ if (agentData.contextConfig.id === contextId) return agentData.contextConfig;
256
+ }
257
+ }
258
+ }
259
+ /**
260
+ * Find status component data by ID from project agents
261
+ */
262
+ function findStatusComponentData(project, statusId) {
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) {
265
+ let compId;
266
+ if (typeof statusComp === "string") compId = statusComp;
267
+ else if (typeof statusComp === "object" && statusComp) compId = statusComp.type;
268
+ if (compId === statusId) return typeof statusComp === "string" ? {
269
+ id: statusId,
270
+ type: statusId,
271
+ description: `Status component for ${statusId}`
272
+ } : statusComp;
273
+ }
274
+ }
275
+ }
276
+
277
+ //#endregion
278
+ export { introspectGenerate };
@@ -0,0 +1,192 @@
1
+ import { createTargetedTypeScriptPlaceholders, restoreTargetedTypeScriptPlaceholders } from "./targeted-typescript-placeholders.js";
2
+ import { getAvailableModel } from "./utils/model-provider-detector.js";
3
+ import chalk from "chalk";
4
+ import { generateText } from "ai";
5
+
6
+ //#region src/commands/pull-v3/llm-content-merger.ts
7
+ /**
8
+ * LLM Content Merger - Intelligently merge old and new component content
9
+ *
10
+ * Uses an LLM to selectively update modified components while preserving:
11
+ * - Original file structure and formatting
12
+ * - Code style consistency
13
+ * - Better zod schemas
14
+ * - Imports and other non-component code
15
+ */
16
+ /**
17
+ * Strip code fences from LLM response if present
18
+ */
19
+ function stripCodeFences(content) {
20
+ content = content.replace(/^```(?:typescript|ts|javascript|js)?\s*\n?/i, "");
21
+ content = content.replace(/\n?```\s*$/i, "");
22
+ return content;
23
+ }
24
+ /**
25
+ * Estimate tokens in text (rough approximation: 1 token ≈ 4 characters)
26
+ */
27
+ function estimateTokens(text) {
28
+ return Math.ceil(text.length / 4);
29
+ }
30
+ function calculateCostEstimate(promptTokens, completionTokens) {
31
+ return promptTokens / 1e6 * 3 + completionTokens / 1e6 * 15;
32
+ }
33
+ /**
34
+ * Use LLM to intelligently merge old content with new component definitions
35
+ */
36
+ async function mergeComponentsWithLLM(request) {
37
+ const { oldContent, newContent, modifiedComponents, filePath, newComponents, componentsToExport } = request;
38
+ const componentList = modifiedComponents.map((c) => `- ${c.componentType}:${c.componentId}`).join("\n");
39
+ const newComponentsList = newComponents && newComponents.length > 0 ? newComponents.map((c) => {
40
+ const currentDir = filePath.replace(/^.*\/([^/]+\/[^/]+)$/, "$1").replace(/\/[^/]+$/, "");
41
+ let componentPath = c.filePath;
42
+ if (componentPath.includes(".temp-")) componentPath = componentPath.replace(/^.*\.temp-[^/]+\//, "");
43
+ componentPath = componentPath.replace(/\.ts$/, "");
44
+ const importPath = calculateRelativeImportPath(currentDir, componentPath);
45
+ const variableName = c.componentId.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
46
+ return `- ${c.componentType}:${c.componentId} (import as: import { ${variableName} } from '${importPath}')`;
47
+ }).join("\n") : "";
48
+ function calculateRelativeImportPath(fromDir, toPath) {
49
+ const fromParts = fromDir.split("/");
50
+ const toParts = toPath.split("/");
51
+ let commonLength = 0;
52
+ while (commonLength < fromParts.length && commonLength < toParts.length - 1 && fromParts[commonLength] === toParts[commonLength]) commonLength++;
53
+ const upLevels = fromParts.length - commonLength;
54
+ let relativePath = "";
55
+ for (let i = 0; i < upLevels; i++) relativePath += "../";
56
+ relativePath += toParts.slice(commonLength).join("/");
57
+ return relativePath.startsWith("../") ? relativePath : "./" + relativePath;
58
+ }
59
+ const componentsToExportList = componentsToExport && componentsToExport.length > 0 ? componentsToExport.map((c) => `- ${c.variableName} (${c.reason})`).join("\n") : "";
60
+ const prompt = `You are a TypeScript code expert tasked with intelligently merging component updates.
61
+
62
+ ## Task
63
+ Merge the OLD file content with NEW component definitions, preserving the original file structure while updating only the modified components.
64
+
65
+ ## Modified Components to Update
66
+ ${componentList}
67
+ ${newComponentsList ? `
68
+ ## New Components Available (can be imported)
69
+ ${newComponentsList}
70
+ ` : ""}${componentsToExportList ? `
71
+ ## Components That Need To Be Exported
72
+ The following existing components are referenced by new components and must be exported:
73
+ ${componentsToExportList}
74
+
75
+ Ensure these components have export statements (convert \`const\` to \`export const\`, or add \`export\` to existing declarations).
76
+ ` : ""}
77
+ ## Instructions
78
+ 0. **Please ensure you focus changes to minimize git diff size.** We want a clean git history.
79
+ 1. **Preserve original structure**: Keep imports, exports, comments, and overall file organization
80
+ 2. **Update only modified components**: Replace the specified components with their new versions
81
+ 3. **Maintain code style**: Match the original formatting, indentation, and style
82
+ 4. **Improve schemas**: Use better zod schemas from the new content where applicable. E.g. if the new content uses something like z.union([z.null(), z.string()]), use z.string().nullable() instead.
83
+ 5. **Keep variable names**: Preserve original variable names and declarations
84
+ 6. **Preserve non-component code**: Keep any non-component logic, comments, or utilities
85
+ 7. **Smart import handling**:
86
+ - Please leave all imports at the top of the file. Don't use .js imports, use .ts imports instead. (import example from './example')
87
+ - Preserve all imports from the original content that are not modified, if a component is modified or no longer exists, remove the import.
88
+ - For NEW components listed above, add proper import statements
89
+ - For components that exist in the same file (modified components), DO NOT add import statements
90
+ - Remove any incorrect imports from the NEW component definitions that reference same-file components
91
+ - Use relative paths for imports (e.g., './example' not './example.js')
92
+ 8. **Format JavaScript functions for maximum readability**:
93
+ - When you see compressed/minified function code like \`async({params})=>{...code...}\`, expand and prettify it
94
+ - Add proper line breaks, spacing, and indentation to make the function readable
95
+ - Ensure all braces \`{}\`, parentheses \`()\`, and syntax are properly balanced and valid
96
+ - Format the function code following TypeScript/JavaScript best practices
97
+ - Make sure the final code is compilable and syntactically correct
98
+ - Example: \`async({a,b})=>{return a+b}\` should become:
99
+ \`\`\`
100
+ async ({ a, b }) => {
101
+ return a + b;
102
+ }
103
+ \`\`\`
104
+
105
+ ## OLD File to be updated with new component definitions:
106
+ \`\`\`typescript
107
+ ${oldContent}
108
+ \`\`\`
109
+
110
+ ## NEW Component Definitions to replace/add to the old file:
111
+ \`\`\`typescript
112
+ ${newContent}
113
+ \`\`\`
114
+
115
+ ## Output
116
+ Provide the merged TypeScript file that:
117
+ - Keeps the original file structure
118
+ - Updates ONLY the modified components listed above
119
+ - Maintains consistent code style
120
+ - Uses improved schemas where beneficial
121
+ - Preserves all imports, exports, and other code that are necessary to keep the file working.
122
+ - **Formats all function code beautifully with proper spacing, line breaks, and indentation**
123
+ - **Ensures all syntax is valid and compilable TypeScript/JavaScript**
124
+ - Start the code immidiately with the first line of the file, skip any backticks or other formatting announcing that it is a code block or typescript file.
125
+ - Please follow biomes.dev code style.
126
+ - Please remember the NEW component definitions are to replace/add to the old file.
127
+
128
+ Return only the merged TypeScript code without any explanation or markdown formatting.`;
129
+ try {
130
+ const oldPlaceholders = createTargetedTypeScriptPlaceholders(oldContent);
131
+ const newPlaceholders = createTargetedTypeScriptPlaceholders(newContent);
132
+ const processedPrompt = prompt.replace(oldContent, oldPlaceholders.processedContent).replace(newContent, newPlaceholders.processedContent);
133
+ const estimatedPromptTokens = estimateTokens(processedPrompt);
134
+ let mergedContent = (await generateText({
135
+ model: getAvailableModel(),
136
+ prompt: processedPrompt
137
+ })).text.trim();
138
+ mergedContent = stripCodeFences(mergedContent);
139
+ const estimatedCompletionTokens = estimateTokens(mergedContent);
140
+ const totalTokens = estimatedPromptTokens + estimatedCompletionTokens;
141
+ const estimatedCost = calculateCostEstimate(estimatedPromptTokens, estimatedCompletionTokens);
142
+ console.log(chalk.gray(` 💰 LLM usage: ~${totalTokens.toLocaleString()} tokens ($${estimatedCost.toFixed(4)})`));
143
+ const allReplacements = {
144
+ ...oldPlaceholders.replacements,
145
+ ...newPlaceholders.replacements
146
+ };
147
+ if (Object.keys(allReplacements).length > 0) mergedContent = restoreTargetedTypeScriptPlaceholders(mergedContent, allReplacements);
148
+ const changes = modifiedComponents.map((c) => `Updated ${c.componentType}:${c.componentId}`);
149
+ return {
150
+ mergedContent,
151
+ changes,
152
+ success: true,
153
+ usage: {
154
+ promptTokens: estimatedPromptTokens,
155
+ completionTokens: estimatedCompletionTokens,
156
+ totalTokens,
157
+ estimatedCost
158
+ }
159
+ };
160
+ } catch (error) {
161
+ return {
162
+ mergedContent: oldContent,
163
+ changes: [],
164
+ success: false,
165
+ error: error instanceof Error ? error.message : String(error)
166
+ };
167
+ }
168
+ }
169
+ /**
170
+ * Preview the merge result by showing a diff-like summary
171
+ */
172
+ function previewMergeResult(oldContent, mergedContent, changes) {
173
+ console.log(chalk.cyan("\n🔍 Merge Preview:"));
174
+ console.log(chalk.gray(` Old content: ${oldContent.length} characters`));
175
+ console.log(chalk.gray(` New content: ${mergedContent.length} characters`));
176
+ console.log(chalk.yellow(` Changes applied:`));
177
+ changes.forEach((change) => {
178
+ console.log(chalk.gray(` • ${change}`));
179
+ });
180
+ const lines = mergedContent.split("\n");
181
+ const preview = lines.slice(0, 10).join("\n");
182
+ console.log(chalk.cyan("\n📄 Merged content preview (first 10 lines):"));
183
+ console.log(chalk.gray(" ┌─────"));
184
+ preview.split("\n").forEach((line, i) => {
185
+ console.log(chalk.gray(` │ ${String(i + 1).padStart(2, " ")}: ${line}`));
186
+ });
187
+ if (lines.length > 10) console.log(chalk.gray(` │ ... (${lines.length - 10} more lines)`));
188
+ console.log(chalk.gray(" └─────"));
189
+ }
190
+
191
+ //#endregion
192
+ export { mergeComponentsWithLLM, previewMergeResult };
@@ -1,5 +1,16 @@
1
- #!/usr/bin/env node
2
- import { C as generateCredentialFile, D as toCamelCase, E as generateAgentFile, S as generateDataComponentFile, T as generateArtifactComponentFile, c as findSubAgentWithParent, f as generateMcpToolFile, h as generateEnvironmentFile, l as generateSubAgentFile, m as generateExternalAgentFile, p as generateFunctionToolFile, u as generateStatusComponentFile, w as generateContextConfigFile } from "./index.js";
1
+ import { toCamelCase } from "./utils/generator-utils.js";
2
+ import { generateAgentFile } from "./components/agent-generator.js";
3
+ import { generateArtifactComponentFile } from "./components/artifact-component-generator.js";
4
+ import { generateContextConfigFile } from "./components/context-config-generator.js";
5
+ import { generateCredentialFile } from "./components/credential-generator.js";
6
+ import { generateDataComponentFile } from "./components/data-component-generator.js";
7
+ import { generateEnvironmentFile } from "./components/environment-generator.js";
8
+ import { generateExternalAgentFile } from "./components/external-agent-generator.js";
9
+ import { generateFunctionToolFile } from "./components/function-tool-generator.js";
10
+ import { generateMcpToolFile } from "./components/mcp-tool-generator.js";
11
+ import { generateStatusComponentFile } from "./components/status-component-generator.js";
12
+ import { generateSubAgentFile } from "./components/sub-agent-generator.js";
13
+ import { findSubAgentWithParent } from "./utils/component-registry.js";
3
14
  import { existsSync, mkdirSync, writeFileSync } from "node:fs";
4
15
  import { dirname, join } from "node:path";
5
16
  import chalk from "chalk";
@@ -218,7 +229,7 @@ async function createNewComponents(comparison, remoteProject, localRegistry, pat
218
229
  const createdEnvironments = results.filter((r) => r.success && r.componentType === "environments");
219
230
  if (createdEnvironments.length > 0) try {
220
231
  console.log(chalk.cyan("📝 Generating environments index file..."));
221
- const { generateEnvironmentIndexFile } = await import("./environment-generator.js");
232
+ const { generateEnvironmentIndexFile } = await import("./components/environment-generator.js");
222
233
  const indexContent = generateEnvironmentIndexFile(createdEnvironments.map((r) => r.componentId), {
223
234
  quotes: "single",
224
235
  indentation: " ",