@inkeep/agents-cli 0.50.6 ā 0.52.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/agents-cli/package.js +6 -0
- package/dist/commands/config.js +1 -1
- package/dist/commands/dev.js +1 -1
- package/dist/commands/init.js +1 -1
- package/dist/commands/pull-v3/component-parser.js +4 -10
- package/dist/commands/pull-v4/agent-generator.js +274 -0
- package/dist/commands/pull-v4/artifact-component-generator.js +69 -0
- package/dist/commands/pull-v4/context-config-generator.js +264 -0
- package/dist/commands/pull-v4/credential-generator.js +30 -0
- package/dist/commands/pull-v4/data-component-generator.js +50 -0
- package/dist/commands/pull-v4/environment-generator.js +123 -0
- package/dist/commands/pull-v4/external-agent-generator.js +56 -0
- package/dist/commands/pull-v4/function-tool-generator.js +48 -0
- package/dist/commands/pull-v4/introspect/index.js +365 -0
- package/dist/commands/pull-v4/introspect/test-helpers.js +143 -0
- package/dist/commands/pull-v4/introspect-generator.js +691 -0
- package/dist/commands/pull-v4/mcp-tool-generator.js +91 -0
- package/dist/commands/pull-v4/module-merge.js +379 -0
- package/dist/commands/pull-v4/project-generator.js +101 -0
- package/dist/commands/pull-v4/status-component-generator.js +35 -0
- package/dist/commands/pull-v4/sub-agent-generator.js +168 -0
- package/dist/commands/pull-v4/trigger-generator.js +58 -0
- package/dist/commands/pull-v4/utils.js +219 -0
- package/dist/commands/push.js +1 -1
- package/dist/commands/update.js +2 -2
- package/dist/index.js +18 -44
- package/dist/node_modules/.pnpm/diff@8.0.3/node_modules/diff/libesm/diff/array.js +18 -0
- package/dist/node_modules/.pnpm/diff@8.0.3/node_modules/diff/libesm/diff/base.js +180 -0
- package/dist/node_modules/.pnpm/diff@8.0.3/node_modules/diff/libesm/diff/character.js +8 -0
- package/dist/node_modules/.pnpm/diff@8.0.3/node_modules/diff/libesm/diff/css.js +12 -0
- package/dist/node_modules/.pnpm/diff@8.0.3/node_modules/diff/libesm/diff/json.js +60 -0
- package/dist/node_modules/.pnpm/diff@8.0.3/node_modules/diff/libesm/diff/line.js +37 -0
- package/dist/node_modules/.pnpm/diff@8.0.3/node_modules/diff/libesm/diff/sentence.js +31 -0
- package/dist/node_modules/.pnpm/diff@8.0.3/node_modules/diff/libesm/diff/word.js +118 -0
- package/dist/node_modules/.pnpm/diff@8.0.3/node_modules/diff/libesm/index.js +11 -0
- package/dist/node_modules/.pnpm/diff@8.0.3/node_modules/diff/libesm/patch/create.js +141 -0
- package/dist/node_modules/.pnpm/diff@8.0.3/node_modules/diff/libesm/util/string.js +63 -0
- package/dist/utils/ci-environment.js +1 -1
- package/dist/utils/config.js +1 -1
- package/dist/utils/environment-loader.js +1 -1
- package/dist/utils/file-finder.js +1 -1
- package/dist/utils/mcp-runner.js +1 -1
- package/dist/utils/profile-config.js +1 -1
- package/dist/utils/profiles/profile-manager.js +1 -1
- package/dist/utils/project-directory.js +1 -1
- package/dist/utils/project-loader.js +1 -1
- package/dist/utils/version-check.js +6 -15
- package/package.json +5 -4
- package/dist/commands/pull-v3/component-updater.js +0 -768
- package/dist/commands/pull-v3/components/agent-generator.js +0 -255
- package/dist/commands/pull-v3/components/artifact-component-generator.js +0 -143
- package/dist/commands/pull-v3/components/context-config-generator.js +0 -190
- package/dist/commands/pull-v3/components/credential-generator.js +0 -89
- package/dist/commands/pull-v3/components/data-component-generator.js +0 -102
- package/dist/commands/pull-v3/components/environment-generator.js +0 -173
- package/dist/commands/pull-v3/components/external-agent-generator.js +0 -75
- package/dist/commands/pull-v3/components/function-tool-generator.js +0 -92
- package/dist/commands/pull-v3/components/mcp-tool-generator.js +0 -86
- package/dist/commands/pull-v3/components/project-generator.js +0 -157
- package/dist/commands/pull-v3/components/status-component-generator.js +0 -92
- package/dist/commands/pull-v3/components/sub-agent-generator.js +0 -295
- package/dist/commands/pull-v3/components/trigger-generator.js +0 -185
- package/dist/commands/pull-v3/index.js +0 -510
- package/dist/commands/pull-v3/introspect-generator.js +0 -286
- package/dist/commands/pull-v3/llm-content-merger.js +0 -192
- package/dist/commands/pull-v3/new-component-generator.js +0 -279
- package/dist/commands/pull-v3/project-index-generator.js +0 -32
- package/dist/commands/pull-v3/project-validator.js +0 -358
- package/dist/utils/url.js +0 -26
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { addValueToObject, createFactoryDefinition, toCamelCase } from "./utils.js";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
|
|
4
|
+
//#region src/commands/pull-v4/credential-generator.ts
|
|
5
|
+
const CredentialSchema = z.object({
|
|
6
|
+
credentialId: z.string().nonempty(),
|
|
7
|
+
name: z.string().nonempty(),
|
|
8
|
+
type: z.string().nonempty(),
|
|
9
|
+
credentialStoreId: z.string().nonempty(),
|
|
10
|
+
description: z.string().optional(),
|
|
11
|
+
retrievalParams: z.unknown().optional()
|
|
12
|
+
});
|
|
13
|
+
function generateCredentialDefinition(data) {
|
|
14
|
+
const result = CredentialSchema.safeParse(data);
|
|
15
|
+
if (!result.success) throw new Error(`Validation failed for credential:\n${z.prettifyError(result.error)}`);
|
|
16
|
+
const parsed = result.data;
|
|
17
|
+
const { sourceFile, configObject } = createFactoryDefinition({
|
|
18
|
+
importName: "credential",
|
|
19
|
+
variableName: toCamelCase(parsed.credentialId)
|
|
20
|
+
});
|
|
21
|
+
const { credentialId, ...rest } = parsed;
|
|
22
|
+
for (const [k, v] of Object.entries({
|
|
23
|
+
id: credentialId,
|
|
24
|
+
...rest
|
|
25
|
+
})) addValueToObject(configObject, k, v);
|
|
26
|
+
return sourceFile;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
//#endregion
|
|
30
|
+
export { generateCredentialDefinition };
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { addStringProperty, addValueToObject, convertJsonSchemaToZodSafe, createFactoryDefinition, toCamelCase } from "./utils.js";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
|
|
4
|
+
//#region src/commands/pull-v4/data-component-generator.ts
|
|
5
|
+
const DataComponentSchema = z.object({
|
|
6
|
+
dataComponentId: z.string().nonempty(),
|
|
7
|
+
name: z.string().nonempty(),
|
|
8
|
+
description: z.string().nullable().optional(),
|
|
9
|
+
props: z.unknown().optional(),
|
|
10
|
+
schema: z.unknown().optional(),
|
|
11
|
+
render: z.looseObject({
|
|
12
|
+
component: z.string().optional(),
|
|
13
|
+
mockData: z.looseObject({}).optional()
|
|
14
|
+
}).nullable().optional()
|
|
15
|
+
});
|
|
16
|
+
function generateDataComponentDefinition(data) {
|
|
17
|
+
const result = DataComponentSchema.safeParse(data);
|
|
18
|
+
if (!result.success) throw new Error(`Validation failed for data component:\n${z.prettifyError(result.error)}`);
|
|
19
|
+
const parsed = result.data;
|
|
20
|
+
const props = parsed.props !== void 0 ? parsed.props : parsed.schema;
|
|
21
|
+
const { sourceFile, configObject } = createFactoryDefinition({
|
|
22
|
+
importName: "dataComponent",
|
|
23
|
+
variableName: toCamelCase(parsed.dataComponentId)
|
|
24
|
+
});
|
|
25
|
+
if (props !== void 0) sourceFile.addImportDeclaration({
|
|
26
|
+
namedImports: ["z"],
|
|
27
|
+
moduleSpecifier: "zod"
|
|
28
|
+
});
|
|
29
|
+
writeDataComponentConfig(configObject, parsed, props);
|
|
30
|
+
return sourceFile;
|
|
31
|
+
}
|
|
32
|
+
function writeDataComponentConfig(configObject, data, props) {
|
|
33
|
+
addStringProperty(configObject, "id", data.dataComponentId);
|
|
34
|
+
addStringProperty(configObject, "name", data.name);
|
|
35
|
+
if (typeof data.description === "string") addStringProperty(configObject, "description", data.description);
|
|
36
|
+
if (props !== void 0) configObject.addPropertyAssignment({
|
|
37
|
+
name: "props",
|
|
38
|
+
initializer: convertJsonSchemaToZodSafe(props)
|
|
39
|
+
});
|
|
40
|
+
if (data.render) addRenderProperty(configObject, data.render);
|
|
41
|
+
}
|
|
42
|
+
function addRenderProperty(configObject, render) {
|
|
43
|
+
if (render.component) addValueToObject(configObject, "render", {
|
|
44
|
+
component: render.component,
|
|
45
|
+
mockData: render.mockData
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
//#endregion
|
|
50
|
+
export { generateDataComponentDefinition };
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { addStringProperty, createFactoryDefinition, formatInlineLiteral, formatPropertyName, isPlainObject } from "./utils.js";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { SyntaxKind } from "ts-morph";
|
|
4
|
+
|
|
5
|
+
//#region src/commands/pull-v4/environment-generator.ts
|
|
6
|
+
const EnvironmentSettingsSchema = z.looseObject({ credentials: z.record(z.string(), z.unknown()).nullable().optional() });
|
|
7
|
+
const EnvironmentIndexSchema = z.array(z.string());
|
|
8
|
+
function generateEnvironmentSettingsImports(environmentData) {
|
|
9
|
+
const imports = [`import { registerEnvironmentSettings } from '@inkeep/agents-sdk';`];
|
|
10
|
+
if (needsCredentialStoreType(environmentData)) imports.push(`import { CredentialStoreType } from '@inkeep/agents-core';`);
|
|
11
|
+
return imports;
|
|
12
|
+
}
|
|
13
|
+
function generateEnvironmentIndexImports(environments) {
|
|
14
|
+
const result = EnvironmentIndexSchema.safeParse(environments);
|
|
15
|
+
if (!result.success) throw new Error(`Validation failed for environments index:\n${z.prettifyError(result.error)}`);
|
|
16
|
+
const imports = [`import { createEnvironmentSettings } from '@inkeep/agents-sdk';`];
|
|
17
|
+
for (const environmentName of result.data) imports.push(`import { ${environmentName} } from './${environmentName}.env';`);
|
|
18
|
+
return imports;
|
|
19
|
+
}
|
|
20
|
+
function generateEnvironmentSettingsDefinition(environmentName, environmentData) {
|
|
21
|
+
const environmentNameResult = z.string().nonempty().safeParse(environmentName);
|
|
22
|
+
if (!environmentNameResult.success) throw new Error(`Validation failed for environment name:\n${z.prettifyError(environmentNameResult.error)}`);
|
|
23
|
+
const result = EnvironmentSettingsSchema.safeParse(environmentData);
|
|
24
|
+
if (!result.success) throw new Error(`Validation failed for environment settings:\n${z.prettifyError(result.error)}`);
|
|
25
|
+
const parsed = result.data;
|
|
26
|
+
const { sourceFile, configObject } = createFactoryDefinition({
|
|
27
|
+
importName: "registerEnvironmentSettings",
|
|
28
|
+
variableName: environmentNameResult.data
|
|
29
|
+
});
|
|
30
|
+
const hasCredentialStoreType = needsCredentialStoreType(parsed);
|
|
31
|
+
if (hasCredentialStoreType) sourceFile.addImportDeclaration({
|
|
32
|
+
namedImports: ["CredentialStoreType"],
|
|
33
|
+
moduleSpecifier: "@inkeep/agents-core"
|
|
34
|
+
});
|
|
35
|
+
addCredentialsProperty(configObject, parsed.credentials, hasCredentialStoreType);
|
|
36
|
+
return sourceFile;
|
|
37
|
+
}
|
|
38
|
+
function generateEnvironmentIndexDefinition(environments) {
|
|
39
|
+
const result = EnvironmentIndexSchema.safeParse(environments);
|
|
40
|
+
if (!result.success) throw new Error(`Validation failed for environments index:\n${z.prettifyError(result.error)}`);
|
|
41
|
+
const { sourceFile, configObject } = createFactoryDefinition({
|
|
42
|
+
importName: "createEnvironmentSettings",
|
|
43
|
+
variableName: "envSettings"
|
|
44
|
+
});
|
|
45
|
+
for (const environmentName of result.data) sourceFile.addImportDeclaration({
|
|
46
|
+
namedImports: [environmentName],
|
|
47
|
+
moduleSpecifier: `./${environmentName}.env`
|
|
48
|
+
});
|
|
49
|
+
for (const environmentName of result.data) configObject.addShorthandPropertyAssignment({ name: environmentName });
|
|
50
|
+
return sourceFile;
|
|
51
|
+
}
|
|
52
|
+
function generateEnvironmentSettingsFile(environmentName, environmentData) {
|
|
53
|
+
return generateEnvironmentSettingsDefinition(environmentName, environmentData);
|
|
54
|
+
}
|
|
55
|
+
function generateEnvironmentIndexFile(environments) {
|
|
56
|
+
return generateEnvironmentIndexDefinition(environments);
|
|
57
|
+
}
|
|
58
|
+
function needsCredentialStoreType(environmentData) {
|
|
59
|
+
if (!isPlainObject(environmentData.credentials)) return false;
|
|
60
|
+
return Object.values(environmentData.credentials).some((credential) => isPlainObject(credential) && typeof credential.type === "string" && [
|
|
61
|
+
"memory",
|
|
62
|
+
"env",
|
|
63
|
+
"keychain"
|
|
64
|
+
].includes(credential.type));
|
|
65
|
+
}
|
|
66
|
+
function addCredentialsProperty(configObject, credentials, hasCredentialStoreType) {
|
|
67
|
+
if (!isPlainObject(credentials) || !Object.keys(credentials).length) {
|
|
68
|
+
configObject.addPropertyAssignment({
|
|
69
|
+
name: "credentials",
|
|
70
|
+
initializer: "{}"
|
|
71
|
+
});
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const credentialsObject = configObject.addPropertyAssignment({
|
|
75
|
+
name: "credentials",
|
|
76
|
+
initializer: "{}"
|
|
77
|
+
}).getInitializerIfKindOrThrow(SyntaxKind.ObjectLiteralExpression);
|
|
78
|
+
for (const [credentialKey, credentialValue] of Object.entries(credentials)) {
|
|
79
|
+
if (!isPlainObject(credentialValue)) continue;
|
|
80
|
+
writeCredential(credentialsObject.addPropertyAssignment({
|
|
81
|
+
name: formatPropertyName(credentialKey),
|
|
82
|
+
initializer: "{}"
|
|
83
|
+
}).getInitializerIfKindOrThrow(SyntaxKind.ObjectLiteralExpression), credentialValue, hasCredentialStoreType);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function writeCredential(credentialObject, credentialData, hasCredentialStoreType) {
|
|
87
|
+
if (credentialData.id !== void 0) addStringProperty(credentialObject, "id", credentialData.id);
|
|
88
|
+
if (credentialData.name !== void 0 && credentialData.name !== null) addStringProperty(credentialObject, "name", credentialData.name);
|
|
89
|
+
if (credentialData.type !== void 0) if (hasCredentialStoreType && typeof credentialData.type === "string" && [
|
|
90
|
+
"memory",
|
|
91
|
+
"env",
|
|
92
|
+
"keychain"
|
|
93
|
+
].includes(credentialData.type)) credentialObject.addPropertyAssignment({
|
|
94
|
+
name: "type",
|
|
95
|
+
initializer: `CredentialStoreType.${credentialData.type}`
|
|
96
|
+
});
|
|
97
|
+
else credentialObject.addPropertyAssignment({
|
|
98
|
+
name: "type",
|
|
99
|
+
initializer: formatInlineLiteral(credentialData.type)
|
|
100
|
+
});
|
|
101
|
+
if (credentialData.credentialStoreId !== void 0) addStringProperty(credentialObject, "credentialStoreId", credentialData.credentialStoreId);
|
|
102
|
+
if (credentialData.description !== void 0 && credentialData.description !== null) addStringProperty(credentialObject, "description", credentialData.description);
|
|
103
|
+
addRetrievalParams(credentialObject, credentialData.retrievalParams);
|
|
104
|
+
}
|
|
105
|
+
function addRetrievalParams(credentialObject, retrievalParams) {
|
|
106
|
+
if (!isPlainObject(retrievalParams)) return;
|
|
107
|
+
const retrievalParamsProperty = credentialObject.addPropertyAssignment({
|
|
108
|
+
name: "retrievalParams",
|
|
109
|
+
initializer: "{}"
|
|
110
|
+
});
|
|
111
|
+
const retrievalParamsObject = retrievalParamsProperty.getInitializerIfKindOrThrow(SyntaxKind.ObjectLiteralExpression);
|
|
112
|
+
for (const [key, value] of Object.entries(retrievalParams)) {
|
|
113
|
+
if (value === void 0 || value === null) continue;
|
|
114
|
+
retrievalParamsObject.addPropertyAssignment({
|
|
115
|
+
name: formatPropertyName(key),
|
|
116
|
+
initializer: formatInlineLiteral(value)
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
if (!retrievalParamsObject.getProperties().length) retrievalParamsProperty.remove();
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
//#endregion
|
|
123
|
+
export { generateEnvironmentIndexDefinition, generateEnvironmentIndexFile, generateEnvironmentIndexImports, generateEnvironmentSettingsDefinition, generateEnvironmentSettingsFile, generateEnvironmentSettingsImports };
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { addStringProperty, createFactoryDefinition, toCamelCase } from "./utils.js";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { SyntaxKind } from "ts-morph";
|
|
4
|
+
|
|
5
|
+
//#region src/commands/pull-v4/external-agent-generator.ts
|
|
6
|
+
const ExternalAgentSchema = z.looseObject({
|
|
7
|
+
externalAgentId: z.string().nonempty(),
|
|
8
|
+
name: z.string().nonempty(),
|
|
9
|
+
description: z.string().nullable().optional(),
|
|
10
|
+
baseUrl: z.string().nonempty(),
|
|
11
|
+
credentialReference: z.union([z.string(), z.looseObject({
|
|
12
|
+
id: z.string().optional(),
|
|
13
|
+
name: z.string().optional(),
|
|
14
|
+
description: z.string().optional()
|
|
15
|
+
})]).optional()
|
|
16
|
+
});
|
|
17
|
+
function generateExternalAgentDefinition(data) {
|
|
18
|
+
const result = ExternalAgentSchema.safeParse(data);
|
|
19
|
+
if (!result.success) throw new Error(`Validation failed for external agent:\n${z.prettifyError(result.error)}`);
|
|
20
|
+
const parsed = result.data;
|
|
21
|
+
const { sourceFile, configObject } = createFactoryDefinition({
|
|
22
|
+
importName: "externalAgent",
|
|
23
|
+
variableName: toCamelCase(parsed.externalAgentId)
|
|
24
|
+
});
|
|
25
|
+
if (typeof parsed.credentialReference === "string") sourceFile.addImportDeclaration({
|
|
26
|
+
namedImports: [toCamelCase(parsed.credentialReference)],
|
|
27
|
+
moduleSpecifier: `../credentials/${parsed.credentialReference}`
|
|
28
|
+
});
|
|
29
|
+
writeExternalAgentConfig(configObject, parsed);
|
|
30
|
+
return sourceFile;
|
|
31
|
+
}
|
|
32
|
+
function writeExternalAgentConfig(configObject, data) {
|
|
33
|
+
addStringProperty(configObject, "id", data.externalAgentId);
|
|
34
|
+
addStringProperty(configObject, "name", data.name);
|
|
35
|
+
if (data.description !== null && data.description !== void 0) addStringProperty(configObject, "description", data.description);
|
|
36
|
+
else addStringProperty(configObject, "description", `External agent ${data.externalAgentId}`);
|
|
37
|
+
addStringProperty(configObject, "baseUrl", data.baseUrl);
|
|
38
|
+
if (typeof data.credentialReference === "string") {
|
|
39
|
+
configObject.addPropertyAssignment({
|
|
40
|
+
name: "credentialReference",
|
|
41
|
+
initializer: toCamelCase(data.credentialReference)
|
|
42
|
+
});
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
if (!data.credentialReference) return;
|
|
46
|
+
const credentialReferenceObject = configObject.addPropertyAssignment({
|
|
47
|
+
name: "credentialReference",
|
|
48
|
+
initializer: "{}"
|
|
49
|
+
}).getInitializerIfKindOrThrow(SyntaxKind.ObjectLiteralExpression);
|
|
50
|
+
if (data.credentialReference.id !== void 0) addStringProperty(credentialReferenceObject, "id", data.credentialReference.id);
|
|
51
|
+
if (data.credentialReference.name !== void 0) addStringProperty(credentialReferenceObject, "name", data.credentialReference.name);
|
|
52
|
+
if (data.credentialReference.description !== void 0) addStringProperty(credentialReferenceObject, "description", data.credentialReference.description);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
//#endregion
|
|
56
|
+
export { generateExternalAgentDefinition };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { addValueToObject, createFactoryDefinition, toCamelCase } from "./utils.js";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
|
|
4
|
+
//#region src/commands/pull-v4/function-tool-generator.ts
|
|
5
|
+
const FunctionToolSchema = z.looseObject({
|
|
6
|
+
functionToolId: z.string().nonempty(),
|
|
7
|
+
name: z.string().nonempty(),
|
|
8
|
+
description: z.string().optional(),
|
|
9
|
+
inputSchema: z.unknown().optional(),
|
|
10
|
+
schema: z.unknown().optional(),
|
|
11
|
+
executeCode: z.string().optional(),
|
|
12
|
+
execute: z.string().optional()
|
|
13
|
+
}).superRefine((value, context) => {
|
|
14
|
+
if (value.inputSchema === void 0 && value.schema === void 0) context.addIssue({
|
|
15
|
+
code: "custom",
|
|
16
|
+
message: "inputSchema is required",
|
|
17
|
+
path: ["inputSchema"]
|
|
18
|
+
});
|
|
19
|
+
if (value.executeCode === void 0 && value.execute === void 0) context.addIssue({
|
|
20
|
+
code: "custom",
|
|
21
|
+
message: "executeCode is required",
|
|
22
|
+
path: ["executeCode"]
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
function generateFunctionToolDefinition(data) {
|
|
26
|
+
const result = FunctionToolSchema.safeParse(data);
|
|
27
|
+
if (!result.success) throw new Error(`Validation failed for function tool:\n${z.prettifyError(result.error)}`);
|
|
28
|
+
const parsed = result.data;
|
|
29
|
+
const { sourceFile, configObject } = createFactoryDefinition({
|
|
30
|
+
importName: "functionTool",
|
|
31
|
+
variableName: toCamelCase(parsed.functionToolId)
|
|
32
|
+
});
|
|
33
|
+
writeFunctionToolConfig(configObject, parsed);
|
|
34
|
+
return sourceFile;
|
|
35
|
+
}
|
|
36
|
+
function writeFunctionToolConfig(configObject, { functionToolId, executeCode, inputSchema, schema, ...rest }) {
|
|
37
|
+
for (const [k, v] of Object.entries({
|
|
38
|
+
...rest,
|
|
39
|
+
inputSchema: inputSchema ?? schema
|
|
40
|
+
})) addValueToObject(configObject, k, v);
|
|
41
|
+
if (executeCode) configObject.addPropertyAssignment({
|
|
42
|
+
name: "execute",
|
|
43
|
+
initializer: executeCode
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
//#endregion
|
|
48
|
+
export { generateFunctionToolDefinition };
|
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
import { ManagementApiClient } from "../../../api.js";
|
|
2
|
+
import { initializeCommand } from "../../../utils/cli-pipeline.js";
|
|
3
|
+
import { performBackgroundVersionCheck } from "../../../utils/background-version-check.js";
|
|
4
|
+
import { loadProject } from "../../../utils/project-loader.js";
|
|
5
|
+
import { extractSubAgents } from "../../pull-v3/utils/component-registry.js";
|
|
6
|
+
import { introspectGenerate } from "../introspect-generator.js";
|
|
7
|
+
import { join, resolve } from "node:path";
|
|
8
|
+
import * as p from "@clack/prompts";
|
|
9
|
+
import { existsSync, mkdirSync } from "node:fs";
|
|
10
|
+
import { EventEmitter } from "node:events";
|
|
11
|
+
import { styleText } from "node:util";
|
|
12
|
+
|
|
13
|
+
//#region src/commands/pull-v4/introspect/index.ts
|
|
14
|
+
/**
|
|
15
|
+
* Pull v3 - Clean, efficient project generation
|
|
16
|
+
*
|
|
17
|
+
* Step 1: Validate and compile existing code
|
|
18
|
+
* Step 2: Compare project with DB to detect ALL changes
|
|
19
|
+
* Step 3: Classify changes as new vs modified components
|
|
20
|
+
* Step 4: Generate new components deterministically
|
|
21
|
+
* Step 5: Use LLM to correct modified components
|
|
22
|
+
*/
|
|
23
|
+
EventEmitter.defaultMaxListeners = 20;
|
|
24
|
+
/**
|
|
25
|
+
* Create project directory structure
|
|
26
|
+
*/
|
|
27
|
+
function createProjectStructure(projectRoot) {
|
|
28
|
+
mkdirSync(projectRoot, { recursive: true });
|
|
29
|
+
return {
|
|
30
|
+
projectRoot,
|
|
31
|
+
agentsDir: join(projectRoot, "agents"),
|
|
32
|
+
toolsDir: join(projectRoot, "tools"),
|
|
33
|
+
dataComponentsDir: join(projectRoot, "data-components"),
|
|
34
|
+
artifactComponentsDir: join(projectRoot, "artifact-components"),
|
|
35
|
+
statusComponentsDir: join(projectRoot, "status-components"),
|
|
36
|
+
environmentsDir: join(projectRoot, "environments"),
|
|
37
|
+
credentialsDir: join(projectRoot, "credentials"),
|
|
38
|
+
contextConfigsDir: join(projectRoot, "context-configs"),
|
|
39
|
+
externalAgentsDir: join(projectRoot, "external-agents"),
|
|
40
|
+
skillsDir: join(projectRoot, "skills")
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Enrich canDelegateTo references with component type information
|
|
45
|
+
*/
|
|
46
|
+
function enrichCanDelegateToWithTypes(project) {
|
|
47
|
+
const agentsIdSet = new Set(project.agents ? Object.keys(project.agents) : []);
|
|
48
|
+
const subAgentsIdSet = new Set(Object.keys(extractSubAgents(project)));
|
|
49
|
+
const externalAgentsIdSet = new Set(project.externalAgents ? Object.keys(project.externalAgents) : []);
|
|
50
|
+
function enrichCanDelegateToArray(canDelegateTo) {
|
|
51
|
+
return canDelegateTo.map((item) => {
|
|
52
|
+
if (typeof item !== "string") return item;
|
|
53
|
+
if (agentsIdSet.has(item)) return { agentId: item };
|
|
54
|
+
if (subAgentsIdSet.has(item)) return { subAgentId: item };
|
|
55
|
+
if (externalAgentsIdSet.has(item)) return { externalAgentId: item };
|
|
56
|
+
return item;
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
if (project.agents) {
|
|
60
|
+
for (const agentData of Object.values(project.agents)) if (agentData.subAgents) {
|
|
61
|
+
for (const subAgentData of Object.values(agentData.subAgents)) if (subAgentData.canDelegateTo) subAgentData.canDelegateTo = enrichCanDelegateToArray(subAgentData.canDelegateTo);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Main pull-v3 command
|
|
67
|
+
* @returns PullResult when in batch mode, otherwise void (exits process)
|
|
68
|
+
*/
|
|
69
|
+
async function pullV4Command(options) {
|
|
70
|
+
if (options.all) {
|
|
71
|
+
await pullAllProjects(options);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const batchMode = options._batchMode ?? false;
|
|
75
|
+
const originalLogLevel = process.env.LOG_LEVEL;
|
|
76
|
+
process.env.LOG_LEVEL = "silent";
|
|
77
|
+
const restoreLogLevel = () => {
|
|
78
|
+
if (originalLogLevel !== void 0) process.env.LOG_LEVEL = originalLogLevel;
|
|
79
|
+
else delete process.env.LOG_LEVEL;
|
|
80
|
+
};
|
|
81
|
+
if (!batchMode) performBackgroundVersionCheck();
|
|
82
|
+
console.log(styleText("blue", "\nInkeep Pull:"));
|
|
83
|
+
if (options.introspect) console.log(styleText("gray", " Introspect mode ⢠Complete regeneration ⢠No comparison needed"));
|
|
84
|
+
else console.log(styleText("gray", " Smart comparison ⢠Detect all changes ⢠Targeted updates"));
|
|
85
|
+
const s = p.spinner();
|
|
86
|
+
try {
|
|
87
|
+
const { config, isCI } = await initializeCommand({
|
|
88
|
+
configPath: options.config,
|
|
89
|
+
profileName: options.profile,
|
|
90
|
+
tag: options.tag,
|
|
91
|
+
showSpinner: true,
|
|
92
|
+
spinnerText: "Loading configuration...",
|
|
93
|
+
logConfig: true,
|
|
94
|
+
quiet: options.quiet
|
|
95
|
+
});
|
|
96
|
+
s.start("Detecting project...");
|
|
97
|
+
let projectDir;
|
|
98
|
+
let projectId;
|
|
99
|
+
let localProjectForId = null;
|
|
100
|
+
const currentDir = process.cwd();
|
|
101
|
+
if (existsSync(join(currentDir, "index.ts"))) {
|
|
102
|
+
projectDir = currentDir;
|
|
103
|
+
s.start("Loading local project...");
|
|
104
|
+
try {
|
|
105
|
+
localProjectForId = await loadProject(projectDir);
|
|
106
|
+
const localProjectId = localProjectForId.getId();
|
|
107
|
+
if (options.project) {
|
|
108
|
+
if (localProjectId !== options.project) {
|
|
109
|
+
s.stop("Project ID mismatch");
|
|
110
|
+
console.error(styleText("red", `Local project ID "${localProjectId}" doesn't match --project "${options.project}"`));
|
|
111
|
+
console.error(styleText("yellow", "Either remove --project flag or ensure it matches the local project ID"));
|
|
112
|
+
if (batchMode) return {
|
|
113
|
+
success: false,
|
|
114
|
+
error: "Project ID mismatch"
|
|
115
|
+
};
|
|
116
|
+
process.exit(1);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
projectId = localProjectId;
|
|
120
|
+
s.stop(`Using local project: ${projectId}`);
|
|
121
|
+
} catch (error) {
|
|
122
|
+
s.stop("Failed to load local project");
|
|
123
|
+
throw new Error(`Could not load local project: ${error instanceof Error ? error.message : String(error)}`);
|
|
124
|
+
}
|
|
125
|
+
} else {
|
|
126
|
+
if (!options.project) {
|
|
127
|
+
s.stop("No index.ts found in current directory");
|
|
128
|
+
console.error(styleText("yellow", "Please run this command from a directory containing index.ts or use --project <project-id>"));
|
|
129
|
+
if (batchMode) return {
|
|
130
|
+
success: false,
|
|
131
|
+
error: "No index.ts found and no --project specified"
|
|
132
|
+
};
|
|
133
|
+
process.exit(1);
|
|
134
|
+
}
|
|
135
|
+
const projectPath = resolve(currentDir, options.project);
|
|
136
|
+
if (existsSync(join(projectPath, "index.ts"))) {
|
|
137
|
+
projectDir = projectPath;
|
|
138
|
+
s.start("Loading project from specified path...");
|
|
139
|
+
try {
|
|
140
|
+
localProjectForId = await loadProject(projectDir);
|
|
141
|
+
projectId = localProjectForId.getId();
|
|
142
|
+
s.stop(`Using project from path: ${projectId}`);
|
|
143
|
+
} catch (error) {
|
|
144
|
+
s.stop("Failed to load project from path");
|
|
145
|
+
throw new Error(`Could not load project from ${projectPath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
146
|
+
}
|
|
147
|
+
} else {
|
|
148
|
+
projectId = options.project;
|
|
149
|
+
projectDir = join(currentDir, projectId);
|
|
150
|
+
s.stop(`Creating new project directory: ${projectDir}`);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
s.start(`Fetching project: ${projectId}`);
|
|
154
|
+
const remoteProject = await (await ManagementApiClient.create(config.agentsApiUrl, options.config, config.tenantId, projectId, isCI, config.agentsApiKey)).getFullProject(projectId);
|
|
155
|
+
if (options.debug && remoteProject.functions) {
|
|
156
|
+
console.log(styleText("gray", " š Project-level functions from API:"), Object.keys(remoteProject.functions));
|
|
157
|
+
Object.entries(remoteProject.functions).forEach(([id, data]) => {
|
|
158
|
+
console.log(styleText("gray", ` ${id}: has name=${!!data.name}, has description=${!!data.description}`));
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
if (remoteProject.agents) for (const [agentId, agentData] of Object.entries(remoteProject.agents)) {
|
|
162
|
+
if (agentData.functionTools) {
|
|
163
|
+
remoteProject.functionTools = remoteProject.functionTools || {};
|
|
164
|
+
Object.assign(remoteProject.functionTools, agentData.functionTools);
|
|
165
|
+
if (options.debug) console.log(styleText("gray", ` Hoisted functionTools from agent ${agentId}: ${Object.keys(agentData.functionTools).join(", ")}`));
|
|
166
|
+
}
|
|
167
|
+
if (agentData.functions) {
|
|
168
|
+
remoteProject.functions = remoteProject.functions || {};
|
|
169
|
+
Object.entries(agentData.functions).forEach(([funcId, funcData]) => {
|
|
170
|
+
if (!remoteProject.functions[funcId]) remoteProject.functions[funcId] = {
|
|
171
|
+
id: funcData.id,
|
|
172
|
+
inputSchema: funcData.inputSchema,
|
|
173
|
+
executeCode: funcData.executeCode,
|
|
174
|
+
dependencies: funcData.dependencies
|
|
175
|
+
};
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
if (remoteProject.agents && remoteProject.tools) {
|
|
180
|
+
const projectToolIds = Object.keys(remoteProject.tools);
|
|
181
|
+
for (const agentData of Object.values(remoteProject.agents)) if (agentData.tools) {
|
|
182
|
+
const agentSpecificTools = Object.fromEntries(Object.entries(agentData.tools).filter(([toolId]) => !projectToolIds.includes(toolId)));
|
|
183
|
+
if (Object.keys(agentSpecificTools).length > 0) agentData.tools = agentSpecificTools;
|
|
184
|
+
else delete agentData.tools;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
enrichCanDelegateToWithTypes(remoteProject);
|
|
188
|
+
s.message("Project data fetched");
|
|
189
|
+
if (options.json) {
|
|
190
|
+
console.log(JSON.stringify(remoteProject, null, 2));
|
|
191
|
+
restoreLogLevel();
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
const paths = createProjectStructure(projectDir);
|
|
195
|
+
if (remoteProject.skills && Object.keys(remoteProject.skills).length) {
|
|
196
|
+
const { generateSkills } = await import("../../pull-v3/components/skill-generator.js");
|
|
197
|
+
await generateSkills(remoteProject.skills, paths.skillsDir);
|
|
198
|
+
}
|
|
199
|
+
s.start("Starting generating files...");
|
|
200
|
+
await introspectGenerate({
|
|
201
|
+
project: remoteProject,
|
|
202
|
+
paths,
|
|
203
|
+
debug: options.debug
|
|
204
|
+
});
|
|
205
|
+
s.stop("All files generated");
|
|
206
|
+
console.log(styleText("green", "\nProject synced successfully!"));
|
|
207
|
+
console.log(styleText("gray", ` Location: ${paths.projectRoot}`));
|
|
208
|
+
console.log(styleText("gray", ` Environment: ${options.env || "development"}`));
|
|
209
|
+
console.log(styleText("yellow", "ā ļø If you encounter broken code after running `inkeep pull`, please report it at https://github.com/inkeep/agents/issues."));
|
|
210
|
+
restoreLogLevel();
|
|
211
|
+
if (batchMode) return { success: true };
|
|
212
|
+
process.exit(0);
|
|
213
|
+
} catch (error) {
|
|
214
|
+
const message = error instanceof Error ? error.stack : String(error);
|
|
215
|
+
s.stop();
|
|
216
|
+
console.error(styleText("red", `\nError: ${message}`));
|
|
217
|
+
if (options.debug && error instanceof Error) console.error(styleText("red", error.stack || ""));
|
|
218
|
+
restoreLogLevel();
|
|
219
|
+
if (batchMode) return {
|
|
220
|
+
success: false,
|
|
221
|
+
error: message
|
|
222
|
+
};
|
|
223
|
+
process.exit(1);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Pull all projects for the current tenant
|
|
228
|
+
* Uses smart comparison with LLM merging for existing projects, introspect for new projects
|
|
229
|
+
*/
|
|
230
|
+
async function pullAllProjects(options) {
|
|
231
|
+
console.log(styleText("blue", "\nš Batch Pull: Sequential processing with smart comparison\n"));
|
|
232
|
+
console.log(styleText("gray", " ⢠Existing projects: Smart comparison + LLM merging + confirmation prompts"));
|
|
233
|
+
console.log(styleText("gray", " ⢠New projects: Fresh generation with introspect mode\n"));
|
|
234
|
+
performBackgroundVersionCheck();
|
|
235
|
+
const { config, isCI } = await initializeCommand({
|
|
236
|
+
configPath: options.config,
|
|
237
|
+
profileName: options.profile,
|
|
238
|
+
tag: options.tag,
|
|
239
|
+
showSpinner: true,
|
|
240
|
+
spinnerText: "Loading configuration...",
|
|
241
|
+
logConfig: true,
|
|
242
|
+
quiet: options.quiet
|
|
243
|
+
});
|
|
244
|
+
const s = p.spinner();
|
|
245
|
+
try {
|
|
246
|
+
s.start("Fetching project list from API...");
|
|
247
|
+
const projects = await (await ManagementApiClient.create(config.agentsApiUrl, options.config, config.tenantId, void 0, isCI, config.agentsApiKey)).listAllProjects();
|
|
248
|
+
s.stop(`Found ${projects.length} project(s)`);
|
|
249
|
+
if (!projects.length) {
|
|
250
|
+
console.log(styleText("yellow", "No projects found for this tenant."));
|
|
251
|
+
process.exit(0);
|
|
252
|
+
}
|
|
253
|
+
const existingProjects = [];
|
|
254
|
+
const newProjects = [];
|
|
255
|
+
for (const project of projects) if (existsSync(join(join(process.cwd(), project.id), "index.ts"))) existingProjects.push(project);
|
|
256
|
+
else newProjects.push(project);
|
|
257
|
+
console.log(styleText("gray", "\nProjects to pull:\n"));
|
|
258
|
+
if (existingProjects.length > 0) {
|
|
259
|
+
console.log(styleText("cyan", " Existing (smart comparison):"));
|
|
260
|
+
for (const project of existingProjects) console.log(styleText("gray", ` ⢠${project.name || project.id} (${project.id})`));
|
|
261
|
+
}
|
|
262
|
+
if (newProjects.length > 0) {
|
|
263
|
+
console.log(styleText("cyan", " New (introspect):"));
|
|
264
|
+
for (const project of newProjects) console.log(styleText("gray", ` ⢠${project.name || project.id} (${project.id})`));
|
|
265
|
+
}
|
|
266
|
+
console.log();
|
|
267
|
+
const results = [];
|
|
268
|
+
const total = projects.length;
|
|
269
|
+
for (let i = 0; i < projects.length; i++) {
|
|
270
|
+
const project = projects[i];
|
|
271
|
+
const progress = `[${i + 1}/${total}]`;
|
|
272
|
+
console.log(styleText("cyan", `\n${"ā".repeat(60)}`));
|
|
273
|
+
console.log(styleText("cyan", `${progress} Pulling ${project.name || project.id}...`));
|
|
274
|
+
const result = await pullSingleProject(project.id, project.name, options, config, isCI);
|
|
275
|
+
results.push(result);
|
|
276
|
+
if (result.success) console.log(styleText("green", `\n ā ${result.projectName || result.projectId} ā ${result.targetDir}`));
|
|
277
|
+
else console.log(styleText("red", `\n ā ${result.projectName || result.projectId}: ${result.error}`));
|
|
278
|
+
}
|
|
279
|
+
const succeeded = results.filter((r) => r.success).length;
|
|
280
|
+
const failed = results.filter((r) => !r.success).length;
|
|
281
|
+
console.log(styleText("cyan", `\n${"ā".repeat(60)}`));
|
|
282
|
+
console.log(styleText("cyan", "š Batch Pull Summary:"));
|
|
283
|
+
console.log(styleText("green", ` ā Succeeded: ${succeeded}`));
|
|
284
|
+
if (failed > 0) {
|
|
285
|
+
console.log(styleText("red", ` ā Failed: ${failed}`));
|
|
286
|
+
console.log(styleText("red", "\nFailed projects:"));
|
|
287
|
+
for (const result of results) if (!result.success) console.log(styleText("red", ` ⢠${result.projectId}: ${result.error}`));
|
|
288
|
+
}
|
|
289
|
+
process.exit(failed > 0 ? 1 : 0);
|
|
290
|
+
} catch (error) {
|
|
291
|
+
s.stop();
|
|
292
|
+
console.error(styleText("red", `\nError: ${error instanceof Error ? error.message : String(error)}`));
|
|
293
|
+
process.exit(1);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Pull a single project (used by batch operations)
|
|
298
|
+
* Uses smart comparison flow for existing projects, introspect for new projects
|
|
299
|
+
*/
|
|
300
|
+
async function pullSingleProject(projectId, projectName, options, config, isCI) {
|
|
301
|
+
const targetDir = join(process.cwd(), projectId);
|
|
302
|
+
const hasExistingProject = existsSync(join(targetDir, "index.ts"));
|
|
303
|
+
try {
|
|
304
|
+
if (hasExistingProject) {
|
|
305
|
+
console.log(styleText("gray", ` š Existing project found - using smart comparison mode`));
|
|
306
|
+
const originalDir = process.cwd();
|
|
307
|
+
process.chdir(targetDir);
|
|
308
|
+
try {
|
|
309
|
+
const result = await pullV4Command({
|
|
310
|
+
...options,
|
|
311
|
+
project: projectId,
|
|
312
|
+
all: false,
|
|
313
|
+
_batchMode: true
|
|
314
|
+
});
|
|
315
|
+
process.chdir(originalDir);
|
|
316
|
+
if (result && typeof result === "object") return {
|
|
317
|
+
projectId,
|
|
318
|
+
projectName,
|
|
319
|
+
targetDir,
|
|
320
|
+
success: result.success,
|
|
321
|
+
error: result.error
|
|
322
|
+
};
|
|
323
|
+
return {
|
|
324
|
+
projectId,
|
|
325
|
+
projectName,
|
|
326
|
+
targetDir,
|
|
327
|
+
success: true
|
|
328
|
+
};
|
|
329
|
+
} catch (error) {
|
|
330
|
+
process.chdir(originalDir);
|
|
331
|
+
throw error;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
console.log(styleText("gray", ` š New project - using introspect mode`));
|
|
335
|
+
const originalLogLevel = process.env.LOG_LEVEL;
|
|
336
|
+
process.env.LOG_LEVEL = "silent";
|
|
337
|
+
const restoreLogLevel = () => {
|
|
338
|
+
if (originalLogLevel !== void 0) process.env.LOG_LEVEL = originalLogLevel;
|
|
339
|
+
else delete process.env.LOG_LEVEL;
|
|
340
|
+
};
|
|
341
|
+
const remoteProject = await (await ManagementApiClient.create(config.agentsApiUrl, options.config, config.tenantId, projectId, isCI, config.agentsApiKey)).getFullProject(projectId);
|
|
342
|
+
await introspectGenerate({
|
|
343
|
+
project: remoteProject,
|
|
344
|
+
paths: createProjectStructure(targetDir)
|
|
345
|
+
});
|
|
346
|
+
restoreLogLevel();
|
|
347
|
+
return {
|
|
348
|
+
projectId,
|
|
349
|
+
projectName: projectName || remoteProject.name,
|
|
350
|
+
targetDir,
|
|
351
|
+
success: true
|
|
352
|
+
};
|
|
353
|
+
} catch (error) {
|
|
354
|
+
return {
|
|
355
|
+
projectId,
|
|
356
|
+
projectName,
|
|
357
|
+
targetDir,
|
|
358
|
+
success: false,
|
|
359
|
+
error: error instanceof Error ? error.message : String(error)
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
//#endregion
|
|
365
|
+
export { createProjectStructure, enrichCanDelegateToWithTypes, pullV4Command };
|