@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.
- package/dist/_virtual/rolldown_runtime.js +7 -0
- package/dist/api.js +185 -0
- package/dist/commands/add.js +139 -0
- package/dist/commands/config.js +86 -0
- package/dist/commands/dev.js +259 -0
- package/dist/commands/init.js +360 -0
- package/dist/commands/list-agents.js +56 -0
- package/dist/commands/login.js +179 -0
- package/dist/commands/logout.js +56 -0
- package/dist/commands/profile.js +276 -0
- package/dist/{component-parser2.js → commands/pull-v3/component-parser.js} +16 -3
- package/dist/commands/pull-v3/component-updater.js +710 -0
- package/dist/commands/pull-v3/components/agent-generator.js +241 -0
- package/dist/commands/pull-v3/components/artifact-component-generator.js +127 -0
- package/dist/commands/pull-v3/components/context-config-generator.js +190 -0
- package/dist/commands/pull-v3/components/credential-generator.js +89 -0
- package/dist/commands/pull-v3/components/data-component-generator.js +102 -0
- package/dist/commands/pull-v3/components/environment-generator.js +170 -0
- package/dist/commands/pull-v3/components/external-agent-generator.js +75 -0
- package/dist/commands/pull-v3/components/function-tool-generator.js +94 -0
- package/dist/commands/pull-v3/components/mcp-tool-generator.js +86 -0
- package/dist/commands/pull-v3/components/project-generator.js +145 -0
- package/dist/commands/pull-v3/components/status-component-generator.js +92 -0
- package/dist/commands/pull-v3/components/sub-agent-generator.js +285 -0
- package/dist/commands/pull-v3/index.js +510 -0
- package/dist/commands/pull-v3/introspect-generator.js +278 -0
- package/dist/commands/pull-v3/llm-content-merger.js +192 -0
- package/dist/{new-component-generator.js → commands/pull-v3/new-component-generator.js} +14 -3
- package/dist/commands/pull-v3/project-comparator.js +914 -0
- package/dist/{project-index-generator.js → commands/pull-v3/project-index-generator.js} +1 -2
- package/dist/{project-validator.js → commands/pull-v3/project-validator.js} +4 -4
- package/dist/commands/pull-v3/targeted-typescript-placeholders.js +173 -0
- package/dist/commands/pull-v3/utils/component-registry.js +369 -0
- package/dist/commands/pull-v3/utils/component-tracker.js +165 -0
- package/dist/commands/pull-v3/utils/generator-utils.js +146 -0
- package/dist/commands/pull-v3/utils/model-provider-detector.js +44 -0
- package/dist/commands/push.js +326 -0
- package/dist/commands/status.js +89 -0
- package/dist/commands/update.js +97 -0
- package/dist/commands/whoami.js +38 -0
- package/dist/config.js +0 -1
- package/dist/env.js +30 -0
- package/dist/exports.js +3 -0
- package/dist/index.js +28 -196514
- package/dist/instrumentation.js +47 -0
- package/dist/types/agent.js +1 -0
- package/dist/types/tsx.d.d.ts +1 -0
- package/dist/utils/background-version-check.js +19 -0
- package/dist/utils/ci-environment.js +87 -0
- package/dist/utils/cli-pipeline.js +158 -0
- package/dist/utils/config.js +290 -0
- package/dist/utils/credentials.js +132 -0
- package/dist/utils/environment-loader.js +28 -0
- package/dist/utils/file-finder.js +62 -0
- package/dist/utils/json-comparator.js +185 -0
- package/dist/utils/json-comparison.js +232 -0
- package/dist/utils/mcp-runner.js +120 -0
- package/dist/utils/model-config.js +182 -0
- package/dist/utils/package-manager.js +58 -0
- package/dist/utils/profile-config.js +85 -0
- package/dist/utils/profiles/index.js +4 -0
- package/dist/utils/profiles/profile-manager.js +219 -0
- package/dist/utils/profiles/types.js +62 -0
- package/dist/utils/project-directory.js +33 -0
- package/dist/utils/project-loader.js +29 -0
- package/dist/utils/schema-introspection.js +44 -0
- package/dist/utils/templates.js +198 -0
- package/dist/utils/tsx-loader.js +27 -0
- package/dist/utils/url.js +26 -0
- package/dist/utils/version-check.js +79 -0
- package/package.json +4 -19
- package/dist/component-parser.js +0 -4
- package/dist/component-updater.js +0 -4
- package/dist/config2.js +0 -4
- package/dist/credential-stores.js +0 -4
- package/dist/environment-generator.js +0 -4
- package/dist/nodefs.js +0 -27
- package/dist/opfs-ahp.js +0 -368
- package/dist/project-loader.js +0 -4
- package/dist/tsx-loader.js +0 -4
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { jsonSchemaToZod } from "json-schema-to-zod";
|
|
2
|
+
|
|
3
|
+
//#region src/commands/pull-v3/components/data-component-generator.ts
|
|
4
|
+
/**
|
|
5
|
+
* Data Component Generator - Generate data component definitions
|
|
6
|
+
*
|
|
7
|
+
* Generates data components using the dataComponent() builder function from @inkeep/agents-sdk
|
|
8
|
+
*/
|
|
9
|
+
const DEFAULT_STYLE = {
|
|
10
|
+
quotes: "single",
|
|
11
|
+
semicolons: true,
|
|
12
|
+
indentation: " "
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Utility functions
|
|
16
|
+
*/
|
|
17
|
+
function toCamelCase(str) {
|
|
18
|
+
return str.toLowerCase().replace(/[-_](.)/g, (_, char) => char.toUpperCase()).replace(/[^a-zA-Z0-9]/g, "").replace(/^[0-9]/, "_$&");
|
|
19
|
+
}
|
|
20
|
+
function formatString(str, quote = "'", multiline = false) {
|
|
21
|
+
if (!str) return `${quote}${quote}`;
|
|
22
|
+
if (multiline && (str.includes("\n") || str.length > 80)) return `\`${str.replace(/`/g, "\\`")}\``;
|
|
23
|
+
return `${quote}${str.replace(new RegExp(quote, "g"), "\\" + quote)}${quote}`;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Convert JSON Schema to Zod schema using existing utility
|
|
27
|
+
*/
|
|
28
|
+
function convertJsonSchemaToZod(schema) {
|
|
29
|
+
if (!schema || typeof schema !== "object") return "z.any()";
|
|
30
|
+
try {
|
|
31
|
+
return jsonSchemaToZod(schema);
|
|
32
|
+
} catch (error) {
|
|
33
|
+
console.warn("Failed to convert JSON schema to Zod:", error);
|
|
34
|
+
return "z.any()";
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Generate Data Component Definition using dataComponent() builder function
|
|
39
|
+
*/
|
|
40
|
+
function generateDataComponentDefinition(componentId, componentData, style = DEFAULT_STYLE) {
|
|
41
|
+
if (!componentId || typeof componentId !== "string") throw new Error("componentId is required and must be a string");
|
|
42
|
+
if (!componentData || typeof componentData !== "object") throw new Error(`componentData is required for data component '${componentId}'`);
|
|
43
|
+
const missingFields = ["name"].filter((field) => !componentData[field] || componentData[field] === null || componentData[field] === void 0);
|
|
44
|
+
if (!componentData.props) missingFields.push("props");
|
|
45
|
+
if (missingFields.length > 0) throw new Error(`Missing required fields for data component '${componentId}': ${missingFields.join(", ")}`);
|
|
46
|
+
const { quotes, semicolons, indentation } = style;
|
|
47
|
+
const q = quotes === "single" ? "'" : "\"";
|
|
48
|
+
const semi = semicolons ? ";" : "";
|
|
49
|
+
const componentVarName = toCamelCase(componentId);
|
|
50
|
+
const lines = [];
|
|
51
|
+
lines.push(`export const ${componentVarName} = dataComponent({`);
|
|
52
|
+
lines.push(`${indentation}id: ${formatString(componentId, q)},`);
|
|
53
|
+
lines.push(`${indentation}name: ${formatString(componentData.name, q)},`);
|
|
54
|
+
lines.push(`${indentation}description: ${formatString(componentData.description, q, true)},`);
|
|
55
|
+
const schema = componentData.props || componentData.schema;
|
|
56
|
+
if (schema) {
|
|
57
|
+
const zodSchema = convertJsonSchemaToZod(schema);
|
|
58
|
+
lines.push(`${indentation}props: ${zodSchema},`);
|
|
59
|
+
}
|
|
60
|
+
if (componentData.render && typeof componentData.render === "object") {
|
|
61
|
+
const render = componentData.render;
|
|
62
|
+
if (render.component && typeof render.component === "string") {
|
|
63
|
+
lines.push(`${indentation}render: {`);
|
|
64
|
+
const componentString = JSON.stringify(render.component);
|
|
65
|
+
lines.push(`${indentation}${indentation}component: ${componentString},`);
|
|
66
|
+
if (render.mockData && typeof render.mockData === "object") {
|
|
67
|
+
const formattedMockData = JSON.stringify(render.mockData, null, 2).split("\n").map((line, index) => {
|
|
68
|
+
if (index === 0) return line;
|
|
69
|
+
return `${indentation}${indentation}${line}`;
|
|
70
|
+
}).join("\n");
|
|
71
|
+
lines.push(`${indentation}${indentation}mockData: ${formattedMockData},`);
|
|
72
|
+
}
|
|
73
|
+
lines.push(`${indentation}},`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
if (lines.length > 0 && lines[lines.length - 1].endsWith(",")) lines[lines.length - 1] = lines[lines.length - 1].slice(0, -1);
|
|
77
|
+
lines.push(`})${semi}`);
|
|
78
|
+
return lines.join("\n");
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Generate imports needed for a data component file
|
|
82
|
+
*/
|
|
83
|
+
function generateDataComponentImports(componentId, componentData, style = DEFAULT_STYLE) {
|
|
84
|
+
const { quotes, semicolons } = style;
|
|
85
|
+
const q = quotes === "single" ? "'" : "\"";
|
|
86
|
+
const semi = semicolons ? ";" : "";
|
|
87
|
+
const imports = [];
|
|
88
|
+
imports.push(`import { dataComponent } from ${q}@inkeep/agents-sdk${q}${semi}`);
|
|
89
|
+
if (componentData.props || componentData.schema) imports.push(`import { z } from ${q}zod${q}${semi}`);
|
|
90
|
+
return imports;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Generate complete data component file (imports + definition)
|
|
94
|
+
*/
|
|
95
|
+
function generateDataComponentFile(componentId, componentData, style = DEFAULT_STYLE) {
|
|
96
|
+
const imports = generateDataComponentImports(componentId, componentData, style);
|
|
97
|
+
const definition = generateDataComponentDefinition(componentId, componentData, style);
|
|
98
|
+
return imports.join("\n") + "\n\n" + definition + "\n";
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
//#endregion
|
|
102
|
+
export { generateDataComponentDefinition, generateDataComponentFile, generateDataComponentImports };
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
//#region src/commands/pull-v3/components/environment-generator.ts
|
|
2
|
+
const DEFAULT_STYLE = {
|
|
3
|
+
quotes: "single",
|
|
4
|
+
semicolons: true,
|
|
5
|
+
indentation: " "
|
|
6
|
+
};
|
|
7
|
+
function formatString(str, quote = "'", multiline = false) {
|
|
8
|
+
if (!str) return `${quote}${quote}`;
|
|
9
|
+
if (multiline && (str.includes("\n") || str.length > 80)) return `\`${str.replace(/`/g, "\\`")}\``;
|
|
10
|
+
return `${quote}${str.replace(new RegExp(quote, "g"), "\\" + quote)}${quote}`;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Format credentials object for environment settings
|
|
14
|
+
*/
|
|
15
|
+
function formatCredentialsObject(credentials, style, indentLevel) {
|
|
16
|
+
if (!credentials || typeof credentials !== "object") return "{}";
|
|
17
|
+
const { quotes, indentation } = style;
|
|
18
|
+
const q = quotes === "single" ? "'" : "\"";
|
|
19
|
+
const baseIndent = indentation.repeat(indentLevel);
|
|
20
|
+
const indent = indentation.repeat(indentLevel + 1);
|
|
21
|
+
const nestedIndent = indentation.repeat(indentLevel + 2);
|
|
22
|
+
const lines = ["{"];
|
|
23
|
+
for (const [key, credentialData] of Object.entries(credentials)) {
|
|
24
|
+
lines.push(`${indent}${formatString(key, q)}: {`);
|
|
25
|
+
if (credentialData.id) lines.push(`${nestedIndent}id: ${formatString(credentialData.id, q)},`);
|
|
26
|
+
if (credentialData.name) lines.push(`${nestedIndent}name: ${formatString(credentialData.name, q)},`);
|
|
27
|
+
if (credentialData.type) if (typeof credentialData.type === "string") {
|
|
28
|
+
const enumValue = credentialData.type === "memory" ? "CredentialStoreType.memory" : credentialData.type === "env" ? "CredentialStoreType.env" : credentialData.type === "keychain" ? "CredentialStoreType.keychain" : formatString(credentialData.type, q);
|
|
29
|
+
lines.push(`${nestedIndent}type: ${enumValue},`);
|
|
30
|
+
} else lines.push(`${nestedIndent}type: ${credentialData.type},`);
|
|
31
|
+
if (credentialData.credentialStoreId) lines.push(`${nestedIndent}credentialStoreId: ${formatString(credentialData.credentialStoreId, q)},`);
|
|
32
|
+
if (credentialData.description) lines.push(`${nestedIndent}description: ${formatString(credentialData.description, q)},`);
|
|
33
|
+
if (credentialData.retrievalParams) {
|
|
34
|
+
lines.push(`${nestedIndent}retrievalParams: {`);
|
|
35
|
+
for (const [paramKey, paramValue] of Object.entries(credentialData.retrievalParams)) {
|
|
36
|
+
if (paramValue === null || paramValue === void 0) continue;
|
|
37
|
+
if (typeof paramValue === "string") lines.push(`${nestedIndent}${indent}${paramKey}: ${formatString(paramValue, q)},`);
|
|
38
|
+
else lines.push(`${nestedIndent}${indent}${paramKey}: ${JSON.stringify(paramValue)},`);
|
|
39
|
+
}
|
|
40
|
+
const lastLineIndex = lines.length - 1;
|
|
41
|
+
if (lines[lastLineIndex].endsWith(",")) lines[lastLineIndex] = lines[lastLineIndex].slice(0, -1);
|
|
42
|
+
lines.push(`${nestedIndent}},`);
|
|
43
|
+
}
|
|
44
|
+
const lastPropIndex = lines.length - 1;
|
|
45
|
+
if (lines[lastPropIndex].endsWith(",")) lines[lastPropIndex] = lines[lastPropIndex].slice(0, -1);
|
|
46
|
+
lines.push(`${indent}},`);
|
|
47
|
+
}
|
|
48
|
+
if (lines.length > 1 && lines[lines.length - 1].endsWith(",")) lines[lines.length - 1] = lines[lines.length - 1].slice(0, -1);
|
|
49
|
+
lines.push(`${baseIndent}}`);
|
|
50
|
+
return lines.join("\n");
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Generate Individual Environment Settings Definition (development.env.ts, production.env.ts)
|
|
54
|
+
*/
|
|
55
|
+
function generateEnvironmentSettingsDefinition(environmentName, environmentData, style = DEFAULT_STYLE) {
|
|
56
|
+
if (!environmentName || typeof environmentName !== "string") throw new Error("environmentName is required and must be a string");
|
|
57
|
+
if (!environmentData || typeof environmentData !== "object") throw new Error(`environmentData is required for environment '${environmentName}'`);
|
|
58
|
+
const { quotes, semicolons, indentation } = style;
|
|
59
|
+
const semi = semicolons ? ";" : "";
|
|
60
|
+
const lines = [];
|
|
61
|
+
lines.push(`export const ${environmentName} = registerEnvironmentSettings({`);
|
|
62
|
+
if (environmentData.credentials && Object.keys(environmentData.credentials).length > 0) {
|
|
63
|
+
const formattedCredentials = formatCredentialsObject(environmentData.credentials, style, 1);
|
|
64
|
+
lines.push(`${indentation}credentials: ${formattedCredentials},`);
|
|
65
|
+
} else lines.push(`${indentation}credentials: {},`);
|
|
66
|
+
if (lines.length > 1 && lines[lines.length - 1].endsWith(",")) lines[lines.length - 1] = lines[lines.length - 1].slice(0, -1);
|
|
67
|
+
lines.push(`})${semi}`);
|
|
68
|
+
return lines.join("\n");
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Generate Main Environment Settings Index (index.ts)
|
|
72
|
+
*/
|
|
73
|
+
function generateEnvironmentIndexDefinition(environments, style = DEFAULT_STYLE) {
|
|
74
|
+
const { quotes, semicolons, indentation } = style;
|
|
75
|
+
const semi = semicolons ? ";" : "";
|
|
76
|
+
const lines = [];
|
|
77
|
+
lines.push(`export const envSettings = createEnvironmentSettings({`);
|
|
78
|
+
for (const envName of environments) lines.push(`${indentation}${envName},`);
|
|
79
|
+
if (lines.length > 1 && lines[lines.length - 1].endsWith(",")) lines[lines.length - 1] = lines[lines.length - 1].slice(0, -1);
|
|
80
|
+
lines.push(`})${semi}`);
|
|
81
|
+
return lines.join("\n");
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Generate imports for individual environment settings file
|
|
85
|
+
*/
|
|
86
|
+
function generateEnvironmentSettingsImports(environmentName, environmentData, style = DEFAULT_STYLE) {
|
|
87
|
+
const { quotes, semicolons } = style;
|
|
88
|
+
const q = quotes === "single" ? "'" : "\"";
|
|
89
|
+
const semi = semicolons ? ";" : "";
|
|
90
|
+
const imports = [];
|
|
91
|
+
imports.push(`import { registerEnvironmentSettings } from ${q}@inkeep/agents-sdk${q}${semi}`);
|
|
92
|
+
if (environmentData.credentials && Object.values(environmentData.credentials).some((cred) => typeof cred.type === "string" && [
|
|
93
|
+
"memory",
|
|
94
|
+
"env",
|
|
95
|
+
"keychain"
|
|
96
|
+
].includes(cred.type))) imports.push(`import { CredentialStoreType } from ${q}@inkeep/agents-core${q}${semi}`);
|
|
97
|
+
return imports;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Generate imports for main environment index file
|
|
101
|
+
*/
|
|
102
|
+
function generateEnvironmentIndexImports(environments, style = DEFAULT_STYLE) {
|
|
103
|
+
const { quotes, semicolons } = style;
|
|
104
|
+
const q = quotes === "single" ? "'" : "\"";
|
|
105
|
+
const semi = semicolons ? ";" : "";
|
|
106
|
+
const imports = [];
|
|
107
|
+
imports.push(`import { createEnvironmentSettings } from ${q}@inkeep/agents-sdk${q}${semi}`);
|
|
108
|
+
for (const envName of environments) imports.push(`import { ${envName} } from ${q}./${envName}.env${q}${semi}`);
|
|
109
|
+
return imports;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Generate complete environment settings file
|
|
113
|
+
*/
|
|
114
|
+
function generateEnvironmentSettingsFile(environmentName, environmentData, style = DEFAULT_STYLE) {
|
|
115
|
+
const imports = generateEnvironmentSettingsImports(environmentName, environmentData, style);
|
|
116
|
+
const definition = generateEnvironmentSettingsDefinition(environmentName, environmentData, style);
|
|
117
|
+
return imports.join("\n") + "\n\n" + definition + "\n";
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Generate complete environment index file
|
|
121
|
+
*/
|
|
122
|
+
function generateEnvironmentIndexFile(environments, style = DEFAULT_STYLE) {
|
|
123
|
+
const imports = generateEnvironmentIndexImports(environments, style);
|
|
124
|
+
const definition = generateEnvironmentIndexDefinition(environments, style);
|
|
125
|
+
return imports.join("\n") + "\n\n" + definition + "\n";
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Generate environment file (alias for generateEnvironmentSettingsFile)
|
|
129
|
+
* This is the main function used by introspect-generator
|
|
130
|
+
*/
|
|
131
|
+
function generateEnvironmentFile(environmentName, environmentData, style = DEFAULT_STYLE, registry) {
|
|
132
|
+
if (registry && environmentData.credentials && Array.isArray(environmentData.credentials)) {
|
|
133
|
+
const { quotes, semicolons, indentation } = style;
|
|
134
|
+
const q = quotes === "single" ? "'" : "\"";
|
|
135
|
+
const semi = semicolons ? ";" : "";
|
|
136
|
+
const imports = [];
|
|
137
|
+
const credentialRefs = [];
|
|
138
|
+
imports.push(`import { registerEnvironmentSettings } from ${q}@inkeep/agents-sdk${q}${semi}`);
|
|
139
|
+
for (const credentialId of environmentData.credentials) {
|
|
140
|
+
const credentialComponent = registry.get(credentialId, "credentials");
|
|
141
|
+
if (credentialComponent) {
|
|
142
|
+
const relativePath = `../credentials/${credentialId}`;
|
|
143
|
+
imports.push(`import { ${credentialComponent.name} } from ${q}${relativePath}${q}${semi}`);
|
|
144
|
+
credentialRefs.push(credentialComponent.name);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
const lines = [];
|
|
148
|
+
lines.push(...imports);
|
|
149
|
+
lines.push("");
|
|
150
|
+
lines.push(`export const ${environmentName} = registerEnvironmentSettings({`);
|
|
151
|
+
if (credentialRefs.length > 0) {
|
|
152
|
+
lines.push(`${indentation}credentials: {`);
|
|
153
|
+
for (let i = 0; i < environmentData.credentials.length; i++) {
|
|
154
|
+
const credentialId = environmentData.credentials[i];
|
|
155
|
+
const credentialVarName = credentialRefs[i];
|
|
156
|
+
const isLast = i === credentialRefs.length - 1;
|
|
157
|
+
const validKey = registry.getVariableName(credentialId, "credentials");
|
|
158
|
+
lines.push(`${indentation}${indentation}${validKey}: ${credentialVarName}${isLast ? "" : ","}`);
|
|
159
|
+
}
|
|
160
|
+
lines.push(`${indentation}}`);
|
|
161
|
+
} else lines.push(`${indentation}credentials: {}`);
|
|
162
|
+
lines.push(`})${semi}`);
|
|
163
|
+
lines.push("");
|
|
164
|
+
return lines.join("\n");
|
|
165
|
+
}
|
|
166
|
+
return generateEnvironmentSettingsFile(environmentName, environmentData, style);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
//#endregion
|
|
170
|
+
export { generateEnvironmentFile, generateEnvironmentIndexDefinition, generateEnvironmentIndexFile, generateEnvironmentIndexImports, generateEnvironmentSettingsDefinition, generateEnvironmentSettingsFile, generateEnvironmentSettingsImports };
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { DEFAULT_STYLE, formatString, generateFileContent, generateImport, removeTrailingComma, toCamelCase } from "../utils/generator-utils.js";
|
|
2
|
+
|
|
3
|
+
//#region src/commands/pull-v3/components/external-agent-generator.ts
|
|
4
|
+
/**
|
|
5
|
+
* Generate External Agent Definition using externalAgent() builder function
|
|
6
|
+
*/
|
|
7
|
+
function generateExternalAgentDefinition(agentId, agentData, style = DEFAULT_STYLE, registry) {
|
|
8
|
+
if (!agentId || typeof agentId !== "string") throw new Error("agentId is required and must be a string");
|
|
9
|
+
if (!agentData || typeof agentData !== "object") throw new Error(`agentData is required for external agent '${agentId}'`);
|
|
10
|
+
const missingFields = ["name", "baseUrl"].filter((field) => !agentData[field] || agentData[field] === null || agentData[field] === void 0);
|
|
11
|
+
if (missingFields.length > 0) throw new Error(`Missing required fields for external agent '${agentId}': ${missingFields.join(", ")}`);
|
|
12
|
+
const { quotes, semicolons, indentation } = style;
|
|
13
|
+
const q = quotes === "single" ? "'" : "\"";
|
|
14
|
+
const semi = semicolons ? ";" : "";
|
|
15
|
+
let agentVarName = toCamelCase(agentId);
|
|
16
|
+
if (registry) {
|
|
17
|
+
const registryVarName = registry.getVariableName(agentId, "externalAgents");
|
|
18
|
+
if (registryVarName) agentVarName = registryVarName;
|
|
19
|
+
}
|
|
20
|
+
const lines = [];
|
|
21
|
+
lines.push(`export const ${agentVarName} = externalAgent({`);
|
|
22
|
+
lines.push(`${indentation}id: ${formatString(agentId, q)},`);
|
|
23
|
+
if (agentData.name !== void 0 && agentData.name !== null) lines.push(`${indentation}name: ${formatString(agentData.name, q)},`);
|
|
24
|
+
else lines.push(`${indentation}name: ${formatString(agentId, q)},`);
|
|
25
|
+
if (agentData.description !== void 0 && agentData.description !== null) lines.push(`${indentation}description: ${formatString(agentData.description, q, true)},`);
|
|
26
|
+
else lines.push(`${indentation}description: ${formatString(`External agent ${agentId}`, q)},`);
|
|
27
|
+
if (agentData.baseUrl !== void 0 && agentData.baseUrl !== null) lines.push(`${indentation}baseUrl: ${formatString(agentData.baseUrl, q)},`);
|
|
28
|
+
if (agentData.credentialReference) {
|
|
29
|
+
if (typeof agentData.credentialReference === "string") {
|
|
30
|
+
if (!registry) throw new Error("Registry is required for credentialReference generation");
|
|
31
|
+
const credentialVar = registry.getVariableName(agentData.credentialReference, "credentials");
|
|
32
|
+
if (!credentialVar) throw new Error(`Failed to resolve variable name for credential reference: ${agentData.credentialReference}`);
|
|
33
|
+
lines.push(`${indentation}credentialReference: ${credentialVar},`);
|
|
34
|
+
} else if (typeof agentData.credentialReference === "object") {
|
|
35
|
+
const credLines = [];
|
|
36
|
+
if (agentData.credentialReference.id) credLines.push(`${indentation}${indentation}id: ${formatString(agentData.credentialReference.id, q)},`);
|
|
37
|
+
if (agentData.credentialReference.name) credLines.push(`${indentation}${indentation}name: ${formatString(agentData.credentialReference.name, q)},`);
|
|
38
|
+
if (agentData.credentialReference.description) credLines.push(`${indentation}${indentation}description: ${formatString(agentData.credentialReference.description, q)},`);
|
|
39
|
+
if (credLines.length > 0 && credLines[credLines.length - 1].endsWith(",")) credLines[credLines.length - 1] = credLines[credLines.length - 1].slice(0, -1);
|
|
40
|
+
lines.push(`${indentation}credentialReference: {`);
|
|
41
|
+
lines.push(...credLines);
|
|
42
|
+
lines.push(`${indentation}},`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
removeTrailingComma(lines);
|
|
46
|
+
lines.push(`})${semi}`);
|
|
47
|
+
return lines.join("\n");
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Generate imports needed for an external agent file
|
|
51
|
+
*/
|
|
52
|
+
function generateExternalAgentImports(agentId, agentData, style = DEFAULT_STYLE, registry) {
|
|
53
|
+
const imports = [];
|
|
54
|
+
imports.push(generateImport(["externalAgent"], "@inkeep/agents-sdk", style));
|
|
55
|
+
if (agentData.credentialReference && typeof agentData.credentialReference === "string") {
|
|
56
|
+
if (!registry) throw new Error("Registry is required for credential reference imports");
|
|
57
|
+
const currentFilePath = `external-agents/${agentId}.ts`;
|
|
58
|
+
const credentialRefs = [{
|
|
59
|
+
id: agentData.credentialReference,
|
|
60
|
+
type: "credentials"
|
|
61
|
+
}];
|
|
62
|
+
const componentImports = registry.getImportsForFile(currentFilePath, credentialRefs);
|
|
63
|
+
imports.push(...componentImports);
|
|
64
|
+
}
|
|
65
|
+
return imports;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Generate complete external agent file (imports + definition)
|
|
69
|
+
*/
|
|
70
|
+
function generateExternalAgentFile(agentId, agentData, style = DEFAULT_STYLE, registry) {
|
|
71
|
+
return generateFileContent(generateExternalAgentImports(agentId, agentData, style, registry), [generateExternalAgentDefinition(agentId, agentData, style, registry)]);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
//#endregion
|
|
75
|
+
export { generateExternalAgentDefinition, generateExternalAgentFile, generateExternalAgentImports };
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { jsonSchemaToZod } from "json-schema-to-zod";
|
|
2
|
+
|
|
3
|
+
//#region src/commands/pull-v3/components/function-tool-generator.ts
|
|
4
|
+
const DEFAULT_STYLE = {
|
|
5
|
+
quotes: "single",
|
|
6
|
+
semicolons: true,
|
|
7
|
+
indentation: " "
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Utility functions
|
|
11
|
+
*/
|
|
12
|
+
function toCamelCase(str) {
|
|
13
|
+
return str.toLowerCase().replace(/[-_](.)/g, (_, char) => char.toUpperCase()).replace(/[^a-zA-Z0-9]/g, "").replace(/^[0-9]/, "_$&");
|
|
14
|
+
}
|
|
15
|
+
function formatString(str, quote = "'", multiline = false) {
|
|
16
|
+
if (!str) return `${quote}${quote}`;
|
|
17
|
+
if (multiline && (str.includes("\n") || str.length > 80)) return `\`${str.replace(/`/g, "\\`")}\``;
|
|
18
|
+
return `${quote}${str.replace(new RegExp(quote, "g"), "\\" + quote)}${quote}`;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Format JavaScript function code with proper indentation
|
|
22
|
+
*/
|
|
23
|
+
function formatExecuteFunction(executeCode, indentation) {
|
|
24
|
+
if (!executeCode || typeof executeCode !== "string") return `async ({}) => {\n${indentation} // TODO: Implement function logic\n${indentation} return {};\n${indentation}}`;
|
|
25
|
+
const trimmedCode = executeCode.trim();
|
|
26
|
+
if (trimmedCode.includes("\n")) return trimmedCode.split("\n").map((line, index) => {
|
|
27
|
+
if (index === 0) return line;
|
|
28
|
+
return indentation + line;
|
|
29
|
+
}).join("\n");
|
|
30
|
+
if (trimmedCode.startsWith("async") || trimmedCode.startsWith("function")) return trimmedCode;
|
|
31
|
+
return `async ({}) => {\n${indentation} ${executeCode.replace(/\n/g, `\n${indentation} `)}\n${indentation}}`;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Generate Function Tool Definition using functionTool() builder function
|
|
35
|
+
*/
|
|
36
|
+
function generateFunctionToolDefinition(toolId, toolData, style = DEFAULT_STYLE) {
|
|
37
|
+
if (!toolId || typeof toolId !== "string") throw new Error("toolId is required and must be a string");
|
|
38
|
+
if (!toolData || typeof toolData !== "object") throw new Error(`toolData is required for function tool '${toolId}'`);
|
|
39
|
+
const missingFields = ["name"].filter((field) => !toolData[field] || toolData[field] === null || toolData[field] === void 0);
|
|
40
|
+
if (!toolData.inputSchema && !toolData.schema) missingFields.push("inputSchema");
|
|
41
|
+
if (!toolData.executeCode && !toolData.execute) missingFields.push("executeCode");
|
|
42
|
+
if (missingFields.length > 0) throw new Error(`Missing required fields for function tool '${toolId}': ${missingFields.join(", ")}`);
|
|
43
|
+
const { quotes, semicolons, indentation } = style;
|
|
44
|
+
const q = quotes === "single" ? "'" : "\"";
|
|
45
|
+
const semi = semicolons ? ";" : "";
|
|
46
|
+
const toolVarName = toCamelCase(toolId);
|
|
47
|
+
const lines = [];
|
|
48
|
+
lines.push(`export const ${toolVarName} = functionTool({`);
|
|
49
|
+
lines.push(`${indentation}name: ${formatString(toolData.name, q)},`);
|
|
50
|
+
if (toolData.description) lines.push(`${indentation}description: ${formatString(toolData.description, q, true)},`);
|
|
51
|
+
const inputSchema = toolData.inputSchema || toolData.schema;
|
|
52
|
+
if (inputSchema) {
|
|
53
|
+
const formattedSchema = JSON.stringify(inputSchema, null, 2).split("\n").map((line, index) => {
|
|
54
|
+
if (index === 0) return `${indentation}inputSchema: ${line}`;
|
|
55
|
+
return `${indentation}${line}`;
|
|
56
|
+
}).join("\n");
|
|
57
|
+
lines.push(formattedSchema + ",");
|
|
58
|
+
}
|
|
59
|
+
const executeCode = toolData.executeCode || toolData.execute;
|
|
60
|
+
if (executeCode) {
|
|
61
|
+
const executeFunc = formatExecuteFunction(executeCode, indentation);
|
|
62
|
+
lines.push(`${indentation}execute: ${executeFunc},`);
|
|
63
|
+
} else {
|
|
64
|
+
lines.push(`${indentation}execute: async ({}) => {`);
|
|
65
|
+
lines.push(`${indentation} // TODO: Implement function logic`);
|
|
66
|
+
lines.push(`${indentation} return {};`);
|
|
67
|
+
lines.push(`${indentation}},`);
|
|
68
|
+
}
|
|
69
|
+
if (lines.length > 0 && lines[lines.length - 1].endsWith(",")) lines[lines.length - 1] = lines[lines.length - 1].slice(0, -1);
|
|
70
|
+
lines.push(`})${semi}`);
|
|
71
|
+
return lines.join("\n");
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Generate imports needed for a function tool file
|
|
75
|
+
*/
|
|
76
|
+
function generateFunctionToolImports(toolId, toolData, style = DEFAULT_STYLE) {
|
|
77
|
+
const { quotes, semicolons } = style;
|
|
78
|
+
const q = quotes === "single" ? "'" : "\"";
|
|
79
|
+
const semi = semicolons ? ";" : "";
|
|
80
|
+
const imports = [];
|
|
81
|
+
imports.push(`import { functionTool } from ${q}@inkeep/agents-sdk${q}${semi}`);
|
|
82
|
+
return imports;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Generate complete function tool file (imports + definition)
|
|
86
|
+
*/
|
|
87
|
+
function generateFunctionToolFile(toolId, toolData, style = DEFAULT_STYLE) {
|
|
88
|
+
const imports = generateFunctionToolImports(toolId, toolData, style);
|
|
89
|
+
const definition = generateFunctionToolDefinition(toolId, toolData, style);
|
|
90
|
+
return imports.join("\n") + "\n\n" + definition + "\n";
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
//#endregion
|
|
94
|
+
export { generateFunctionToolDefinition, generateFunctionToolFile, generateFunctionToolImports };
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
//#region src/commands/pull-v3/components/mcp-tool-generator.ts
|
|
2
|
+
const DEFAULT_STYLE = {
|
|
3
|
+
quotes: "single",
|
|
4
|
+
semicolons: true,
|
|
5
|
+
indentation: " "
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Utility functions
|
|
9
|
+
*/
|
|
10
|
+
function toCamelCase(str) {
|
|
11
|
+
return str.toLowerCase().replace(/[-_](.)/g, (_, char) => char.toUpperCase()).replace(/[^a-zA-Z0-9]/g, "").replace(/^[0-9]/, "_$&");
|
|
12
|
+
}
|
|
13
|
+
function formatString(str, quote = "'", multiline = false) {
|
|
14
|
+
if (!str) return `${quote}${quote}`;
|
|
15
|
+
if (multiline && (str.includes("\n") || str.length > 80)) return `\`${str.replace(/`/g, "\\`")}\``;
|
|
16
|
+
return `${quote}${str.replace(new RegExp(quote, "g"), "\\" + quote)}${quote}`;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Generate MCP Tool Definition using mcpTool() builder function
|
|
20
|
+
*/
|
|
21
|
+
function generateMcpToolDefinition(toolId, toolData, style = DEFAULT_STYLE, registry) {
|
|
22
|
+
if (!toolId || typeof toolId !== "string") throw new Error("toolId is required and must be a string");
|
|
23
|
+
if (!toolData || typeof toolData !== "object") throw new Error(`toolData is required for MCP tool '${toolId}'`);
|
|
24
|
+
const requiredFields = ["name"];
|
|
25
|
+
const serverUrl = toolData.config?.mcp?.server?.url || toolData.serverUrl;
|
|
26
|
+
const missingFields = requiredFields.filter((field) => !toolData[field] || toolData[field] === null || toolData[field] === void 0);
|
|
27
|
+
if (!serverUrl) missingFields.push("serverUrl (from config.mcp.server.url or serverUrl)");
|
|
28
|
+
if (missingFields.length > 0) throw new Error(`Missing required fields for MCP tool '${toolId}': ${missingFields.join(", ")}`);
|
|
29
|
+
const { quotes, semicolons, indentation } = style;
|
|
30
|
+
const q = quotes === "single" ? "'" : "\"";
|
|
31
|
+
const semi = semicolons ? ";" : "";
|
|
32
|
+
const toolVarName = toCamelCase(toolId);
|
|
33
|
+
const lines = [];
|
|
34
|
+
lines.push(`export const ${toolVarName} = mcpTool({`);
|
|
35
|
+
lines.push(`${indentation}id: ${formatString(toolId, q)},`);
|
|
36
|
+
lines.push(`${indentation}name: ${formatString(toolData.name, q)},`);
|
|
37
|
+
if (toolData.config?.mcp && typeof toolData.config.mcp === "object") {
|
|
38
|
+
const mcpConfig = toolData.config.mcp;
|
|
39
|
+
lines.push(`${indentation}serverUrl: ${formatString(mcpConfig.server?.url, q)},`);
|
|
40
|
+
if (mcpConfig.transport) lines.push(`${indentation}transport: ${JSON.stringify(mcpConfig.transport, null, 2)},`);
|
|
41
|
+
if (mcpConfig.activeTools && Array.isArray(mcpConfig.activeTools)) lines.push(`${indentation}activeTools: ${JSON.stringify(mcpConfig.activeTools)},`);
|
|
42
|
+
}
|
|
43
|
+
if (toolData.description) lines.push(`${indentation}description: ${formatString(toolData.description, q, true)},`);
|
|
44
|
+
if (toolData.imageUrl) lines.push(`${indentation}imageUrl: ${formatString(toolData.imageUrl, q)},`);
|
|
45
|
+
if (toolData.headers && typeof toolData.headers === "object") {
|
|
46
|
+
const formattedHeaders = JSON.stringify(toolData.headers, null, 2).split("\n").map((line, index) => {
|
|
47
|
+
if (index === 0) return `${indentation}headers: ${line}`;
|
|
48
|
+
return `${indentation}${line}`;
|
|
49
|
+
}).join("\n");
|
|
50
|
+
lines.push(formattedHeaders + ",");
|
|
51
|
+
}
|
|
52
|
+
if (toolData.credential) if (typeof toolData.credential === "object") {
|
|
53
|
+
const credentialStr = JSON.stringify(toolData.credential);
|
|
54
|
+
lines.push(`${indentation}credential: ${credentialStr},`);
|
|
55
|
+
} else lines.push(`${indentation}credential: ${toolData.credential},`);
|
|
56
|
+
else if (toolData.credentialReferenceId && registry) {
|
|
57
|
+
const validKey = registry.getVariableName(toolData.credentialReferenceId, "credentials");
|
|
58
|
+
lines.push(`${indentation}credential: envSettings.getEnvironmentCredential(${formatString(validKey, q)}),`);
|
|
59
|
+
}
|
|
60
|
+
if (lines.length > 0 && lines[lines.length - 1].endsWith(",")) lines[lines.length - 1] = lines[lines.length - 1].slice(0, -1);
|
|
61
|
+
lines.push(`})${semi}`);
|
|
62
|
+
return lines.join("\n");
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Generate imports needed for an MCP tool file
|
|
66
|
+
*/
|
|
67
|
+
function generateMcpToolImports(toolId, toolData, style = DEFAULT_STYLE) {
|
|
68
|
+
const { quotes, semicolons } = style;
|
|
69
|
+
const q = quotes === "single" ? "'" : "\"";
|
|
70
|
+
const semi = semicolons ? ";" : "";
|
|
71
|
+
const imports = [];
|
|
72
|
+
imports.push(`import { mcpTool } from ${q}@inkeep/agents-sdk${q}${semi}`);
|
|
73
|
+
if (toolData.credentialReferenceId) imports.push(`import { envSettings } from ${q}../environments${q}${semi}`);
|
|
74
|
+
return imports;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Generate complete MCP tool file (imports + definition)
|
|
78
|
+
*/
|
|
79
|
+
function generateMcpToolFile(toolId, toolData, style = DEFAULT_STYLE, registry) {
|
|
80
|
+
const imports = generateMcpToolImports(toolId, toolData, style);
|
|
81
|
+
const definition = generateMcpToolDefinition(toolId, toolData, style, registry);
|
|
82
|
+
return imports.join("\n") + "\n\n" + definition + "\n";
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
//#endregion
|
|
86
|
+
export { generateMcpToolDefinition, generateMcpToolFile, generateMcpToolImports };
|