@inkeep/agents-cli 0.41.2 → 0.42.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.
- package/README.md +13 -20
- package/dist/api.js +8 -8
- package/dist/commands/init.js +19 -39
- package/dist/commands/list-agents.js +1 -1
- package/dist/commands/login.js +3 -3
- package/dist/commands/profile.js +7 -26
- package/dist/commands/pull-v3/component-parser.js +0 -2
- package/dist/commands/pull-v3/component-updater.js +122 -64
- package/dist/commands/pull-v3/components/agent-generator.js +17 -3
- package/dist/commands/pull-v3/components/artifact-component-generator.js +7 -7
- package/dist/commands/pull-v3/components/context-config-generator.js +6 -6
- package/dist/commands/pull-v3/components/credential-generator.js +4 -4
- package/dist/commands/pull-v3/components/data-component-generator.js +4 -4
- package/dist/commands/pull-v3/components/environment-generator.js +10 -7
- package/dist/commands/pull-v3/components/function-tool-generator.js +5 -7
- package/dist/commands/pull-v3/components/mcp-tool-generator.js +5 -5
- package/dist/commands/pull-v3/components/project-generator.js +4 -4
- package/dist/commands/pull-v3/components/status-component-generator.js +6 -6
- package/dist/commands/pull-v3/components/trigger-generator.js +114 -0
- package/dist/commands/pull-v3/index.js +25 -30
- package/dist/commands/pull-v3/introspect-generator.js +15 -7
- package/dist/commands/pull-v3/llm-content-merger.js +1 -1
- package/dist/commands/pull-v3/new-component-generator.js +5 -16
- package/dist/commands/pull-v3/project-comparator.js +49 -49
- package/dist/commands/pull-v3/project-validator.js +5 -4
- package/dist/commands/pull-v3/targeted-typescript-placeholders.js +2 -2
- package/dist/commands/pull-v3/utils/component-registry.js +9 -7
- package/dist/commands/pull-v3/utils/component-tracker.js +1 -1
- package/dist/commands/pull-v3/utils/generator-utils.js +2 -2
- package/dist/commands/push.js +9 -9
- package/dist/commands/status.js +4 -8
- package/dist/index.js +2 -2
- package/dist/utils/ci-environment.js +4 -6
- package/dist/utils/cli-pipeline.js +8 -12
- package/dist/utils/config.js +17 -25
- package/dist/utils/json-comparison.js +3 -3
- package/dist/utils/profile-config.js +4 -6
- package/dist/utils/profiles/profile-manager.js +1 -1
- package/dist/utils/profiles/types.js +6 -9
- package/dist/utils/templates.js +3 -5
- package/package.json +7 -6
|
@@ -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"),
|
|
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 {
|
|
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 {
|
|
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(
|
|
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(
|
|
118
|
+
const imports = generateEnvironmentSettingsImports(environmentData, style);
|
|
116
119
|
const definition = generateEnvironmentSettingsDefinition(environmentName, environmentData, style);
|
|
117
|
-
return imports.join("\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")
|
|
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"),
|
|
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(
|
|
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(
|
|
86
|
+
const imports = generateFunctionToolImports(style);
|
|
89
87
|
const definition = generateFunctionToolDefinition(toolId, toolData, style);
|
|
90
|
-
return imports.join("\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"),
|
|
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(
|
|
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(
|
|
80
|
+
const imports = generateMcpToolImports(toolData, style);
|
|
81
81
|
const definition = generateMcpToolDefinition(toolId, toolData, style, registry);
|
|
82
|
-
return imports.join("\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(
|
|
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
|
|
87
|
-
else if (registry
|
|
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(
|
|
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"),
|
|
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] +=
|
|
61
|
+
lines[lines.length - 1] += `\n${indentation}${line}`;
|
|
62
62
|
});
|
|
63
|
-
lines[lines.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(
|
|
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(
|
|
86
|
+
const imports = generateStatusComponentImports(componentData, style);
|
|
87
87
|
const definition = generateStatusComponentDefinition(componentId, componentData, style);
|
|
88
|
-
return imports.join("\n")
|
|
88
|
+
return `${imports.join("\n")}\n\n${definition}\n`;
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
//#endregion
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { DEFAULT_STYLE, formatString, generateFileContent, generateImport, toCamelCase } from "../utils/generator-utils.js";
|
|
2
|
+
|
|
3
|
+
//#region src/commands/pull-v3/components/trigger-generator.ts
|
|
4
|
+
/**
|
|
5
|
+
* Trigger Generator - Generate trigger definitions
|
|
6
|
+
*
|
|
7
|
+
* Generates triggers using the Trigger class from @inkeep/agents-sdk
|
|
8
|
+
* Triggers are webhooks that can invoke agent conversations
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Format authentication configuration
|
|
12
|
+
* New format uses headers array: { headers: [{ name, valueHash, valuePrefix }] }
|
|
13
|
+
* We generate code that uses environment variables for the secret values
|
|
14
|
+
*/
|
|
15
|
+
function formatAuthentication(auth, style, indentLevel) {
|
|
16
|
+
if (!auth) return "";
|
|
17
|
+
const { indentation, quotes } = style;
|
|
18
|
+
const q = quotes === "single" ? "'" : "\"";
|
|
19
|
+
const indent = indentation.repeat(indentLevel);
|
|
20
|
+
const innerIndent = indentation.repeat(indentLevel + 1);
|
|
21
|
+
const headerIndent = indentation.repeat(indentLevel + 2);
|
|
22
|
+
const lines = [];
|
|
23
|
+
if (auth.headers && Array.isArray(auth.headers) && auth.headers.length > 0) {
|
|
24
|
+
lines.push(`${indent}authentication: {`);
|
|
25
|
+
lines.push(`${innerIndent}headers: [`);
|
|
26
|
+
for (const header of auth.headers) {
|
|
27
|
+
const envVarName = `TRIGGER_AUTH_${header.name.toUpperCase().replace(/[^A-Z0-9]/g, "_")}`;
|
|
28
|
+
lines.push(`${headerIndent}{`);
|
|
29
|
+
lines.push(`${headerIndent}${indentation}name: ${q}${header.name}${q},`);
|
|
30
|
+
lines.push(`${headerIndent}${indentation}value: process.env.${envVarName} || ${q}${q},`);
|
|
31
|
+
lines.push(`${headerIndent}},`);
|
|
32
|
+
}
|
|
33
|
+
lines.push(`${innerIndent}],`);
|
|
34
|
+
lines.push(`${indent}},`);
|
|
35
|
+
}
|
|
36
|
+
return lines.join("\n");
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Format output transform configuration
|
|
40
|
+
*/
|
|
41
|
+
function formatOutputTransform(transform, style, indentLevel) {
|
|
42
|
+
if (!transform) return "";
|
|
43
|
+
const { indentation } = style;
|
|
44
|
+
const indent = indentation.repeat(indentLevel);
|
|
45
|
+
const innerIndent = indentation.repeat(indentLevel + 1);
|
|
46
|
+
const lines = [];
|
|
47
|
+
lines.push(`${indent}outputTransform: {`);
|
|
48
|
+
if (transform.jmespath) lines.push(`${innerIndent}jmespath: '${transform.jmespath}',`);
|
|
49
|
+
if (transform.objectTransformation) {
|
|
50
|
+
const formattedTransform = JSON.stringify(transform.objectTransformation, null, 2).split("\n").map((line, index) => {
|
|
51
|
+
if (index === 0) return `${innerIndent}objectTransformation: ${line}`;
|
|
52
|
+
return `${innerIndent}${line}`;
|
|
53
|
+
}).join("\n");
|
|
54
|
+
lines.push(`${formattedTransform},`);
|
|
55
|
+
}
|
|
56
|
+
if (lines.length > 1 && lines[lines.length - 1].endsWith(",")) lines[lines.length - 1] = lines[lines.length - 1].slice(0, -1);
|
|
57
|
+
lines.push(`${indent}},`);
|
|
58
|
+
return lines.join("\n");
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Generate Trigger Definition using Trigger class
|
|
62
|
+
*/
|
|
63
|
+
function generateTriggerDefinition(triggerId, triggerData, style = DEFAULT_STYLE) {
|
|
64
|
+
if (!triggerId || typeof triggerId !== "string") throw new Error("triggerId is required and must be a string");
|
|
65
|
+
if (!triggerData || typeof triggerData !== "object") throw new Error(`triggerData is required for trigger '${triggerId}'`);
|
|
66
|
+
const missingFields = ["name", "messageTemplate"].filter((field) => !triggerData[field] || triggerData[field] === null || triggerData[field] === void 0);
|
|
67
|
+
if (missingFields.length > 0) throw new Error(`Missing required fields for trigger '${triggerId}': ${missingFields.join(", ")}`);
|
|
68
|
+
const { quotes, semicolons, indentation } = style;
|
|
69
|
+
const q = quotes === "single" ? "'" : "\"";
|
|
70
|
+
const semi = semicolons ? ";" : "";
|
|
71
|
+
const triggerVarName = toCamelCase(triggerId);
|
|
72
|
+
const lines = [];
|
|
73
|
+
lines.push(`export const ${triggerVarName} = new Trigger({`);
|
|
74
|
+
lines.push(`${indentation}id: ${formatString(triggerId, q)},`);
|
|
75
|
+
lines.push(`${indentation}name: ${formatString(triggerData.name, q)},`);
|
|
76
|
+
if (triggerData.description) lines.push(`${indentation}description: ${formatString(triggerData.description, q, true)},`);
|
|
77
|
+
if (triggerData.enabled !== void 0 && triggerData.enabled !== null) lines.push(`${indentation}enabled: ${triggerData.enabled},`);
|
|
78
|
+
lines.push(`${indentation}messageTemplate: ${formatString(triggerData.messageTemplate, q, true)},`);
|
|
79
|
+
if (triggerData.inputSchema) {
|
|
80
|
+
const formattedSchema = JSON.stringify(triggerData.inputSchema, null, 2).split("\n").map((line, index) => {
|
|
81
|
+
if (index === 0) return `${indentation}inputSchema: ${line}`;
|
|
82
|
+
return `${indentation}${line}`;
|
|
83
|
+
}).join("\n");
|
|
84
|
+
lines.push(`${formattedSchema},`);
|
|
85
|
+
}
|
|
86
|
+
if (triggerData.outputTransform) {
|
|
87
|
+
const outputTransformFormatted = formatOutputTransform(triggerData.outputTransform, style, 1);
|
|
88
|
+
if (outputTransformFormatted) lines.push(outputTransformFormatted);
|
|
89
|
+
}
|
|
90
|
+
if (triggerData.authentication) {
|
|
91
|
+
const authFormatted = formatAuthentication(triggerData.authentication, style, 1);
|
|
92
|
+
if (authFormatted) lines.push(authFormatted);
|
|
93
|
+
}
|
|
94
|
+
if (lines.length > 0 && lines[lines.length - 1].endsWith(",")) lines[lines.length - 1] = lines[lines.length - 1].slice(0, -1);
|
|
95
|
+
lines.push(`})${semi}`);
|
|
96
|
+
return lines.join("\n");
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Generate imports needed for a trigger file
|
|
100
|
+
*/
|
|
101
|
+
function generateTriggerImports(style = DEFAULT_STYLE) {
|
|
102
|
+
const imports = [];
|
|
103
|
+
imports.push(generateImport(["Trigger"], "@inkeep/agents-sdk", style));
|
|
104
|
+
return imports;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Generate complete trigger file (imports + definition)
|
|
108
|
+
*/
|
|
109
|
+
function generateTriggerFile(triggerId, triggerData, style = DEFAULT_STYLE) {
|
|
110
|
+
return generateFileContent(generateTriggerImports(style), [generateTriggerDefinition(triggerId, triggerData, style)]);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
//#endregion
|
|
114
|
+
export { generateTriggerDefinition, generateTriggerFile, generateTriggerImports };
|
|
@@ -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 {
|
|
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
|
|
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
|
|
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
|
|
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
|
|
83
|
-
for (const
|
|
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
|
|
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
|
|
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,
|
|
124
|
+
const { config, isCI } = await initializeCommand({
|
|
129
125
|
configPath: options.config,
|
|
130
126
|
profileName: options.profile,
|
|
131
127
|
tag: options.tag,
|
|
@@ -192,7 +188,7 @@ async function pullV3Command(options) {
|
|
|
192
188
|
}
|
|
193
189
|
}
|
|
194
190
|
s.start(`Fetching project: ${projectId}`);
|
|
195
|
-
const remoteProject = await (await ManagementApiClient.create(config.
|
|
191
|
+
const remoteProject = await (await ManagementApiClient.create(config.agentsApiUrl, options.config, config.tenantId, projectId, isCI, config.agentsApiKey)).getFullProject(projectId);
|
|
196
192
|
if (options.debug && remoteProject.functions) {
|
|
197
193
|
console.log(chalk.gray(" 📋 Project-level functions from API:"), Object.keys(remoteProject.functions));
|
|
198
194
|
Object.entries(remoteProject.functions).forEach(([id, data]) => {
|
|
@@ -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
|
|
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
|
|
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
|
|
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
|
|
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)
|
|
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,
|
|
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(
|
|
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)
|
|
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.
|
|
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,
|
|
378
|
+
const { config, isCI } = await initializeCommand({
|
|
384
379
|
configPath: options.config,
|
|
385
380
|
profileName: options.profile,
|
|
386
381
|
tag: options.tag,
|
|
@@ -392,7 +387,7 @@ async function pullAllProjects(options) {
|
|
|
392
387
|
const s = p.spinner();
|
|
393
388
|
try {
|
|
394
389
|
s.start("Fetching project list from API...");
|
|
395
|
-
const projects = await (await ManagementApiClient.create(config.
|
|
390
|
+
const projects = await (await ManagementApiClient.create(config.agentsApiUrl, options.config, config.tenantId, void 0, isCI, config.agentsApiKey)).listAllProjects();
|
|
396
391
|
s.stop(`Found ${projects.length} project(s)`);
|
|
397
392
|
if (projects.length === 0) {
|
|
398
393
|
console.log(chalk.yellow("No projects found for this tenant."));
|
|
@@ -486,8 +481,8 @@ async function pullSingleProject(projectId, projectName, options, config, isCI)
|
|
|
486
481
|
if (originalLogLevel !== void 0) process.env.LOG_LEVEL = originalLogLevel;
|
|
487
482
|
else delete process.env.LOG_LEVEL;
|
|
488
483
|
};
|
|
489
|
-
const remoteProject = await (await ManagementApiClient.create(config.
|
|
490
|
-
await introspectGenerate(remoteProject, createProjectStructure(targetDir
|
|
484
|
+
const remoteProject = await (await ManagementApiClient.create(config.agentsApiUrl, options.config, config.tenantId, projectId, isCI, config.agentsApiKey)).getFullProject(projectId);
|
|
485
|
+
await introspectGenerate(remoteProject, createProjectStructure(targetDir), options.env || "development", false);
|
|
491
486
|
restoreLogLevel();
|
|
492
487
|
return {
|
|
493
488
|
projectId,
|
|
@@ -12,6 +12,7 @@ import { generateProjectFile } from "./components/project-generator.js";
|
|
|
12
12
|
import { generateStatusComponentFile } from "./components/status-component-generator.js";
|
|
13
13
|
import { generateSubAgentFile } from "./components/sub-agent-generator.js";
|
|
14
14
|
import { ComponentRegistry, registerAllComponents } from "./utils/component-registry.js";
|
|
15
|
+
import { generateTriggerFile } from "./components/trigger-generator.js";
|
|
15
16
|
import { mkdirSync, writeFileSync } from "node:fs";
|
|
16
17
|
import { dirname, join } from "node:path";
|
|
17
18
|
import chalk from "chalk";
|
|
@@ -33,7 +34,7 @@ function ensureDir(filePath) {
|
|
|
33
34
|
* Check if an agent is complete enough for code generation
|
|
34
35
|
* An agent needs a name, defaultSubAgentId, and at least one sub-agent
|
|
35
36
|
*/
|
|
36
|
-
function isAgentComplete(
|
|
37
|
+
function isAgentComplete(agentData) {
|
|
37
38
|
if (!agentData.name) return {
|
|
38
39
|
complete: false,
|
|
39
40
|
reason: "missing name"
|
|
@@ -102,7 +103,7 @@ async function introspectGenerate(project, paths, environment, debug, options =
|
|
|
102
103
|
generatedFiles.push(functionFile);
|
|
103
104
|
functionToolsGenerated.add(toolId);
|
|
104
105
|
}
|
|
105
|
-
if (project.agents) for (const
|
|
106
|
+
if (project.agents) for (const agentData of Object.values(project.agents)) {
|
|
106
107
|
const agentFunctionTools = agentData.functionTools;
|
|
107
108
|
const agentFunctions = agentData.functions;
|
|
108
109
|
if (agentFunctionTools) for (const [toolId, toolData] of Object.entries(agentFunctionTools)) {
|
|
@@ -126,7 +127,7 @@ async function introspectGenerate(project, paths, environment, debug, options =
|
|
|
126
127
|
}
|
|
127
128
|
}
|
|
128
129
|
if (project.functions) {
|
|
129
|
-
for (const
|
|
130
|
+
for (const funcId of Object.keys(project.functions)) if (!functionToolsGenerated.has(funcId)) {
|
|
130
131
|
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
|
}
|
|
132
133
|
}
|
|
@@ -182,7 +183,7 @@ async function introspectGenerate(project, paths, environment, debug, options =
|
|
|
182
183
|
}
|
|
183
184
|
const completeAgentIds = /* @__PURE__ */ new Set();
|
|
184
185
|
if (project.agents) for (const [agentId, agentData] of Object.entries(project.agents)) {
|
|
185
|
-
const completeness = isAgentComplete(
|
|
186
|
+
const completeness = isAgentComplete(agentData);
|
|
186
187
|
if (completeness.complete) completeAgentIds.add(agentId);
|
|
187
188
|
else {
|
|
188
189
|
skippedAgents.push({
|
|
@@ -196,7 +197,7 @@ async function introspectGenerate(project, paths, environment, debug, options =
|
|
|
196
197
|
let totalSubAgents = 0;
|
|
197
198
|
for (const [agentId, agentData] of Object.entries(project.agents)) {
|
|
198
199
|
if (!completeAgentIds.has(agentId)) continue;
|
|
199
|
-
if (agentData.subAgents) for (const
|
|
200
|
+
if (agentData.subAgents) for (const _subAgentId of Object.keys(agentData.subAgents)) totalSubAgents++;
|
|
200
201
|
}
|
|
201
202
|
if (totalSubAgents > 0) for (const [agentId, agentData] of Object.entries(project.agents)) {
|
|
202
203
|
if (!completeAgentIds.has(agentId)) continue;
|
|
@@ -219,6 +220,13 @@ async function introspectGenerate(project, paths, environment, debug, options =
|
|
|
219
220
|
ensureDir(agentFile);
|
|
220
221
|
writeFileSync(agentFile, agentContent, "utf-8");
|
|
221
222
|
generatedFiles.push(agentFile);
|
|
223
|
+
if (agentData.triggers && Object.keys(agentData.triggers).length > 0) for (const [triggerId, triggerData] of Object.entries(agentData.triggers)) {
|
|
224
|
+
const triggerFile = join(paths.agentsDir, "triggers", `${triggerId}.ts`);
|
|
225
|
+
const triggerContent = generateTriggerFile(triggerId, triggerData, style);
|
|
226
|
+
ensureDir(triggerFile);
|
|
227
|
+
writeFileSync(triggerFile, triggerContent, "utf-8");
|
|
228
|
+
generatedFiles.push(triggerFile);
|
|
229
|
+
}
|
|
222
230
|
}
|
|
223
231
|
const projectDataForGenerator = {
|
|
224
232
|
...project,
|
|
@@ -251,7 +259,7 @@ async function introspectGenerate(project, paths, environment, debug, options =
|
|
|
251
259
|
*/
|
|
252
260
|
function findContextConfigData(project, contextId) {
|
|
253
261
|
if (project.agents) {
|
|
254
|
-
for (const
|
|
262
|
+
for (const agentData of Object.values(project.agents)) if (agentData.contextConfig) {
|
|
255
263
|
if (agentData.contextConfig.id === contextId) return agentData.contextConfig;
|
|
256
264
|
}
|
|
257
265
|
}
|
|
@@ -261,7 +269,7 @@ function findContextConfigData(project, contextId) {
|
|
|
261
269
|
*/
|
|
262
270
|
function findStatusComponentData(project, statusId) {
|
|
263
271
|
if (project.agents) {
|
|
264
|
-
for (const
|
|
272
|
+
for (const agentData of Object.values(project.agents)) if (agentData.statusUpdates?.statusComponents) for (const statusComp of agentData.statusUpdates.statusComponents) {
|
|
265
273
|
let compId;
|
|
266
274
|
if (typeof statusComp === "string") compId = statusComp;
|
|
267
275
|
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 :
|
|
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.
|