@inkeep/agents-cli 0.52.0 → 0.53.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 (28) hide show
  1. package/dist/agents-cli/package.js +1 -1
  2. package/dist/commands/{pull-v3 → pull-v4}/component-parser.js +3 -3
  3. package/dist/commands/{pull-v3/utils → pull-v4}/component-registry.js +1 -1
  4. package/dist/commands/pull-v4/{agent-generator.js → generators/agent-generator.js} +2 -18
  5. package/dist/commands/pull-v4/{artifact-component-generator.js → generators/artifact-component-generator.js} +2 -2
  6. package/dist/commands/pull-v4/{context-config-generator.js → generators/context-config-generator.js} +2 -2
  7. package/dist/commands/pull-v4/{credential-generator.js → generators/credential-generator.js} +2 -2
  8. package/dist/commands/pull-v4/{data-component-generator.js → generators/data-component-generator.js} +2 -2
  9. package/dist/commands/pull-v4/{environment-generator.js → generators/environment-generator.js} +2 -2
  10. package/dist/commands/pull-v4/{external-agent-generator.js → generators/external-agent-generator.js} +2 -2
  11. package/dist/commands/pull-v4/{function-tool-generator.js → generators/function-tool-generator.js} +2 -2
  12. package/dist/commands/pull-v4/{mcp-tool-generator.js → generators/mcp-tool-generator.js} +5 -5
  13. package/dist/commands/pull-v4/{project-generator.js → generators/project-generator.js} +48 -24
  14. package/dist/commands/{pull-v3/components → pull-v4/generators}/skill-generator.js +1 -1
  15. package/dist/commands/pull-v4/{status-component-generator.js → generators/status-component-generator.js} +2 -2
  16. package/dist/commands/pull-v4/{sub-agent-generator.js → generators/sub-agent-generator.js} +103 -2
  17. package/dist/commands/pull-v4/{trigger-generator.js → generators/trigger-generator.js} +2 -2
  18. package/dist/commands/pull-v4/introspect/index.js +3 -3
  19. package/dist/commands/pull-v4/introspect/test-helpers.js +1 -1
  20. package/dist/commands/pull-v4/introspect-generator.js +26 -11
  21. package/dist/commands/pull-v4/module-merge.js +33 -7
  22. package/dist/commands/pull-v4/utils.js +17 -1
  23. package/package.json +3 -6
  24. package/dist/commands/pull-v3/project-comparator.js +0 -914
  25. package/dist/commands/pull-v3/targeted-typescript-placeholders.js +0 -173
  26. package/dist/commands/pull-v3/utils/component-tracker.js +0 -165
  27. package/dist/commands/pull-v3/utils/generator-utils.js +0 -146
  28. package/dist/commands/pull-v3/utils/model-provider-detector.js +0 -50
@@ -1,173 +0,0 @@
1
- import { Node, Project } from "ts-morph";
2
- import { randomBytes } from "node:crypto";
3
-
4
- //#region src/commands/pull-v3/targeted-typescript-placeholders.ts
5
- /**
6
- * Targeted TypeScript Placeholder System
7
- *
8
- * Uses AST parsing to intelligently identify large content blocks for replacement:
9
- * - prompt: (template literals or strings)
10
- * - description: (string literals)
11
- * - inputSchema: (object literals)
12
- * - detailsSchema: (object literals)
13
- * - props: (object literals in artifact/data components)
14
- */
15
- /**
16
- * Generate a unique placeholder ID
17
- */
18
- function generatePlaceholderId() {
19
- return randomBytes(4).toString("hex").toUpperCase();
20
- }
21
- /**
22
- * Minimum length threshold for replacement (only replace if longer than this)
23
- */
24
- const MIN_REPLACEMENT_LENGTH = 10;
25
- /**
26
- * Create targeted placeholders using AST parsing for better accuracy
27
- */
28
- function createTargetedTypeScriptPlaceholders(content) {
29
- const replacements = {};
30
- let replacedFields = 0;
31
- const originalSize = content.length;
32
- try {
33
- const sourceFile = new Project({ useInMemoryFileSystem: true }).createSourceFile("temp.ts", content);
34
- const replacementOperations = [];
35
- sourceFile.forEachDescendant((node) => {
36
- if (Node.isPropertyAssignment(node)) {
37
- const propertyName = node.getName();
38
- const valueNode = node.getInitializer();
39
- if (!valueNode) return;
40
- let valueText = valueNode.getText();
41
- if (valueText.trim().length < MIN_REPLACEMENT_LENGTH) return;
42
- let placeholderPrefix = "";
43
- switch (propertyName) {
44
- case "prompt":
45
- placeholderPrefix = "PROMPT";
46
- break;
47
- case "description":
48
- placeholderPrefix = "DESC";
49
- break;
50
- case "inputSchema":
51
- placeholderPrefix = "INPUT_SCHEMA";
52
- break;
53
- case "detailsSchema":
54
- placeholderPrefix = "DETAILS_SCHEMA";
55
- break;
56
- case "props":
57
- placeholderPrefix = "PROPS";
58
- break;
59
- case "render":
60
- placeholderPrefix = "RENDER";
61
- break;
62
- default: return;
63
- }
64
- const start = valueNode.getStart();
65
- let end = valueNode.getEnd();
66
- const propertyEnd = node.getEnd();
67
- if (propertyName === "inputSchema" || propertyName === "render") {
68
- const searchStart = start;
69
- let braceCount = 0;
70
- let correctEnd = -1;
71
- let inString = false;
72
- let stringChar = "";
73
- for (let i = searchStart; i < content.length; i++) {
74
- const char = content[i];
75
- const prevChar = i > 0 ? content[i - 1] : "";
76
- if ((char === "\"" || char === "'") && prevChar !== "\\") {
77
- if (!inString) {
78
- inString = true;
79
- stringChar = char;
80
- } else if (char === stringChar) {
81
- inString = false;
82
- stringChar = "";
83
- }
84
- }
85
- if (!inString) {
86
- if (char === "{") braceCount++;
87
- else if (char === "}") {
88
- braceCount--;
89
- if (braceCount === 0) {
90
- let j = i + 1;
91
- while (j < content.length && /\s/.test(content[j])) j++;
92
- if (j < content.length && content[j] === ",") {
93
- correctEnd = j + 1;
94
- break;
95
- }
96
- }
97
- }
98
- }
99
- }
100
- if (correctEnd > start && correctEnd < end + 100) {
101
- end = correctEnd;
102
- valueText = content.slice(start, end);
103
- }
104
- } else if (!content.slice(end, end + 20).match(/^\s*[,}]/)) {
105
- let correctEnd = end;
106
- while (correctEnd > start && !content.slice(correctEnd, correctEnd + 10).match(/^\s*[,}]/)) correctEnd--;
107
- if (correctEnd > start) {
108
- end = correctEnd;
109
- valueText = content.slice(start, end);
110
- } else return;
111
- }
112
- if (end > propertyEnd) return;
113
- const actualText = content.slice(start, end);
114
- if (valueText !== actualText) return;
115
- if (!content.slice(end, end + 20).match(/^\s*[,}]/)) return;
116
- const placeholder = `<${placeholderPrefix}_${generatePlaceholderId()}>`;
117
- replacements[placeholder] = valueText;
118
- replacedFields++;
119
- replacementOperations.push({
120
- start,
121
- end,
122
- placeholder,
123
- originalText: valueText
124
- });
125
- }
126
- });
127
- replacementOperations.sort((a, b) => b.start - a.start);
128
- let processedContent = content;
129
- for (const op of replacementOperations) processedContent = processedContent.slice(0, op.start) + op.placeholder + processedContent.slice(op.end);
130
- const processedSize = processedContent.length;
131
- const savings = originalSize - processedSize;
132
- const savingsPercentage = originalSize > 0 ? savings / originalSize * 100 : 0;
133
- return {
134
- processedContent,
135
- replacements,
136
- stats: {
137
- originalSize,
138
- processedSize,
139
- savings,
140
- savingsPercentage,
141
- replacedFields
142
- }
143
- };
144
- } catch {
145
- return {
146
- processedContent: content,
147
- replacements: {},
148
- stats: {
149
- originalSize,
150
- processedSize: originalSize,
151
- savings: 0,
152
- savingsPercentage: 0,
153
- replacedFields: 0
154
- }
155
- };
156
- }
157
- }
158
- /**
159
- * Restore placeholders in TypeScript content
160
- */
161
- function restoreTargetedTypeScriptPlaceholders(content, replacements) {
162
- let restoredContent = content;
163
- const sortedPlaceholders = Object.keys(replacements).sort((a, b) => b.length - a.length);
164
- for (const placeholder of sortedPlaceholders) {
165
- const originalValue = replacements[placeholder];
166
- if (!restoredContent.includes(placeholder)) continue;
167
- restoredContent = restoredContent.replace(placeholder, originalValue);
168
- }
169
- return restoredContent;
170
- }
171
-
172
- //#endregion
173
- export { createTargetedTypeScriptPlaceholders, restoreTargetedTypeScriptPlaceholders };
@@ -1,165 +0,0 @@
1
- //#region src/commands/pull-v3/utils/component-tracker.ts
2
- var ComponentTracker = class {
3
- components = /* @__PURE__ */ new Map();
4
- usedNames = /* @__PURE__ */ new Set();
5
- /**
6
- * Register a component in the tracker
7
- */
8
- register(info) {
9
- const uniqueName = this.ensureUniqueName(info.name, info.type);
10
- const uniqueExportName = this.ensureUniqueName(info.exportName, info.type);
11
- const updatedInfo = {
12
- ...info,
13
- name: uniqueName,
14
- exportName: uniqueExportName
15
- };
16
- this.components.set(info.id, updatedInfo);
17
- this.usedNames.add(uniqueName);
18
- this.usedNames.add(uniqueExportName);
19
- }
20
- /**
21
- * Ensure a variable name is unique across the project
22
- */
23
- ensureUniqueName(baseName, type) {
24
- let uniqueName = baseName;
25
- let counter = 1;
26
- while (this.usedNames.has(uniqueName)) {
27
- if (counter === 1) uniqueName = `${this.getTypePrefix(type)}${baseName.charAt(0).toUpperCase() + baseName.slice(1)}`;
28
- else uniqueName = `${baseName}${counter}`;
29
- counter++;
30
- if (counter > 100) {
31
- uniqueName = `${baseName}_${Date.now()}`;
32
- break;
33
- }
34
- }
35
- return uniqueName;
36
- }
37
- /**
38
- * Get type prefix for uniqueness resolution
39
- */
40
- getTypePrefix(type) {
41
- switch (type) {
42
- case "agent": return "agent";
43
- case "subAgent": return "sub";
44
- case "externalAgent": return "ext";
45
- case "tool": return "tool";
46
- case "functionTool": return "func";
47
- case "dataComponent": return "data";
48
- case "artifactComponent": return "artifact";
49
- case "credential": return "cred";
50
- case "statusComponent": return "status";
51
- case "contextConfig": return "context";
52
- default: return "comp";
53
- }
54
- }
55
- /**
56
- * Get component info by ID
57
- */
58
- get(id) {
59
- return this.components.get(id);
60
- }
61
- /**
62
- * Check if component exists
63
- */
64
- has(id) {
65
- return this.components.has(id);
66
- }
67
- /**
68
- * Get all components of a specific type
69
- */
70
- getByType(type) {
71
- return Array.from(this.components.values()).filter((c) => c.type === type);
72
- }
73
- /**
74
- * Extract IDs from mixed array (objects with id property or strings)
75
- */
76
- extractIds(references) {
77
- if (!Array.isArray(references)) return [];
78
- return references.map((ref) => {
79
- if (typeof ref === "string") return ref;
80
- if (typeof ref === "object" && ref) {
81
- if (ref.id) return ref.id;
82
- if (ref.type) return ref.type;
83
- if (ref.name) return ref.name;
84
- console.warn("ComponentTracker: Skipping reference without clear ID:", ref);
85
- return null;
86
- }
87
- return null;
88
- }).filter(Boolean);
89
- }
90
- /**
91
- * Resolve references to import statements and variable names
92
- */
93
- resolveReferences(references, currentFilePath) {
94
- const ids = this.extractIds(references);
95
- const imports = [];
96
- const variableNames = [];
97
- for (const id of ids) {
98
- const component = this.get(id);
99
- if (component) {
100
- const importPath = this.getRelativeImportPath(currentFilePath, component.filePath);
101
- imports.push(`import { ${component.exportName} } from '${importPath}';`);
102
- variableNames.push(component.name);
103
- } else variableNames.push(id);
104
- }
105
- return {
106
- imports,
107
- variableNames
108
- };
109
- }
110
- /**
111
- * Generate formatted array of variable names for code generation
112
- */
113
- formatReferencesForCode(references, style, indentLevel) {
114
- const ids = this.extractIds(references);
115
- const variableNames = [];
116
- for (const id of ids) {
117
- const component = this.get(id);
118
- if (component) variableNames.push(component.name);
119
- else variableNames.push(id);
120
- }
121
- if (variableNames.length === 0) return "[]";
122
- const { indentation } = style;
123
- const indent = indentation.repeat(indentLevel);
124
- if (variableNames.length === 1) return `[${variableNames[0]}]`;
125
- const lines = ["["];
126
- for (const name of variableNames) lines.push(`${indent}${name},`);
127
- if (lines.length > 1 && lines[lines.length - 1].endsWith(",")) lines[lines.length - 1] = lines[lines.length - 1].slice(0, -1);
128
- lines.push(`${indentation.repeat(indentLevel - 1)}]`);
129
- return lines.join("\n");
130
- }
131
- /**
132
- * Calculate relative import path between files
133
- */
134
- getRelativeImportPath(fromPath, toPath) {
135
- const fromParts = fromPath.replace(".ts", "").split("/");
136
- const toParts = toPath.replace(".ts", "").split("/");
137
- fromParts.pop();
138
- let relativePath = "";
139
- for (let i = 0; i < fromParts.length; i++) relativePath += "../";
140
- relativePath += toParts.join("/");
141
- if (relativePath.startsWith("../")) return relativePath;
142
- return `./${relativePath}`;
143
- }
144
- /**
145
- * Get all components as a list
146
- */
147
- getAllComponents() {
148
- return Array.from(this.components.values());
149
- }
150
- /**
151
- * Clear all registered components
152
- */
153
- clear() {
154
- this.components.clear();
155
- }
156
- };
157
- /**
158
- * Convert kebab-case or snake_case to camelCase
159
- */
160
- function toCamelCase(str) {
161
- return str.toLowerCase().replace(/[-_](.)/g, (_, char) => char.toUpperCase()).replace(/[^a-zA-Z0-9]/g, "").replace(/^[0-9]/, "_$&");
162
- }
163
-
164
- //#endregion
165
- export { ComponentTracker, toCamelCase };
@@ -1,146 +0,0 @@
1
- //#region src/commands/pull-v3/utils/generator-utils.ts
2
- const DEFAULT_STYLE = {
3
- quotes: "single",
4
- semicolons: true,
5
- indentation: " "
6
- };
7
- /**
8
- * Convert kebab-case or snake_case to camelCase for variable names
9
- */
10
- function toCamelCase(str) {
11
- const result = str.replace(/[-_](.)/g, (_, char) => char.toUpperCase()).replace(/[^a-zA-Z0-9]/g, "").replace(/^[0-9]/, "_$&");
12
- return result.charAt(0).toLowerCase() + result.slice(1);
13
- }
14
- /**
15
- * Format a string value with proper quoting and multiline handling
16
- */
17
- function formatString(str, quote = "'", multiline = false) {
18
- if (!str && str !== "") return `${quote}${quote}`;
19
- if (multiline && (str.includes("\n") || str.length > 80)) return `\`${str.replace(/`/g, "\\`")}\``;
20
- return `${quote}${str.replace(new RegExp(quote, "g"), `\\${quote}`)}${quote}`;
21
- }
22
- /**
23
- * Check if a string contains template variables like {{user.name}}
24
- */
25
- function hasTemplateVariables(str) {
26
- return /\{\{[^}]+\}\}/.test(str);
27
- }
28
- /**
29
- * Determine if a variable path exists in headers schema
30
- */
31
- function isHeadersVariable(variablePath, contextConfigData) {
32
- if (!contextConfigData?.headersSchema?.schema) return false;
33
- const schemaStr = JSON.stringify(contextConfigData.headersSchema.schema);
34
- return schemaStr.includes(`"${variablePath}"`) || schemaStr.includes(variablePath.split(".")[0]);
35
- }
36
- /**
37
- * Determine if a variable path exists in context variables
38
- */
39
- function isContextVariable(variablePath, contextConfigData) {
40
- if (!contextConfigData?.contextVariables) return false;
41
- const topLevelVar = variablePath.split(".")[0];
42
- return Object.keys(contextConfigData.contextVariables).includes(topLevelVar);
43
- }
44
- /**
45
- * Format prompt strings with appropriate context.toTemplate() or headers.toTemplate() based on actual schema structure
46
- */
47
- function formatPromptWithContext(str, contextVarName, headersVarName, contextConfigData, quote = "'", multiline = false) {
48
- if (!str && str !== "") return `${quote}${quote}`;
49
- if (hasTemplateVariables(str)) return `\`${str.replace(/\{\{([^}]+)\}\}/g, (_match, variablePath) => {
50
- if (isContextVariable(variablePath, contextConfigData)) return `\${${contextVarName}.toTemplate("${variablePath}")}`;
51
- if (isHeadersVariable(variablePath, contextConfigData)) return `\${${headersVarName}.toTemplate("${variablePath}")}`;
52
- return `\${${contextVarName}.toTemplate("${variablePath}")}`;
53
- }).replace(/`/g, "\\`")}\``;
54
- return formatString(str, quote, multiline);
55
- }
56
- /**
57
- * Format prompt strings with headers.toTemplate() only (for backwards compatibility)
58
- */
59
- function formatPromptWithHeaders(str, headersVarName, quote = "'", multiline = false) {
60
- if (!str && str !== "") return `${quote}${quote}`;
61
- if (hasTemplateVariables(str)) return `\`${str.replace(/\{\{([^}]+)\}\}/g, `\${${headersVarName}.toTemplate("$1")}`).replace(/`/g, "\\`")}\``;
62
- return formatString(str, quote, multiline);
63
- }
64
- /**
65
- * Format array of references (tools, agents, components) with proper indentation
66
- */
67
- function formatReferencesArray(references, style, indentLevel) {
68
- let refArray;
69
- if (Array.isArray(references)) refArray = references.map((item) => {
70
- if (typeof item === "string") return toCamelCase(item);
71
- if (typeof item === "object" && item && item.id) return toCamelCase(item.id);
72
- return toCamelCase(String(item));
73
- });
74
- else if (references && typeof references === "object") refArray = Object.keys(references).map((key) => toCamelCase(key));
75
- else return "[]";
76
- if (!refArray || refArray.length === 0) return "[]";
77
- const { indentation } = style;
78
- const indent = indentation.repeat(indentLevel);
79
- if (refArray.length === 1) return `[${refArray[0]}]`;
80
- const lines = ["["];
81
- for (const ref of refArray) lines.push(`${indent}${ref},`);
82
- if (lines.length > 1 && lines[lines.length - 1].endsWith(",")) lines[lines.length - 1] = lines[lines.length - 1].slice(0, -1);
83
- lines.push(`${indentation.repeat(indentLevel - 1)}]`);
84
- return lines.join("\n");
85
- }
86
- /**
87
- * Format object properties as JavaScript object literal
88
- */
89
- function formatObject(obj, style, indentLevel) {
90
- if (!obj || typeof obj !== "object") return "{}";
91
- const { quotes, indentation } = style;
92
- const q = quotes === "single" ? "'" : "\"";
93
- const indent = indentation.repeat(indentLevel);
94
- const lines = ["{"];
95
- for (const [key, value] of Object.entries(obj)) {
96
- if (value === null || value === void 0) continue;
97
- const formattedKey = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(key) ? key : formatString(key, q);
98
- if (typeof value === "string") lines.push(`${indent}${formattedKey}: ${formatString(value, q)},`);
99
- else if (typeof value === "object") lines.push(`${indent}${formattedKey}: ${formatObject(value, style, indentLevel + 1)},`);
100
- else lines.push(`${indent}${formattedKey}: ${JSON.stringify(value)},`);
101
- }
102
- if (lines.length > 1 && lines[lines.length - 1].endsWith(",")) lines[lines.length - 1] = lines[lines.length - 1].slice(0, -1);
103
- lines.push(`${indentation.repeat(indentLevel - 1)}}`);
104
- return lines.join("\n");
105
- }
106
- /**
107
- * Remove trailing comma from the last line in an array of lines
108
- */
109
- function removeTrailingComma(lines) {
110
- if (lines.length > 0 && lines[lines.length - 1].endsWith(",")) lines[lines.length - 1] = lines[lines.length - 1].slice(0, -1);
111
- }
112
- /**
113
- * Generate standard import statement with proper quoting and semicolons
114
- */
115
- function generateImport(imports, from, style) {
116
- const { quotes, semicolons } = style;
117
- const q = quotes === "single" ? "'" : "\"";
118
- const semi = semicolons ? ";" : "";
119
- if (imports.length === 1) return `import { ${imports[0]} } from ${q}${from}${q}${semi}`;
120
- return `import { ${imports.join(", ")} } from ${q}${from}${q}${semi}`;
121
- }
122
- /**
123
- * Check if a value is truthy and should be included in output
124
- */
125
- function shouldInclude(value) {
126
- if (value === null || value === void 0) return false;
127
- if (Array.isArray(value) && value.length === 0) return false;
128
- if (typeof value === "object" && Object.keys(value).length === 0) return false;
129
- return true;
130
- }
131
- /**
132
- * Generate complete file content with imports and definitions
133
- */
134
- function generateFileContent(imports, definitions) {
135
- const content = [];
136
- if (imports.length > 0) content.push(imports.join("\n"));
137
- if (definitions.length > 0) {
138
- if (content.length > 0) content.push("");
139
- content.push(definitions.join("\n\n"));
140
- }
141
- content.push("");
142
- return content.join("\n");
143
- }
144
-
145
- //#endregion
146
- export { DEFAULT_STYLE, formatObject, formatPromptWithContext, formatPromptWithHeaders, formatReferencesArray, formatString, generateFileContent, generateImport, hasTemplateVariables, removeTrailingComma, shouldInclude, toCamelCase };
@@ -1,50 +0,0 @@
1
- import { anthropic } from "@ai-sdk/anthropic";
2
- import { google } from "@ai-sdk/google";
3
- import { openai } from "@ai-sdk/openai";
4
-
5
- //#region src/commands/pull-v3/utils/model-provider-detector.ts
6
- /**
7
- * Model Provider Detector - Detect available API keys and select appropriate models
8
- */
9
- const PROVIDER_CONFIGS = [
10
- {
11
- name: "anthropic",
12
- envVars: ["ANTHROPIC_API_KEY"],
13
- model: "claude-sonnet-4-5"
14
- },
15
- {
16
- name: "openai",
17
- envVars: ["OPENAI_API_KEY"],
18
- model: "gpt-5.1"
19
- },
20
- {
21
- name: "google",
22
- envVars: ["GOOGLE_GENERATIVE_AI_API_KEY"],
23
- model: "gemini-2.5-flash"
24
- },
25
- {
26
- name: "azure",
27
- envVars: ["AZURE_API_KEY"],
28
- model: ""
29
- }
30
- ];
31
- /**
32
- * Get a model instance for LLM content merging
33
- * Returns first available provider or throws if none available
34
- */
35
- function getAvailableModel() {
36
- for (const config of PROVIDER_CONFIGS) if (config.envVars.some((envVar) => {
37
- const value = process.env[envVar];
38
- return value && value.trim() !== "";
39
- })) switch (config.name) {
40
- case "anthropic": return anthropic(config.model);
41
- case "openai": return openai(config.model);
42
- case "google": return google(config.model);
43
- case "azure": continue;
44
- default: throw new Error(`Unknown provider: ${config.name}`);
45
- }
46
- throw new Error("No API keys detected. Please set ANTHROPIC_API_KEY, OPENAI_API_KEY, GOOGLE_GENERATIVE_AI_API_KEY, or AZURE_API_KEY");
47
- }
48
-
49
- //#endregion
50
- export { getAvailableModel };