@inkeep/agents-cli 0.63.1 → 0.63.2
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 +1 -1
- package/dist/commands/pull-v4/generation-types.js.map +1 -1
- package/dist/commands/pull-v4/generators/index.js +8 -6
- package/dist/commands/pull-v4/generators/index.js.map +1 -1
- package/dist/commands/pull-v4/generators/skill-generator.js +68 -0
- package/dist/commands/pull-v4/generators/skill-generator.js.map +1 -0
- package/dist/commands/pull-v4/introspect/index.js +2 -12
- package/dist/commands/pull-v4/introspect/index.js.map +1 -1
- package/dist/commands/pull-v4/introspect/test-helpers.js +2 -1
- package/dist/commands/pull-v4/introspect/test-helpers.js.map +1 -1
- package/dist/commands/pull-v4/introspect-generator.js +4 -2
- package/dist/commands/pull-v4/introspect-generator.js.map +1 -1
- package/dist/commands/pull-v4/text-file-writer.js +12 -0
- package/dist/commands/pull-v4/text-file-writer.js.map +1 -0
- package/dist/commands/pull-v4/typescript-file-writer.js +2 -3
- package/dist/commands/pull-v4/typescript-file-writer.js.map +1 -1
- package/package.json +3 -3
- package/dist/commands/pull-v4/skill.js +0 -38
- package/dist/commands/pull-v4/skill.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generation-types.js","names":[],"sources":["../../../src/commands/pull-v4/generation-types.ts"],"sourcesContent":["import type { FullProjectDefinition } from '@inkeep/agents-core';\nimport type { SourceFile } from 'ts-morph';\nimport { asRecord } from './collector-common';\nimport type { ComponentRegistry, ComponentType } from './component-registry';\nimport type { GenerationResolver } from './generation-resolver';\n\nexport interface ProjectPaths {\n projectRoot: string;\n agentsDir: string;\n toolsDir: string;\n dataComponentsDir: string;\n artifactComponentsDir: string;\n statusComponentsDir: string;\n environmentsDir: string;\n credentialsDir: string;\n contextConfigsDir: string;\n externalAgentsDir: string;\n}\n\nexport interface GenerationContext {\n project: FullProjectDefinition;\n paths: ProjectPaths;\n completeAgentIds: Set<string>;\n existingComponentRegistry?: ComponentRegistry;\n resolver: GenerationResolver;\n}\n\nexport interface GenerationRecord<TPayload> {\n id: string;\n filePath: string;\n payload: TPayload;\n}\n\nexport interface GenerationTask<TPayload> {\n type: string;\n collect: (context: GenerationContext) => GenerationRecord<TPayload>[];\n generate: (payload: TPayload) =>
|
|
1
|
+
{"version":3,"file":"generation-types.js","names":[],"sources":["../../../src/commands/pull-v4/generation-types.ts"],"sourcesContent":["import type { FullProjectDefinition } from '@inkeep/agents-core';\nimport type { SourceFile } from 'ts-morph';\nimport { asRecord } from './collector-common';\nimport type { ComponentRegistry, ComponentType } from './component-registry';\nimport type { GenerationResolver } from './generation-resolver';\n\nexport interface ProjectPaths {\n projectRoot: string;\n agentsDir: string;\n toolsDir: string;\n dataComponentsDir: string;\n artifactComponentsDir: string;\n statusComponentsDir: string;\n environmentsDir: string;\n credentialsDir: string;\n contextConfigsDir: string;\n externalAgentsDir: string;\n skillsDir: string;\n}\n\nexport interface GenerationContext {\n project: FullProjectDefinition;\n paths: ProjectPaths;\n completeAgentIds: Set<string>;\n existingComponentRegistry?: ComponentRegistry;\n resolver: GenerationResolver;\n}\n\nexport interface GenerationRecord<TPayload> {\n id: string;\n filePath: string;\n payload: TPayload;\n}\n\nexport type GenerationOutput = SourceFile | string;\n\nexport interface GenerationTask<TPayload> {\n type: string;\n collect: (context: GenerationContext) => GenerationRecord<TPayload>[];\n generate: (payload: TPayload) => GenerationOutput;\n}\n\nexport type SubAgentReferenceOverrideType =\n | 'tools'\n | 'subAgents'\n | 'agents'\n | 'externalAgents'\n | 'dataComponents'\n | 'artifactComponents';\n\nexport type SubAgentReferenceOverrides = Partial<\n Record<SubAgentReferenceOverrideType, Record<string, string>>\n>;\n\nexport type SubAgentReferencePathOverrides = Partial<\n Record<'tools' | 'subAgents' | 'agents' | 'externalAgents', Record<string, string>>\n>;\n\nexport interface SubAgentDependencyReferences {\n referenceOverrides?: SubAgentReferenceOverrides;\n referencePathOverrides?: SubAgentReferencePathOverrides;\n}\n\nexport type ProjectReferenceOverrideType =\n | 'agents'\n | 'tools'\n | 'externalAgents'\n | 'dataComponents'\n | 'artifactComponents'\n | 'credentialReferences';\n\nexport type ProjectReferenceOverrides = Partial<\n Record<ProjectReferenceOverrideType, Record<string, string>>\n>;\n\nexport type ProjectReferencePathOverrides = Partial<\n Record<ProjectReferenceOverrideType, Record<string, string>>\n>;\n\nexport interface TemplateReferenceOverride {\n name: string;\n local?: boolean;\n}\n\nexport interface ContextTemplateReferences {\n contextConfigId: string;\n contextConfigReference: TemplateReferenceOverride;\n contextConfigHeadersReference?: TemplateReferenceOverride;\n}\n\nexport interface SkippedAgent {\n id: string;\n reason: string;\n}\n\nexport function collectCompleteAgentIds(\n project: FullProjectDefinition,\n skippedAgents: SkippedAgent[]\n): Set<string> {\n const completeAgentIds = new Set<string>();\n for (const [agentId, agentData] of Object.entries(project.agents ?? {})) {\n const completeness = isAgentComplete(agentData);\n if (!completeness.complete) {\n skippedAgents.push({ id: agentId, reason: completeness.reason ?? 'incomplete' });\n continue;\n }\n completeAgentIds.add(agentId);\n }\n return completeAgentIds;\n}\n\nfunction isAgentComplete(\n agentData: unknown\n): { complete: true } | { complete: false; reason: string } {\n const data = asRecord(agentData);\n if (!data) {\n return { complete: false, reason: 'invalid agent object' };\n }\n if (!data.name || typeof data.name !== 'string') {\n return { complete: false, reason: 'missing name' };\n }\n if (!data.defaultSubAgentId || typeof data.defaultSubAgentId !== 'string') {\n return { complete: false, reason: 'missing defaultSubAgentId' };\n }\n const subAgents = asRecord(data.subAgents);\n if (!subAgents || !Object.keys(subAgents).length) {\n return { complete: false, reason: 'no sub-agents defined' };\n }\n return { complete: true };\n}\n\nexport function validateProject(project: FullProjectDefinition): void {\n if (!project || typeof project !== 'object') {\n throw new Error('Project data is required');\n }\n if (!project.id) {\n throw new Error('Project id is required');\n }\n if (!project.name) {\n throw new Error('Project name is required');\n }\n}\n\nexport function assignComponentReferenceOverrideForProject(\n registry: ComponentRegistry,\n overrides: ProjectReferenceOverrides,\n overrideType: ProjectReferenceOverrideType,\n componentId: string,\n componentType: ComponentType\n): boolean {\n const component = registry.get(componentId, componentType);\n if (!component?.name) {\n return false;\n }\n\n const overrideMap = overrides[overrideType] ?? {};\n overrideMap[componentId] = component.name;\n overrides[overrideType] = overrideMap;\n return true;\n}\n"],"mappings":";;;AA+FA,SAAgB,wBACd,SACA,eACa;CACb,MAAM,mCAAmB,IAAI,KAAa;AAC1C,MAAK,MAAM,CAAC,SAAS,cAAc,OAAO,QAAQ,QAAQ,UAAU,EAAE,CAAC,EAAE;EACvE,MAAM,eAAe,gBAAgB,UAAU;AAC/C,MAAI,CAAC,aAAa,UAAU;AAC1B,iBAAc,KAAK;IAAE,IAAI;IAAS,QAAQ,aAAa,UAAU;IAAc,CAAC;AAChF;;AAEF,mBAAiB,IAAI,QAAQ;;AAE/B,QAAO;;AAGT,SAAS,gBACP,WAC0D;CAC1D,MAAM,OAAO,SAAS,UAAU;AAChC,KAAI,CAAC,KACH,QAAO;EAAE,UAAU;EAAO,QAAQ;EAAwB;AAE5D,KAAI,CAAC,KAAK,QAAQ,OAAO,KAAK,SAAS,SACrC,QAAO;EAAE,UAAU;EAAO,QAAQ;EAAgB;AAEpD,KAAI,CAAC,KAAK,qBAAqB,OAAO,KAAK,sBAAsB,SAC/D,QAAO;EAAE,UAAU;EAAO,QAAQ;EAA6B;CAEjE,MAAM,YAAY,SAAS,KAAK,UAAU;AAC1C,KAAI,CAAC,aAAa,CAAC,OAAO,KAAK,UAAU,CAAC,OACxC,QAAO;EAAE,UAAU;EAAO,QAAQ;EAAyB;AAE7D,QAAO,EAAE,UAAU,MAAM;;AAG3B,SAAgB,gBAAgB,SAAsC;AACpE,KAAI,CAAC,WAAW,OAAO,YAAY,SACjC,OAAM,IAAI,MAAM,2BAA2B;AAE7C,KAAI,CAAC,QAAQ,GACX,OAAM,IAAI,MAAM,yBAAyB;AAE3C,KAAI,CAAC,QAAQ,KACX,OAAM,IAAI,MAAM,2BAA2B;;AAI/C,SAAgB,2CACd,UACA,WACA,cACA,aACA,eACS;CACT,MAAM,YAAY,SAAS,IAAI,aAAa,cAAc;AAC1D,KAAI,CAAC,WAAW,KACd,QAAO;CAGT,MAAM,cAAc,UAAU,iBAAiB,EAAE;AACjD,aAAY,eAAe,UAAU;AACrC,WAAU,gBAAgB;AAC1B,QAAO"}
|
|
@@ -9,9 +9,10 @@ import { task as task$8 } from "./external-agent-generator.js";
|
|
|
9
9
|
import { task as task$9 } from "./function-tool-generator.js";
|
|
10
10
|
import { task as task$10 } from "./mcp-tool-generator.js";
|
|
11
11
|
import { task as task$11 } from "./project-generator.js";
|
|
12
|
-
import { task as task$12 } from "./
|
|
13
|
-
import { task as task$13 } from "./
|
|
14
|
-
import { task as task$14 } from "./
|
|
12
|
+
import { task as task$12 } from "./skill-generator.js";
|
|
13
|
+
import { task as task$13 } from "./status-component-generator.js";
|
|
14
|
+
import { task as task$14 } from "./sub-agent-generator.js";
|
|
15
|
+
import { task as task$15 } from "./trigger-generator.js";
|
|
15
16
|
|
|
16
17
|
//#region src/commands/pull-v4/generators/index.ts
|
|
17
18
|
const generationTasks = {
|
|
@@ -26,9 +27,10 @@ const generationTasks = {
|
|
|
26
27
|
"./function-tool-generator.ts": task$9,
|
|
27
28
|
"./mcp-tool-generator.ts": task$10,
|
|
28
29
|
"./project-generator.ts": task$11,
|
|
29
|
-
"./
|
|
30
|
-
"./
|
|
31
|
-
"./
|
|
30
|
+
"./skill-generator.ts": task$12,
|
|
31
|
+
"./status-component-generator.ts": task$13,
|
|
32
|
+
"./sub-agent-generator.ts": task$14,
|
|
33
|
+
"./trigger-generator.ts": task$15
|
|
32
34
|
};
|
|
33
35
|
|
|
34
36
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../../src/commands/pull-v4/generators/index.ts"],"sourcesContent":["import type { GenerationTask } from '../generation-types';\n\nexport const generationTasks: Record<\n `./${string}-generator.ts`,\n GenerationTask<unknown>\n> = import.meta\n // @ts-expect-error -- https://vite.dev/guide/features#named-imports\n .glob('./*-generator.ts', {\n import: 'task',\n eager: true,\n });\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../../src/commands/pull-v4/generators/index.ts"],"sourcesContent":["import type { GenerationTask } from '../generation-types';\n\nexport const generationTasks: Record<\n `./${string}-generator.ts`,\n GenerationTask<unknown>\n> = import.meta\n // @ts-expect-error -- https://vite.dev/guide/features#named-imports\n .glob('./*-generator.ts', {\n import: 'task',\n eager: true,\n });\n"],"mappings":";;;;;;;;;;;;;;;;;AAEA,MAAa,kBAGT;;;;;;;;;;;;;;;;CAKA"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { validateGeneratorInput } from "../simple-factory-generator.js";
|
|
2
|
+
import { SKILL_ENTRY_FILE_PATH, SkillWithFilesApiSelectSchema, serializeSkillToMarkdown } from "@inkeep/agents-core";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import { dirname, join } from "node:path";
|
|
5
|
+
|
|
6
|
+
//#region src/commands/pull-v4/generators/skill-generator.ts
|
|
7
|
+
const MySchema = SkillWithFilesApiSelectSchema.omit({
|
|
8
|
+
id: true,
|
|
9
|
+
createdAt: true,
|
|
10
|
+
updatedAt: true
|
|
11
|
+
});
|
|
12
|
+
const SkillSchema = z.strictObject({
|
|
13
|
+
...MySchema.shape,
|
|
14
|
+
metadata: MySchema.shape.metadata.transform((v) => Object.keys(v ?? {}).length ? v : void 0).optional(),
|
|
15
|
+
files: z.array(MySchema.shape.files.element.omit({
|
|
16
|
+
createdAt: true,
|
|
17
|
+
updatedAt: true,
|
|
18
|
+
skillId: true,
|
|
19
|
+
id: true
|
|
20
|
+
}))
|
|
21
|
+
});
|
|
22
|
+
function parseSkillInput({ id, createdAt, updatedAt, ...data }) {
|
|
23
|
+
return validateGeneratorInput(data, {
|
|
24
|
+
schema: SkillSchema,
|
|
25
|
+
errorLabel: "skill"
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
function generateSkillDefinition({ id, createdAt, updatedAt, ...data }) {
|
|
29
|
+
const { files: _files, ...result } = parseSkillInput({
|
|
30
|
+
id,
|
|
31
|
+
createdAt,
|
|
32
|
+
updatedAt,
|
|
33
|
+
...data
|
|
34
|
+
});
|
|
35
|
+
return serializeSkillToMarkdown(result);
|
|
36
|
+
}
|
|
37
|
+
function generateSkillFiles(data) {
|
|
38
|
+
const parsed = parseSkillInput(data);
|
|
39
|
+
if (!parsed.files.length) return [{
|
|
40
|
+
filePath: SKILL_ENTRY_FILE_PATH,
|
|
41
|
+
content: serializeSkillToMarkdown(parsed)
|
|
42
|
+
}];
|
|
43
|
+
return parsed.files.map((file) => ({
|
|
44
|
+
filePath: file.filePath,
|
|
45
|
+
content: file.content
|
|
46
|
+
}));
|
|
47
|
+
}
|
|
48
|
+
const task = {
|
|
49
|
+
type: "skill",
|
|
50
|
+
collect(ctx) {
|
|
51
|
+
return Object.entries(ctx.project.skills ?? {}).flatMap(([skillId, payload]) => {
|
|
52
|
+
const entryPath = join(ctx.paths.skillsDir, skillId, SKILL_ENTRY_FILE_PATH);
|
|
53
|
+
const skillDir = dirname(ctx.resolver.resolveOutputFilePath("skills", skillId, entryPath));
|
|
54
|
+
return generateSkillFiles(payload).map((file) => ({
|
|
55
|
+
id: `${skillId}/${file.filePath}`,
|
|
56
|
+
filePath: join(skillDir, file.filePath),
|
|
57
|
+
payload: file
|
|
58
|
+
}));
|
|
59
|
+
});
|
|
60
|
+
},
|
|
61
|
+
generate(payload) {
|
|
62
|
+
return payload.content;
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
//#endregion
|
|
67
|
+
export { generateSkillDefinition, generateSkillFiles, task };
|
|
68
|
+
//# sourceMappingURL=skill-generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-generator.js","names":[],"sources":["../../../../src/commands/pull-v4/generators/skill-generator.ts"],"sourcesContent":["import { dirname, join } from 'node:path';\nimport {\n SKILL_ENTRY_FILE_PATH,\n type SkillFileApiInsert,\n SkillWithFilesApiSelectSchema,\n serializeSkillToMarkdown,\n} from '@inkeep/agents-core';\nimport { z } from 'zod';\nimport type { GenerationTask } from '../generation-types';\nimport { validateGeneratorInput } from '../simple-factory-generator';\n\nconst MySchema = SkillWithFilesApiSelectSchema.omit({\n id: true,\n createdAt: true,\n updatedAt: true,\n});\n\nconst SkillSchema = z.strictObject({\n ...MySchema.shape,\n metadata: MySchema.shape.metadata\n .transform((v) => (Object.keys(v ?? {}).length ? v : undefined))\n .optional(),\n files: z.array(\n MySchema.shape.files.element.omit({\n createdAt: true,\n updatedAt: true,\n skillId: true,\n id: true,\n })\n ),\n});\n\ntype SkillInput = z.input<typeof SkillSchema>;\n\nfunction parseSkillInput({\n id,\n createdAt,\n updatedAt,\n ...data\n}: SkillInput & Record<string, unknown>) {\n return validateGeneratorInput(data, { schema: SkillSchema, errorLabel: 'skill' });\n}\n\nexport function generateSkillDefinition({\n id,\n createdAt,\n updatedAt,\n ...data\n}: SkillInput & Record<string, unknown>): string {\n const { files: _files, ...result } = parseSkillInput({ id, createdAt, updatedAt, ...data });\n\n return serializeSkillToMarkdown(result);\n}\n\nexport function generateSkillFiles(\n data: SkillInput & Record<string, unknown>\n): SkillFileApiInsert[] {\n const parsed = parseSkillInput(data);\n\n if (!parsed.files.length) {\n return [\n {\n filePath: SKILL_ENTRY_FILE_PATH,\n content: serializeSkillToMarkdown(parsed),\n },\n ];\n }\n\n return parsed.files.map((file) => ({\n filePath: file.filePath,\n content: file.content,\n }));\n}\n\nexport const task: GenerationTask<SkillFileApiInsert> = {\n type: 'skill',\n collect(ctx) {\n return Object.entries(ctx.project.skills ?? {}).flatMap(([skillId, payload]) => {\n const entryPath = join(ctx.paths.skillsDir, skillId, SKILL_ENTRY_FILE_PATH);\n const skillEntryFilePath = ctx.resolver.resolveOutputFilePath('skills', skillId, entryPath);\n const skillDir = dirname(skillEntryFilePath);\n\n return generateSkillFiles(payload).map((file) => ({\n id: `${skillId}/${file.filePath}`,\n filePath: join(skillDir, file.filePath),\n payload: file,\n }));\n });\n },\n generate(payload) {\n return payload.content;\n },\n};\n"],"mappings":";;;;;;AAWA,MAAM,WAAW,8BAA8B,KAAK;CAClD,IAAI;CACJ,WAAW;CACX,WAAW;CACZ,CAAC;AAEF,MAAM,cAAc,EAAE,aAAa;CACjC,GAAG,SAAS;CACZ,UAAU,SAAS,MAAM,SACtB,WAAW,MAAO,OAAO,KAAK,KAAK,EAAE,CAAC,CAAC,SAAS,IAAI,OAAW,CAC/D,UAAU;CACb,OAAO,EAAE,MACP,SAAS,MAAM,MAAM,QAAQ,KAAK;EAChC,WAAW;EACX,WAAW;EACX,SAAS;EACT,IAAI;EACL,CAAC,CACH;CACF,CAAC;AAIF,SAAS,gBAAgB,EACvB,IACA,WACA,WACA,GAAG,QACoC;AACvC,QAAO,uBAAuB,MAAM;EAAE,QAAQ;EAAa,YAAY;EAAS,CAAC;;AAGnF,SAAgB,wBAAwB,EACtC,IACA,WACA,WACA,GAAG,QAC4C;CAC/C,MAAM,EAAE,OAAO,QAAQ,GAAG,WAAW,gBAAgB;EAAE;EAAI;EAAW;EAAW,GAAG;EAAM,CAAC;AAE3F,QAAO,yBAAyB,OAAO;;AAGzC,SAAgB,mBACd,MACsB;CACtB,MAAM,SAAS,gBAAgB,KAAK;AAEpC,KAAI,CAAC,OAAO,MAAM,OAChB,QAAO,CACL;EACE,UAAU;EACV,SAAS,yBAAyB,OAAO;EAC1C,CACF;AAGH,QAAO,OAAO,MAAM,KAAK,UAAU;EACjC,UAAU,KAAK;EACf,SAAS,KAAK;EACf,EAAE;;AAGL,MAAa,OAA2C;CACtD,MAAM;CACN,QAAQ,KAAK;AACX,SAAO,OAAO,QAAQ,IAAI,QAAQ,UAAU,EAAE,CAAC,CAAC,SAAS,CAAC,SAAS,aAAa;GAC9E,MAAM,YAAY,KAAK,IAAI,MAAM,WAAW,SAAS,sBAAsB;GAE3E,MAAM,WAAW,QADU,IAAI,SAAS,sBAAsB,UAAU,SAAS,UAAU,CAC/C;AAE5C,UAAO,mBAAmB,QAAQ,CAAC,KAAK,UAAU;IAChD,IAAI,GAAG,QAAQ,GAAG,KAAK;IACvB,UAAU,KAAK,UAAU,KAAK,SAAS;IACvC,SAAS;IACV,EAAE;IACH;;CAEJ,SAAS,SAAS;AAChB,SAAO,QAAQ;;CAElB"}
|
|
@@ -78,8 +78,7 @@ async function pullV4Command(options) {
|
|
|
78
78
|
};
|
|
79
79
|
if (!batchMode) performBackgroundVersionCheck();
|
|
80
80
|
console.log(styleText("blue", "\nInkeep Pull:"));
|
|
81
|
-
|
|
82
|
-
else console.log(styleText("gray", " Smart comparison • Detect all changes • Targeted updates"));
|
|
81
|
+
console.log(styleText("gray", " Smart comparison • Detect all changes • Targeted updates"));
|
|
83
82
|
try {
|
|
84
83
|
const { config, isCI } = await initializeCommand({
|
|
85
84
|
configPath: options.config,
|
|
@@ -234,7 +233,6 @@ async function pullV4Command(options) {
|
|
|
234
233
|
return;
|
|
235
234
|
}
|
|
236
235
|
const paths = createProjectStructure(projectDir);
|
|
237
|
-
await generateProjectSkillsIfPresent(remoteProject, paths.skillsDir);
|
|
238
236
|
console.log(styleText("gray", "Generating files..."));
|
|
239
237
|
await introspectGenerate({
|
|
240
238
|
project: remoteProject,
|
|
@@ -384,11 +382,9 @@ async function pullSingleProject(projectId, projectName, options, config, isCI)
|
|
|
384
382
|
else delete process.env.LOG_LEVEL;
|
|
385
383
|
};
|
|
386
384
|
const remoteProject = await (await ManagementApiClient.create(config.agentsApiUrl, options.config, config.tenantId, projectId, isCI, config.agentsApiKey)).getFullProject(projectId);
|
|
387
|
-
const paths = createProjectStructure(targetDir);
|
|
388
|
-
await generateProjectSkillsIfPresent(remoteProject, paths.skillsDir);
|
|
389
385
|
await introspectGenerate({
|
|
390
386
|
project: remoteProject,
|
|
391
|
-
paths
|
|
387
|
+
paths: createProjectStructure(targetDir)
|
|
392
388
|
});
|
|
393
389
|
restoreLogLevel();
|
|
394
390
|
return {
|
|
@@ -407,12 +403,6 @@ async function pullSingleProject(projectId, projectName, options, config, isCI)
|
|
|
407
403
|
};
|
|
408
404
|
}
|
|
409
405
|
}
|
|
410
|
-
async function generateProjectSkillsIfPresent(remoteProject, skillsDir) {
|
|
411
|
-
const skills = remoteProject.skills ?? {};
|
|
412
|
-
if (!Object.keys(skills).length) return;
|
|
413
|
-
const { generateSkills } = await import("../skill.js");
|
|
414
|
-
await generateSkills(skills, skillsDir);
|
|
415
|
-
}
|
|
416
406
|
|
|
417
407
|
//#endregion
|
|
418
408
|
export { createProjectStructure, enrichCanDelegateToWithTypes, pullSingleProject, pullV4Command };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../../src/commands/pull-v4/introspect/index.ts"],"sourcesContent":["/**\n * Pull v3 - Clean, efficient project generation\n *\n * Step 1: Validate and compile existing code\n * Step 2: Compare project with DB to detect ALL changes\n * Step 3: Classify changes as new vs modified components\n * Step 4: Generate new components deterministically\n * Step 5: Use LLM to correct modified components\n */\n\nimport { EventEmitter } from 'node:events';\nimport { existsSync, mkdirSync } from 'node:fs';\nimport { join, resolve } from 'node:path';\nimport { styleText } from 'node:util';\nimport * as p from '@clack/prompts';\nimport type { FullProjectDefinition } from '@inkeep/agents-core';\n\n// Increase max listeners to prevent warnings during complex CLI flows\n// This is needed because @clack/prompts + multiple interactive prompts + spinners all add listeners\nEventEmitter.defaultMaxListeners = 20;\n\nimport { ManagementApiClient } from '../../../api';\nimport { performBackgroundVersionCheck } from '../../../utils/background-version-check';\nimport { initializeCommand } from '../../../utils/cli-pipeline';\nimport { loadProject } from '../../../utils/project-loader';\nimport { readProjectState, writeProjectState } from '../../../utils/state';\nimport { withLocalStateBranch } from '../../../utils/temp-branch';\nimport { introspectGenerate } from '../introspect-generator';\n\nexport interface PullV3Options {\n project?: string;\n config?: string;\n profile?: string;\n env?: string;\n json?: boolean;\n debug?: boolean;\n verbose?: boolean;\n force?: boolean;\n introspect?: boolean;\n all?: boolean;\n tag?: string;\n quiet?: boolean;\n conflictStrategy?: 'ours' | 'theirs';\n /** Internal: used for batch operations to return results instead of calling process.exit() */\n _batchMode?: boolean;\n}\n\nexport interface PullResult {\n success: boolean;\n skipped?: boolean;\n upToDate?: boolean;\n error?: string;\n}\n\ninterface BatchPullResult {\n projectId: string;\n projectName?: string;\n targetDir: string;\n success: boolean;\n error?: string;\n}\n\ninterface ProjectPaths {\n projectRoot: string;\n agentsDir: string;\n toolsDir: string;\n dataComponentsDir: string;\n artifactComponentsDir: string;\n statusComponentsDir: string;\n environmentsDir: string;\n credentialsDir: string;\n contextConfigsDir: string;\n externalAgentsDir: string;\n skillsDir: string;\n}\n\n/**\n * Create project directory structure\n */\nexport function createProjectStructure(projectRoot: string): ProjectPaths {\n mkdirSync(projectRoot, { recursive: true });\n return {\n projectRoot,\n agentsDir: join(projectRoot, 'agents'),\n toolsDir: join(projectRoot, 'tools'),\n dataComponentsDir: join(projectRoot, 'data-components'),\n artifactComponentsDir: join(projectRoot, 'artifact-components'),\n statusComponentsDir: join(projectRoot, 'status-components'),\n environmentsDir: join(projectRoot, 'environments'),\n credentialsDir: join(projectRoot, 'credentials'),\n contextConfigsDir: join(projectRoot, 'context-configs'),\n externalAgentsDir: join(projectRoot, 'external-agents'),\n skillsDir: join(projectRoot, 'skills'),\n };\n}\n\n/**\n * Enrich canDelegateTo references with component type information\n */\nexport function enrichCanDelegateToWithTypes(project: FullProjectDefinition): void {\n const { agents } = project;\n // Get all available component IDs by type\n const agentsIdSet = new Set(Object.keys(agents));\n const subAgentsIdSet = new Set(\n Object.values(agents).flatMap((agentData) => Object.keys(agentData.subAgents))\n );\n const externalAgentsIdSet = new Set(\n project.externalAgents ? Object.keys(project.externalAgents) : []\n );\n\n // Function to enrich a canDelegateTo array\n\n function enrichCanDelegateToArray(canDelegateTo: unknown[]): unknown[] {\n return canDelegateTo.map((item) => {\n // Skip if it's already an object (already has type info)\n if (typeof item !== 'string') return item;\n if (agentsIdSet.has(item)) return { agentId: item };\n if (subAgentsIdSet.has(item)) return { subAgentId: item };\n if (externalAgentsIdSet.has(item)) return { externalAgentId: item };\n return item;\n });\n }\n\n // Process all agents\n for (const { subAgents } of Object.values(project.agents)) {\n // Process subAgents within agents\n for (const subAgentData of Object.values(subAgents)) {\n if (Array.isArray(subAgentData.canDelegateTo)) {\n // @ts-expect-error\n subAgentData.canDelegateTo = enrichCanDelegateToArray(subAgentData.canDelegateTo);\n }\n }\n }\n}\n\n/**\n * Main pull v4 command\n * @returns PullResult when in batch mode, otherwise void (exits process)\n */\nexport async function pullV4Command(options: PullV3Options): Promise<PullResult | undefined> {\n // Handle --all flag for batch operations\n if (options.all) {\n await pullAllProjects(options);\n return;\n }\n\n const batchMode = options._batchMode ?? false;\n\n // Suppress SDK logging for cleaner output\n const originalLogLevel = process.env.LOG_LEVEL;\n process.env.LOG_LEVEL = 'silent';\n\n const restoreLogLevel = () => {\n if (originalLogLevel !== undefined) {\n process.env.LOG_LEVEL = originalLogLevel;\n } else {\n delete process.env.LOG_LEVEL;\n }\n };\n\n // Background version check (skip in batch mode - already done)\n if (!batchMode) {\n performBackgroundVersionCheck();\n }\n\n console.log(styleText('blue', '\\nInkeep Pull:'));\n if (options.introspect) {\n console.log(\n styleText('gray', ' Introspect mode • Complete regeneration • No comparison needed')\n );\n } else {\n console.log(styleText('gray', ' Smart comparison • Detect all changes • Targeted updates'));\n }\n\n try {\n // Step 1: Load configuration (same as push command)\n const { config, isCI } = await initializeCommand({\n configPath: options.config,\n profileName: options.profile,\n tag: options.tag,\n showSpinner: true,\n spinnerText: 'Loading configuration...',\n logConfig: true,\n quiet: options.quiet,\n });\n let projectDir: string;\n let projectId: string;\n let localProjectForId: any = null;\n\n const currentDir = process.cwd();\n const hasIndexInCurrent = existsSync(join(currentDir, 'index.ts'));\n\n if (hasIndexInCurrent) {\n // We're in a project directory\n projectDir = currentDir;\n\n try {\n localProjectForId = await loadProject(projectDir);\n const localProjectId = localProjectForId.getId();\n\n if (options.project) {\n // Validate that --project matches local project ID\n if (localProjectId !== options.project) {\n console.error(\n styleText(\n 'red',\n `Local project ID \"${localProjectId}\" doesn't match --project \"${options.project}\"`\n )\n );\n console.error(\n styleText(\n 'yellow',\n 'Either remove --project flag or ensure it matches the local project ID'\n )\n );\n if (batchMode) {\n return { success: false, error: 'Project ID mismatch' };\n }\n process.exit(1);\n }\n }\n\n projectId = localProjectId;\n console.log(styleText('green', `◆ Using local project: ${projectId}`));\n } catch (error) {\n throw new Error(\n `Could not load local project: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n } else {\n // No index.ts in current directory\n if (!options.project) {\n console.error(\n styleText(\n 'yellow',\n 'Please run this command from a directory containing index.ts or use --project <project-id>'\n )\n );\n if (batchMode) {\n return { success: false, error: 'No index.ts found and no --project specified' };\n }\n process.exit(1);\n }\n\n // Try --project as directory path first\n const projectPath = resolve(currentDir, options.project);\n const hasIndexInPath = existsSync(join(projectPath, 'index.ts'));\n\n if (hasIndexInPath) {\n // --project is a valid directory path\n projectDir = projectPath;\n try {\n localProjectForId = await loadProject(projectDir);\n projectId = localProjectForId.getId();\n console.log(styleText('green', `◆ Using project from path: ${projectId}`));\n } catch (error) {\n throw new Error(\n `Could not load project from ${projectPath}: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n } else {\n // Treat --project as project ID, create subdirectory\n projectId = options.project;\n projectDir = join(currentDir, projectId);\n console.log(styleText('green', `◆ Creating new project directory: ${projectDir}`));\n }\n }\n\n const existingState = readProjectState(projectId);\n const lastPulledHash = existingState?.lastPulledHash;\n\n if (options.debug && lastPulledHash) {\n console.log(styleText('gray', ` Last pulled hash: ${lastPulledHash}`));\n }\n\n const apiClient = await ManagementApiClient.create(\n config.agentsApiUrl,\n options.config,\n config.tenantId,\n projectId,\n isCI,\n config.agentsApiKey\n );\n\n let currentMainHash: string | undefined;\n try {\n const mainBranch = await apiClient.getBranch(projectId, 'main');\n currentMainHash = mainBranch.hash;\n } catch (error) {\n if (options.debug) {\n console.log(\n styleText(\n 'gray',\n ` Could not fetch main branch hash: ${error instanceof Error ? error.message : String(error)}`\n )\n );\n }\n // Non-fatal: if we can't get the hash, fall through to direct pull\n }\n\n if (options.debug && currentMainHash) {\n console.log(styleText('gray', ` Current main hash: ${currentMainHash}`));\n }\n\n let remoteProject: Awaited<ReturnType<typeof apiClient.getFullProject>> | undefined;\n\n if (localProjectForId && lastPulledHash) {\n const localProjectDefinition = await localProjectForId.getFullDefinition();\n\n // Merge main INTO temp branch so the temp branch gets a reconciled result\n // (main's changes + user's local changes). We then pull from the temp branch.\n // We must NOT merge temp into main — that would push local edits to main.\n remoteProject = await withLocalStateBranch({\n apiClient,\n projectId,\n fromCommit: lastPulledHash,\n localDefinition: localProjectDefinition,\n branchPrefix: 'cli-pull',\n fn: async (tempBranchName) => {\n const preview = await apiClient.mergePreview(projectId, {\n sourceBranch: 'main',\n targetBranch: tempBranchName,\n });\n\n if (preview.hasConflicts) {\n const { resolveConflictsInteractive } = await import('../merge-conflicts');\n const resolutions = await resolveConflictsInteractive(preview.conflicts, options);\n\n if (resolutions === null) {\n console.log(styleText('yellow', 'Pull cancelled'));\n return undefined;\n }\n\n await apiClient.mergeExecute(projectId, {\n sourceBranch: 'main',\n targetBranch: tempBranchName,\n sourceHash: preview.sourceHash,\n targetHash: preview.targetHash,\n resolutions,\n message: 'CLI pull: merge main into local state',\n });\n } else {\n await apiClient.mergeExecute(projectId, {\n sourceBranch: 'main',\n targetBranch: tempBranchName,\n sourceHash: preview.sourceHash,\n targetHash: preview.targetHash,\n message: 'CLI pull: merge main into local state',\n });\n }\n\n return await apiClient.getFullProject(projectId, tempBranchName);\n },\n });\n\n if (!remoteProject) {\n return;\n }\n } else {\n // Todo: we can probably just exit here because there is nothing new to pull\n remoteProject = await apiClient.getFullProject(projectId);\n }\n\n if (options.debug && remoteProject.functions) {\n console.log(\n styleText('gray', ' 📋 Project-level functions from API:'),\n Object.keys(remoteProject.functions)\n );\n Object.entries(remoteProject.functions).forEach(([id, data]: [string, any]) => {\n console.log(\n styleText(\n 'gray',\n ` ${id}: has name=${!!data.name}, has description=${!!data.description}`\n )\n );\n });\n }\n\n // Normalize remote project (same as pull-v2 - hoist agent-level functionTools)\n if (remoteProject.agents) {\n for (const [agentId, agentData] of Object.entries(remoteProject.agents) as any[]) {\n if (agentData.functionTools) {\n remoteProject.functionTools = remoteProject.functionTools || {};\n Object.assign(remoteProject.functionTools, agentData.functionTools);\n if (options.debug) {\n console.log(\n styleText(\n 'gray',\n ` Hoisted functionTools from agent ${agentId}: ${Object.keys(agentData.functionTools).join(', ')}`\n )\n );\n }\n }\n if (agentData.functions) {\n remoteProject.functions ||= {};\n const { functions } = remoteProject;\n // Only hoist agent functions if project-level functions don't already exist (clean function data)\n Object.entries(agentData.functions).forEach(([funcId, funcData]: [string, any]) => {\n // Clean function data - remove functionTool metadata that shouldn't be in functions collection\n functions[funcId] ||= {\n id: funcData.id,\n inputSchema: funcData.inputSchema,\n executeCode: funcData.executeCode,\n dependencies: funcData.dependencies,\n createdAt: '',\n updatedAt: '',\n };\n });\n }\n }\n }\n\n // Filter out project-level tools from individual agents\n // The API includes project-level tools in each agent's tools field, but our generated\n // code structure keeps tools separate and imports them via canUse relationships\n if (remoteProject.agents && remoteProject.tools) {\n const projectToolIds = Object.keys(remoteProject.tools);\n\n for (const agentData of Object.values(remoteProject.agents) as any[]) {\n if (agentData.tools) {\n // Filter out any tools that are defined at project level\n const agentSpecificTools = Object.fromEntries(\n Object.entries(agentData.tools).filter(([toolId]) => !projectToolIds.includes(toolId))\n );\n\n // Only keep tools field if there are agent-specific tools remaining\n if (Object.keys(agentSpecificTools).length > 0) {\n agentData.tools = agentSpecificTools;\n } else {\n // Remove the tools field entirely if all tools were project-level\n delete agentData.tools;\n }\n }\n }\n }\n\n // Enrich canDelegateTo references with component type information\n // @ts-expect-error -- fixme Types of property `models` are incompatible.\n enrichCanDelegateToWithTypes(remoteProject);\n\n console.log(styleText('green', '◆ Project data fetched'));\n\n if (options.json) {\n console.log(JSON.stringify(remoteProject, null, 2));\n restoreLogLevel();\n return;\n }\n\n // Step 5: Set up project structure\n const paths = createProjectStructure(projectDir);\n\n await generateProjectSkillsIfPresent(remoteProject, paths.skillsDir);\n\n console.log(styleText('gray', 'Generating files...'));\n await introspectGenerate({\n // @ts-expect-error -- ignore Types of property 'models' are incompatible.\n project: remoteProject,\n paths,\n debug: options.debug,\n });\n console.log(styleText('green', '◆ All files generated'));\n\n try {\n const mainBranch = await apiClient.getBranch(projectId, 'main');\n writeProjectState(projectId, mainBranch.hash);\n } catch (error) {\n console.warn(\n styleText(\n 'yellow',\n `Warning: Could not save pull state: ${error instanceof Error ? error.message : String(error)}`\n )\n );\n console.warn(styleText('yellow', 'Future pulls may re-prompt for conflict resolution.'));\n }\n\n console.log(styleText('green', '\\nProject synced successfully!'));\n console.log(styleText('gray', ` Location: ${paths.projectRoot}`));\n console.log(styleText('gray', ` Environment: ${options.env || 'development'}`));\n console.log(\n styleText(\n 'yellow',\n '⚠️ If you encounter broken code after running `inkeep pull`, please report it at https://github.com/inkeep/agents/issues.'\n )\n );\n\n restoreLogLevel();\n if (batchMode) {\n return { success: true };\n }\n process.exit(0);\n } catch (error) {\n const message = error instanceof Error ? error.stack : String(error);\n console.error(styleText('red', `\\nError: ${message}`));\n if (options.debug && error instanceof Error) {\n console.error(styleText('red', error.stack || ''));\n }\n restoreLogLevel();\n if (batchMode) {\n return { success: false, error: message };\n }\n process.exit(1);\n }\n}\n\n/**\n * Pull all projects for the current tenant\n * Uses smart comparison with LLM merging for existing projects, introspect for new projects\n */\nasync function pullAllProjects(options: PullV3Options): Promise<void> {\n console.log(styleText('blue', '\\n🔄 Batch Pull: Sequential processing with smart comparison\\n'));\n console.log(\n styleText(\n 'gray',\n ' • Existing projects: Smart comparison + AST merging + confirmation prompts'\n )\n );\n console.log(styleText('gray', ' • New projects: Fresh generation with introspect mode\\n'));\n\n // Background version check (only once for batch)\n performBackgroundVersionCheck();\n\n // Load configuration first\n const { config, isCI } = await initializeCommand({\n configPath: options.config,\n profileName: options.profile,\n tag: options.tag,\n showSpinner: true,\n spinnerText: 'Loading configuration...',\n logConfig: true,\n quiet: options.quiet,\n });\n\n const s = p.spinner();\n\n try {\n // Fetch all projects from the API\n s.start('Fetching project list from API...');\n const apiClient = await ManagementApiClient.create(\n config.agentsApiUrl,\n options.config,\n config.tenantId,\n undefined,\n isCI,\n config.agentsApiKey\n );\n\n const projects = await apiClient.listAllProjects();\n s.stop(`Found ${projects.length} project(s)`);\n\n if (!projects.length) {\n console.log(styleText('yellow', 'No projects found for this tenant.'));\n process.exit(0);\n }\n\n // Categorize projects\n const existingProjects: typeof projects = [];\n const newProjects: typeof projects = [];\n\n for (const project of projects) {\n const targetDir = join(process.cwd(), project.id);\n if (existsSync(join(targetDir, 'index.ts'))) {\n existingProjects.push(project);\n } else {\n newProjects.push(project);\n }\n }\n\n console.log(styleText('gray', '\\nProjects to pull:\\n'));\n if (existingProjects.length > 0) {\n console.log(styleText('cyan', ' Existing (smart comparison):'));\n for (const project of existingProjects) {\n console.log(styleText('gray', ` • ${project.name || project.id} (${project.id})`));\n }\n }\n if (newProjects.length > 0) {\n console.log(styleText('cyan', ' New (introspect):'));\n for (const project of newProjects) {\n console.log(styleText('gray', ` • ${project.name || project.id} (${project.id})`));\n }\n }\n console.log();\n\n const results: BatchPullResult[] = [];\n const total = projects.length;\n\n for (let i = 0; i < projects.length; i++) {\n const project = projects[i];\n const progress = `[${i + 1}/${total}]`;\n\n console.log(styleText('cyan', `\\n${'─'.repeat(60)}`));\n console.log(styleText('cyan', `${progress} Pulling ${project.name || project.id}...`));\n\n const result = await pullSingleProject(project.id, project.name, options, config, isCI);\n results.push(result);\n\n if (result.success) {\n console.log(\n styleText(\n 'green',\n `\\n ✓ ${result.projectName || result.projectId} → ${result.targetDir}`\n )\n );\n } else {\n console.log(\n styleText('red', `\\n ✗ ${result.projectName || result.projectId}: ${result.error}`)\n );\n }\n }\n\n // Print summary\n const succeeded = results.filter((r) => r.success).length;\n const failed = results.filter((r) => !r.success).length;\n\n console.log(styleText('cyan', `\\n${'═'.repeat(60)}`));\n console.log(styleText('cyan', '📊 Batch Pull Summary:'));\n console.log(styleText('green', ` ✓ Succeeded: ${succeeded}`));\n if (failed > 0) {\n console.log(styleText('red', ` ✗ Failed: ${failed}`));\n\n console.log(styleText('red', '\\nFailed projects:'));\n for (const result of results) {\n if (!result.success) {\n console.log(styleText('red', ` • ${result.projectId}: ${result.error}`));\n }\n }\n }\n\n process.exit(failed > 0 ? 1 : 0);\n } catch (error) {\n s.stop();\n console.error(\n styleText('red', `\\nError: ${error instanceof Error ? error.message : String(error)}`)\n );\n process.exit(1);\n }\n}\n\n/**\n * Pull a single project (used by batch operations)\n * Uses smart comparison flow for existing projects, introspect for new projects\n */\nexport async function pullSingleProject(\n projectId: string,\n projectName: string | undefined,\n options: PullV3Options,\n config: any,\n isCI?: boolean\n): Promise<BatchPullResult> {\n const targetDir = join(process.cwd(), projectId);\n const hasExistingProject = existsSync(join(targetDir, 'index.ts'));\n\n try {\n if (hasExistingProject) {\n // Project exists locally - use smart comparison flow with LLM merging and user prompts\n console.log(styleText('gray', ` 📂 Existing project found - using smart comparison mode`));\n\n // Save current directory and change to project directory\n const originalDir = process.cwd();\n process.chdir(targetDir);\n\n try {\n // Call the main pull command in batch mode (returns results instead of exiting)\n const result = await pullV4Command({\n ...options,\n project: projectId,\n all: false, // Don't recurse into batch mode\n _batchMode: true,\n });\n\n // Restore original directory\n process.chdir(originalDir);\n\n if (result && typeof result === 'object') {\n return {\n projectId,\n projectName,\n targetDir,\n success: result.success,\n error: result.error,\n };\n }\n\n return {\n projectId,\n projectName,\n targetDir,\n success: true,\n };\n } catch (error) {\n // Restore original directory even on error\n process.chdir(originalDir);\n throw error;\n }\n }\n console.log(styleText('gray', ' New project'));\n\n // Suppress SDK logging\n const originalLogLevel = process.env.LOG_LEVEL;\n process.env.LOG_LEVEL = 'silent';\n\n const restoreLogLevel = () => {\n if (originalLogLevel !== undefined) {\n process.env.LOG_LEVEL = originalLogLevel;\n } else {\n delete process.env.LOG_LEVEL;\n }\n };\n\n // Fetch project data from API\n const apiClient = await ManagementApiClient.create(\n config.agentsApiUrl,\n options.config,\n config.tenantId,\n projectId,\n isCI,\n config.agentsApiKey\n );\n\n const remoteProject = await apiClient.getFullProject(projectId);\n // Create project structure\n const paths = createProjectStructure(targetDir);\n await generateProjectSkillsIfPresent(remoteProject, paths.skillsDir);\n\n // Generate all files using introspect mode for new projects\n await introspectGenerate({\n // @ts-expect-error -- ignore Types of property 'models' are incompatible.\n project: remoteProject,\n paths,\n });\n\n restoreLogLevel();\n\n return {\n projectId,\n projectName: projectName || remoteProject.name,\n targetDir,\n success: true,\n };\n } catch (error) {\n return {\n projectId,\n projectName,\n targetDir,\n success: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\nasync function generateProjectSkillsIfPresent(\n remoteProject: any,\n skillsDir: string\n): Promise<void> {\n const skills = remoteProject.skills ?? {};\n if (!Object.keys(skills).length) {\n return;\n }\n\n const { generateSkills } = await import('../skill');\n await generateSkills(skills, skillsDir);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../../src/commands/pull-v4/introspect/index.ts"],"sourcesContent":["/**\n * Pull v3 - Clean, efficient project generation\n *\n * Step 1: Validate and compile existing code\n * Step 2: Compare project with DB to detect ALL changes\n * Step 3: Classify changes as new vs modified components\n * Step 4: Generate new components deterministically\n * Step 5: Use LLM to correct modified components\n */\n\nimport { EventEmitter } from 'node:events';\nimport { existsSync, mkdirSync } from 'node:fs';\nimport { join, resolve } from 'node:path';\nimport { styleText } from 'node:util';\nimport * as p from '@clack/prompts';\nimport type { FullProjectDefinition } from '@inkeep/agents-core';\n\n// Increase max listeners to prevent warnings during complex CLI flows\n// This is needed because @clack/prompts + multiple interactive prompts + spinners all add listeners\nEventEmitter.defaultMaxListeners = 20;\n\nimport { ManagementApiClient } from '../../../api';\nimport { performBackgroundVersionCheck } from '../../../utils/background-version-check';\nimport { initializeCommand } from '../../../utils/cli-pipeline';\nimport { loadProject } from '../../../utils/project-loader';\nimport { readProjectState, writeProjectState } from '../../../utils/state';\nimport { withLocalStateBranch } from '../../../utils/temp-branch';\nimport { introspectGenerate, type ProjectPaths } from '../introspect-generator';\n\nexport interface PullV3Options {\n project?: string;\n config?: string;\n profile?: string;\n env?: string;\n json?: boolean;\n debug?: boolean;\n verbose?: boolean;\n force?: boolean;\n all?: boolean;\n tag?: string;\n quiet?: boolean;\n conflictStrategy?: 'ours' | 'theirs';\n /** Internal: used for batch operations to return results instead of calling process.exit() */\n _batchMode?: boolean;\n}\n\nexport interface PullResult {\n success: boolean;\n skipped?: boolean;\n upToDate?: boolean;\n error?: string;\n}\n\ninterface BatchPullResult {\n projectId: string;\n projectName?: string;\n targetDir: string;\n success: boolean;\n error?: string;\n}\n\n/**\n * Create project directory structure\n */\nexport function createProjectStructure(projectRoot: string): ProjectPaths {\n mkdirSync(projectRoot, { recursive: true });\n return {\n projectRoot,\n agentsDir: join(projectRoot, 'agents'),\n toolsDir: join(projectRoot, 'tools'),\n dataComponentsDir: join(projectRoot, 'data-components'),\n artifactComponentsDir: join(projectRoot, 'artifact-components'),\n statusComponentsDir: join(projectRoot, 'status-components'),\n environmentsDir: join(projectRoot, 'environments'),\n credentialsDir: join(projectRoot, 'credentials'),\n contextConfigsDir: join(projectRoot, 'context-configs'),\n externalAgentsDir: join(projectRoot, 'external-agents'),\n skillsDir: join(projectRoot, 'skills'),\n };\n}\n\n/**\n * Enrich canDelegateTo references with component type information\n */\nexport function enrichCanDelegateToWithTypes(project: FullProjectDefinition): void {\n const { agents } = project;\n // Get all available component IDs by type\n const agentsIdSet = new Set(Object.keys(agents));\n const subAgentsIdSet = new Set(\n Object.values(agents).flatMap((agentData) => Object.keys(agentData.subAgents))\n );\n const externalAgentsIdSet = new Set(\n project.externalAgents ? Object.keys(project.externalAgents) : []\n );\n\n // Function to enrich a canDelegateTo array\n\n function enrichCanDelegateToArray(canDelegateTo: unknown[]): unknown[] {\n return canDelegateTo.map((item) => {\n // Skip if it's already an object (already has type info)\n if (typeof item !== 'string') return item;\n if (agentsIdSet.has(item)) return { agentId: item };\n if (subAgentsIdSet.has(item)) return { subAgentId: item };\n if (externalAgentsIdSet.has(item)) return { externalAgentId: item };\n return item;\n });\n }\n\n // Process all agents\n for (const { subAgents } of Object.values(project.agents)) {\n // Process subAgents within agents\n for (const subAgentData of Object.values(subAgents)) {\n if (Array.isArray(subAgentData.canDelegateTo)) {\n // @ts-expect-error\n subAgentData.canDelegateTo = enrichCanDelegateToArray(subAgentData.canDelegateTo);\n }\n }\n }\n}\n\n/**\n * Main pull v4 command\n * @returns PullResult when in batch mode, otherwise void (exits process)\n */\nexport async function pullV4Command(options: PullV3Options): Promise<PullResult | undefined> {\n // Handle --all flag for batch operations\n if (options.all) {\n await pullAllProjects(options);\n return;\n }\n\n const batchMode = options._batchMode ?? false;\n\n // Suppress SDK logging for cleaner output\n const originalLogLevel = process.env.LOG_LEVEL;\n process.env.LOG_LEVEL = 'silent';\n\n const restoreLogLevel = () => {\n if (originalLogLevel !== undefined) {\n process.env.LOG_LEVEL = originalLogLevel;\n } else {\n delete process.env.LOG_LEVEL;\n }\n };\n\n // Background version check (skip in batch mode - already done)\n if (!batchMode) {\n performBackgroundVersionCheck();\n }\n\n console.log(styleText('blue', '\\nInkeep Pull:'));\n console.log(styleText('gray', ' Smart comparison • Detect all changes • Targeted updates'));\n\n try {\n // Step 1: Load configuration (same as push command)\n const { config, isCI } = await initializeCommand({\n configPath: options.config,\n profileName: options.profile,\n tag: options.tag,\n showSpinner: true,\n spinnerText: 'Loading configuration...',\n logConfig: true,\n quiet: options.quiet,\n });\n let projectDir: string;\n let projectId: string;\n let localProjectForId: any = null;\n\n const currentDir = process.cwd();\n const hasIndexInCurrent = existsSync(join(currentDir, 'index.ts'));\n\n if (hasIndexInCurrent) {\n // We're in a project directory\n projectDir = currentDir;\n\n try {\n localProjectForId = await loadProject(projectDir);\n const localProjectId = localProjectForId.getId();\n\n if (options.project) {\n // Validate that --project matches local project ID\n if (localProjectId !== options.project) {\n console.error(\n styleText(\n 'red',\n `Local project ID \"${localProjectId}\" doesn't match --project \"${options.project}\"`\n )\n );\n console.error(\n styleText(\n 'yellow',\n 'Either remove --project flag or ensure it matches the local project ID'\n )\n );\n if (batchMode) {\n return { success: false, error: 'Project ID mismatch' };\n }\n process.exit(1);\n }\n }\n\n projectId = localProjectId;\n console.log(styleText('green', `◆ Using local project: ${projectId}`));\n } catch (error) {\n throw new Error(\n `Could not load local project: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n } else {\n // No index.ts in current directory\n if (!options.project) {\n console.error(\n styleText(\n 'yellow',\n 'Please run this command from a directory containing index.ts or use --project <project-id>'\n )\n );\n if (batchMode) {\n return { success: false, error: 'No index.ts found and no --project specified' };\n }\n process.exit(1);\n }\n\n // Try --project as directory path first\n const projectPath = resolve(currentDir, options.project);\n const hasIndexInPath = existsSync(join(projectPath, 'index.ts'));\n\n if (hasIndexInPath) {\n // --project is a valid directory path\n projectDir = projectPath;\n try {\n localProjectForId = await loadProject(projectDir);\n projectId = localProjectForId.getId();\n console.log(styleText('green', `◆ Using project from path: ${projectId}`));\n } catch (error) {\n throw new Error(\n `Could not load project from ${projectPath}: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n } else {\n // Treat --project as project ID, create subdirectory\n projectId = options.project;\n projectDir = join(currentDir, projectId);\n console.log(styleText('green', `◆ Creating new project directory: ${projectDir}`));\n }\n }\n\n const existingState = readProjectState(projectId);\n const lastPulledHash = existingState?.lastPulledHash;\n\n if (options.debug && lastPulledHash) {\n console.log(styleText('gray', ` Last pulled hash: ${lastPulledHash}`));\n }\n\n const apiClient = await ManagementApiClient.create(\n config.agentsApiUrl,\n options.config,\n config.tenantId,\n projectId,\n isCI,\n config.agentsApiKey\n );\n\n let currentMainHash: string | undefined;\n try {\n const mainBranch = await apiClient.getBranch(projectId, 'main');\n currentMainHash = mainBranch.hash;\n } catch (error) {\n if (options.debug) {\n console.log(\n styleText(\n 'gray',\n ` Could not fetch main branch hash: ${error instanceof Error ? error.message : String(error)}`\n )\n );\n }\n // Non-fatal: if we can't get the hash, fall through to direct pull\n }\n\n if (options.debug && currentMainHash) {\n console.log(styleText('gray', ` Current main hash: ${currentMainHash}`));\n }\n\n let remoteProject: Awaited<ReturnType<typeof apiClient.getFullProject>> | undefined;\n\n if (localProjectForId && lastPulledHash) {\n const localProjectDefinition = await localProjectForId.getFullDefinition();\n\n // Merge main INTO temp branch so the temp branch gets a reconciled result\n // (main's changes + user's local changes). We then pull from the temp branch.\n // We must NOT merge temp into main — that would push local edits to main.\n remoteProject = await withLocalStateBranch({\n apiClient,\n projectId,\n fromCommit: lastPulledHash,\n localDefinition: localProjectDefinition,\n branchPrefix: 'cli-pull',\n fn: async (tempBranchName) => {\n const preview = await apiClient.mergePreview(projectId, {\n sourceBranch: 'main',\n targetBranch: tempBranchName,\n });\n\n if (preview.hasConflicts) {\n const { resolveConflictsInteractive } = await import('../merge-conflicts');\n const resolutions = await resolveConflictsInteractive(preview.conflicts, options);\n\n if (resolutions === null) {\n console.log(styleText('yellow', 'Pull cancelled'));\n return undefined;\n }\n\n await apiClient.mergeExecute(projectId, {\n sourceBranch: 'main',\n targetBranch: tempBranchName,\n sourceHash: preview.sourceHash,\n targetHash: preview.targetHash,\n resolutions,\n message: 'CLI pull: merge main into local state',\n });\n } else {\n await apiClient.mergeExecute(projectId, {\n sourceBranch: 'main',\n targetBranch: tempBranchName,\n sourceHash: preview.sourceHash,\n targetHash: preview.targetHash,\n message: 'CLI pull: merge main into local state',\n });\n }\n\n return await apiClient.getFullProject(projectId, tempBranchName);\n },\n });\n\n if (!remoteProject) {\n return;\n }\n } else {\n // Todo: we can probably just exit here because there is nothing new to pull\n remoteProject = await apiClient.getFullProject(projectId);\n }\n\n if (options.debug && remoteProject.functions) {\n console.log(\n styleText('gray', ' 📋 Project-level functions from API:'),\n Object.keys(remoteProject.functions)\n );\n Object.entries(remoteProject.functions).forEach(([id, data]: [string, any]) => {\n console.log(\n styleText(\n 'gray',\n ` ${id}: has name=${!!data.name}, has description=${!!data.description}`\n )\n );\n });\n }\n\n // Normalize remote project (same as pull-v2 - hoist agent-level functionTools)\n if (remoteProject.agents) {\n for (const [agentId, agentData] of Object.entries(remoteProject.agents) as any[]) {\n if (agentData.functionTools) {\n remoteProject.functionTools = remoteProject.functionTools || {};\n Object.assign(remoteProject.functionTools, agentData.functionTools);\n if (options.debug) {\n console.log(\n styleText(\n 'gray',\n ` Hoisted functionTools from agent ${agentId}: ${Object.keys(agentData.functionTools).join(', ')}`\n )\n );\n }\n }\n if (agentData.functions) {\n remoteProject.functions ||= {};\n const { functions } = remoteProject;\n // Only hoist agent functions if project-level functions don't already exist (clean function data)\n Object.entries(agentData.functions).forEach(([funcId, funcData]: [string, any]) => {\n // Clean function data - remove functionTool metadata that shouldn't be in functions collection\n functions[funcId] ||= {\n id: funcData.id,\n inputSchema: funcData.inputSchema,\n executeCode: funcData.executeCode,\n dependencies: funcData.dependencies,\n createdAt: '',\n updatedAt: '',\n };\n });\n }\n }\n }\n\n // Filter out project-level tools from individual agents\n // The API includes project-level tools in each agent's tools field, but our generated\n // code structure keeps tools separate and imports them via canUse relationships\n if (remoteProject.agents && remoteProject.tools) {\n const projectToolIds = Object.keys(remoteProject.tools);\n\n for (const agentData of Object.values(remoteProject.agents) as any[]) {\n if (agentData.tools) {\n // Filter out any tools that are defined at project level\n const agentSpecificTools = Object.fromEntries(\n Object.entries(agentData.tools).filter(([toolId]) => !projectToolIds.includes(toolId))\n );\n\n // Only keep tools field if there are agent-specific tools remaining\n if (Object.keys(agentSpecificTools).length > 0) {\n agentData.tools = agentSpecificTools;\n } else {\n // Remove the tools field entirely if all tools were project-level\n delete agentData.tools;\n }\n }\n }\n }\n\n // Enrich canDelegateTo references with component type information\n // @ts-expect-error -- fixme Types of property `models` are incompatible.\n enrichCanDelegateToWithTypes(remoteProject);\n\n console.log(styleText('green', '◆ Project data fetched'));\n\n if (options.json) {\n console.log(JSON.stringify(remoteProject, null, 2));\n restoreLogLevel();\n return;\n }\n\n // Step 5: Set up project structure\n const paths = createProjectStructure(projectDir);\n\n console.log(styleText('gray', 'Generating files...'));\n await introspectGenerate({\n // @ts-expect-error -- ignore Types of property 'models' are incompatible.\n project: remoteProject,\n paths,\n debug: options.debug,\n });\n console.log(styleText('green', '◆ All files generated'));\n\n try {\n const mainBranch = await apiClient.getBranch(projectId, 'main');\n writeProjectState(projectId, mainBranch.hash);\n } catch (error) {\n console.warn(\n styleText(\n 'yellow',\n `Warning: Could not save pull state: ${error instanceof Error ? error.message : String(error)}`\n )\n );\n console.warn(styleText('yellow', 'Future pulls may re-prompt for conflict resolution.'));\n }\n\n console.log(styleText('green', '\\nProject synced successfully!'));\n console.log(styleText('gray', ` Location: ${paths.projectRoot}`));\n console.log(styleText('gray', ` Environment: ${options.env || 'development'}`));\n console.log(\n styleText(\n 'yellow',\n '⚠️ If you encounter broken code after running `inkeep pull`, please report it at https://github.com/inkeep/agents/issues.'\n )\n );\n\n restoreLogLevel();\n if (batchMode) {\n return { success: true };\n }\n process.exit(0);\n } catch (error) {\n const message = error instanceof Error ? error.stack : String(error);\n console.error(styleText('red', `\\nError: ${message}`));\n if (options.debug && error instanceof Error) {\n console.error(styleText('red', error.stack || ''));\n }\n restoreLogLevel();\n if (batchMode) {\n return { success: false, error: message };\n }\n process.exit(1);\n }\n}\n\n/**\n * Pull all projects for the current tenant\n * Uses smart comparison with LLM merging for existing projects, introspect for new projects\n */\nasync function pullAllProjects(options: PullV3Options): Promise<void> {\n console.log(styleText('blue', '\\n🔄 Batch Pull: Sequential processing with smart comparison\\n'));\n console.log(\n styleText(\n 'gray',\n ' • Existing projects: Smart comparison + AST merging + confirmation prompts'\n )\n );\n console.log(styleText('gray', ' • New projects: Fresh generation with introspect mode\\n'));\n\n // Background version check (only once for batch)\n performBackgroundVersionCheck();\n\n // Load configuration first\n const { config, isCI } = await initializeCommand({\n configPath: options.config,\n profileName: options.profile,\n tag: options.tag,\n showSpinner: true,\n spinnerText: 'Loading configuration...',\n logConfig: true,\n quiet: options.quiet,\n });\n\n const s = p.spinner();\n\n try {\n // Fetch all projects from the API\n s.start('Fetching project list from API...');\n const apiClient = await ManagementApiClient.create(\n config.agentsApiUrl,\n options.config,\n config.tenantId,\n undefined,\n isCI,\n config.agentsApiKey\n );\n\n const projects = await apiClient.listAllProjects();\n s.stop(`Found ${projects.length} project(s)`);\n\n if (!projects.length) {\n console.log(styleText('yellow', 'No projects found for this tenant.'));\n process.exit(0);\n }\n\n // Categorize projects\n const existingProjects: typeof projects = [];\n const newProjects: typeof projects = [];\n\n for (const project of projects) {\n const targetDir = join(process.cwd(), project.id);\n if (existsSync(join(targetDir, 'index.ts'))) {\n existingProjects.push(project);\n } else {\n newProjects.push(project);\n }\n }\n\n console.log(styleText('gray', '\\nProjects to pull:\\n'));\n if (existingProjects.length > 0) {\n console.log(styleText('cyan', ' Existing (smart comparison):'));\n for (const project of existingProjects) {\n console.log(styleText('gray', ` • ${project.name || project.id} (${project.id})`));\n }\n }\n if (newProjects.length > 0) {\n console.log(styleText('cyan', ' New (introspect):'));\n for (const project of newProjects) {\n console.log(styleText('gray', ` • ${project.name || project.id} (${project.id})`));\n }\n }\n console.log();\n\n const results: BatchPullResult[] = [];\n const total = projects.length;\n\n for (let i = 0; i < projects.length; i++) {\n const project = projects[i];\n const progress = `[${i + 1}/${total}]`;\n\n console.log(styleText('cyan', `\\n${'─'.repeat(60)}`));\n console.log(styleText('cyan', `${progress} Pulling ${project.name || project.id}...`));\n\n const result = await pullSingleProject(project.id, project.name, options, config, isCI);\n results.push(result);\n\n if (result.success) {\n console.log(\n styleText(\n 'green',\n `\\n ✓ ${result.projectName || result.projectId} → ${result.targetDir}`\n )\n );\n } else {\n console.log(\n styleText('red', `\\n ✗ ${result.projectName || result.projectId}: ${result.error}`)\n );\n }\n }\n\n // Print summary\n const succeeded = results.filter((r) => r.success).length;\n const failed = results.filter((r) => !r.success).length;\n\n console.log(styleText('cyan', `\\n${'═'.repeat(60)}`));\n console.log(styleText('cyan', '📊 Batch Pull Summary:'));\n console.log(styleText('green', ` ✓ Succeeded: ${succeeded}`));\n if (failed > 0) {\n console.log(styleText('red', ` ✗ Failed: ${failed}`));\n\n console.log(styleText('red', '\\nFailed projects:'));\n for (const result of results) {\n if (!result.success) {\n console.log(styleText('red', ` • ${result.projectId}: ${result.error}`));\n }\n }\n }\n\n process.exit(failed > 0 ? 1 : 0);\n } catch (error) {\n s.stop();\n console.error(\n styleText('red', `\\nError: ${error instanceof Error ? error.message : String(error)}`)\n );\n process.exit(1);\n }\n}\n\n/**\n * Pull a single project (used by batch operations)\n * Uses smart comparison flow for existing projects, introspect for new projects\n */\nexport async function pullSingleProject(\n projectId: string,\n projectName: string | undefined,\n options: PullV3Options,\n config: any,\n isCI?: boolean\n): Promise<BatchPullResult> {\n const targetDir = join(process.cwd(), projectId);\n const hasExistingProject = existsSync(join(targetDir, 'index.ts'));\n\n try {\n if (hasExistingProject) {\n // Project exists locally - use smart comparison flow with LLM merging and user prompts\n console.log(styleText('gray', ` 📂 Existing project found - using smart comparison mode`));\n\n // Save current directory and change to project directory\n const originalDir = process.cwd();\n process.chdir(targetDir);\n\n try {\n // Call the main pull command in batch mode (returns results instead of exiting)\n const result = await pullV4Command({\n ...options,\n project: projectId,\n all: false, // Don't recurse into batch mode\n _batchMode: true,\n });\n\n // Restore original directory\n process.chdir(originalDir);\n\n if (result && typeof result === 'object') {\n return {\n projectId,\n projectName,\n targetDir,\n success: result.success,\n error: result.error,\n };\n }\n\n return {\n projectId,\n projectName,\n targetDir,\n success: true,\n };\n } catch (error) {\n // Restore original directory even on error\n process.chdir(originalDir);\n throw error;\n }\n }\n console.log(styleText('gray', ' New project'));\n\n // Suppress SDK logging\n const originalLogLevel = process.env.LOG_LEVEL;\n process.env.LOG_LEVEL = 'silent';\n\n const restoreLogLevel = () => {\n if (originalLogLevel !== undefined) {\n process.env.LOG_LEVEL = originalLogLevel;\n } else {\n delete process.env.LOG_LEVEL;\n }\n };\n\n // Fetch project data from API\n const apiClient = await ManagementApiClient.create(\n config.agentsApiUrl,\n options.config,\n config.tenantId,\n projectId,\n isCI,\n config.agentsApiKey\n );\n\n const remoteProject = await apiClient.getFullProject(projectId);\n // Create project structure\n const paths = createProjectStructure(targetDir);\n\n // Generate all files using introspect mode for new projects\n await introspectGenerate({\n // @ts-expect-error -- ignore Types of property 'models' are incompatible.\n project: remoteProject,\n paths,\n });\n\n restoreLogLevel();\n\n return {\n projectId,\n projectName: projectName || remoteProject.name,\n targetDir,\n success: true,\n };\n } catch (error) {\n return {\n projectId,\n projectName,\n targetDir,\n success: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n}\n"],"mappings":"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"}
|
|
@@ -31,7 +31,8 @@ function createTestEnvironment() {
|
|
|
31
31
|
environmentsDir: join(testDir, "environments"),
|
|
32
32
|
credentialsDir: join(testDir, "credentials"),
|
|
33
33
|
contextConfigsDir: join(testDir, "context-configs"),
|
|
34
|
-
externalAgentsDir: join(testDir, "external-agents")
|
|
34
|
+
externalAgentsDir: join(testDir, "external-agents"),
|
|
35
|
+
skillsDir: join(testDir, "skills")
|
|
35
36
|
}
|
|
36
37
|
};
|
|
37
38
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test-helpers.js","names":[],"sources":["../../../../src/commands/pull-v4/introspect/test-helpers.ts"],"sourcesContent":["import fs from 'node:fs';\nimport { tmpdir } from 'node:os';\nimport { join } from 'node:path';\nimport type { FullProjectDefinition } from '@inkeep/agents-core';\nimport { createTwoFilesPatch } from 'diff';\nimport type { ProjectPaths } from '../introspect-generator';\n\nexport const beforeCredentialContent = `import { credential } from '@inkeep/agents-sdk';\n\nconst keepMe = () => 'keep-me';\n\nexport const apiCredentials = credential({\n id: 'api-credentials',\n name: 'Old API Credentials',\n type: 'bearer',\n credentialStoreId: 'main-store'\n});\n`.trimStart();\n\nexport function createTestEnvironment(): { testDir: string; projectPaths: ProjectPaths } {\n const testDir = join(\n tmpdir(),\n `introspect-v4-test-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`\n );\n fs.mkdirSync(testDir, { recursive: true });\n\n return {\n testDir,\n projectPaths: {\n projectRoot: testDir,\n agentsDir: join(testDir, 'agents'),\n toolsDir: join(testDir, 'tools'),\n dataComponentsDir: join(testDir, 'data-components'),\n artifactComponentsDir: join(testDir, 'artifact-components'),\n statusComponentsDir: join(testDir, 'status-components'),\n environmentsDir: join(testDir, 'environments'),\n credentialsDir: join(testDir, 'credentials'),\n contextConfigsDir: join(testDir, 'context-configs'),\n externalAgentsDir: join(testDir, 'external-agents'),\n },\n };\n}\n\nexport function cleanupTestEnvironment(testDir: string): void {\n fs.rmSync(testDir, { recursive: true, force: true });\n}\n\nexport function getTestPath(): string {\n return `../__tests__/__snapshots__/introspect/${expect.getState().currentTestName?.split(' > ').at(-1)}`;\n}\n\nexport function createProjectFixture(): FullProjectDefinition {\n return {\n id: 'support-project',\n name: 'Support Project',\n description: 'Support project for introspect v4 tests',\n models: {\n base: {\n model: 'gpt-4o-mini',\n },\n },\n credentialReferences: {\n 'api-credentials': {\n id: 'api-credentials',\n name: 'API Credentials',\n type: 'memory',\n credentialStoreId: 'main-store',\n retrievalParams: {\n key: 'token',\n },\n },\n },\n dataComponents: {\n 'customer-profile': {\n id: 'customer-profile',\n name: 'Customer Profile',\n description: 'Customer profile data component',\n props: {\n type: 'object',\n properties: {\n // @ts-expect-error -- fixme\n fullName: { type: 'string' },\n // @ts-expect-error -- fixme\n avatarUrl: { type: 'string' },\n },\n },\n render: {\n component: '<img src=\"{{avatarUrl}}\" alt=\"{{fullName}}\" />',\n mockData: {\n fullName: 'Ada Lovelace',\n avatarUrl: 'https://example.com/avatar.png',\n },\n },\n },\n },\n artifactComponents: {\n 'ticket-summary': {\n id: 'ticket-summary',\n name: 'Ticket Summary',\n props: {\n type: 'object',\n properties: {\n // @ts-expect-error -- fixme\n title: { type: 'string' },\n },\n },\n },\n },\n agents: {\n 'support-agent': {\n id: 'support-agent',\n name: 'Support Agent',\n defaultSubAgentId: 'tier-one',\n subAgents: {\n // @ts-expect-error -- fixme\n 'tier-one': {\n id: 'tier-one',\n name: 'Tier One',\n canUse: [],\n },\n },\n contextConfig: {\n id: 'support-context',\n headersSchema: {\n type: 'object',\n properties: {\n user_id: {\n type: 'string',\n },\n },\n },\n contextVariables: {\n userInfo: {\n id: 'user-info',\n name: 'User Information',\n trigger: 'initialization',\n fetchConfig: {\n // biome-ignore lint/suspicious/noTemplateCurlyInString: snapshot should produce template string\n url: 'https://api.example.com/users/${headersSchema.toTemplate(\"user_id\")}',\n method: 'GET',\n },\n responseSchema: {\n type: 'object',\n properties: {\n name: {\n type: 'string',\n },\n },\n },\n defaultValue: 'Unable to fetch user information',\n },\n },\n },\n triggers: {\n 'github-webhook': {\n id: 'github-webhook',\n name: 'GitHub Webhook',\n messageTemplate: 'New webhook event',\n },\n },\n statusUpdates: {\n numEvents: 1,\n statusComponents: [\n {\n // @ts-expect-error -- fixme\n id: 'tool-summary',\n type: 'tool_summary',\n description: 'Tool summary status component',\n detailsSchema: {\n type: 'object',\n properties: {\n tool_name: {\n type: 'string',\n },\n },\n },\n },\n ],\n },\n },\n },\n createdAt: new Date().toISOString(),\n updatedAt: new Date().toISOString(),\n };\n}\n\nexport async function createUnifiedDiff(\n filePath: string,\n before: string,\n after: string\n): Promise<string> {\n return createTwoFilesPatch(filePath, filePath, before, after, 'before', 'after', {\n context: 3,\n });\n}\n"],"mappings":";;;;;;;AAOA,MAAa,0BAA0B;;;;;;;;;;EAUrC,WAAW;AAEb,SAAgB,wBAAyE;CACvF,MAAM,UAAU,KACd,QAAQ,EACR,sBAAsB,KAAK,KAAK,CAAC,GAAG,KAAK,QAAQ,CAAC,SAAS,GAAG,CAAC,MAAM,GAAG,EAAE,GAC3E;AACD,IAAG,UAAU,SAAS,EAAE,WAAW,MAAM,CAAC;AAE1C,QAAO;EACL;EACA,cAAc;GACZ,aAAa;GACb,WAAW,KAAK,SAAS,SAAS;GAClC,UAAU,KAAK,SAAS,QAAQ;GAChC,mBAAmB,KAAK,SAAS,kBAAkB;GACnD,uBAAuB,KAAK,SAAS,sBAAsB;GAC3D,qBAAqB,KAAK,SAAS,oBAAoB;GACvD,iBAAiB,KAAK,SAAS,eAAe;GAC9C,gBAAgB,KAAK,SAAS,cAAc;GAC5C,mBAAmB,KAAK,SAAS,kBAAkB;GACnD,mBAAmB,KAAK,SAAS,kBAAkB;
|
|
1
|
+
{"version":3,"file":"test-helpers.js","names":[],"sources":["../../../../src/commands/pull-v4/introspect/test-helpers.ts"],"sourcesContent":["import fs from 'node:fs';\nimport { tmpdir } from 'node:os';\nimport { join } from 'node:path';\nimport type { FullProjectDefinition } from '@inkeep/agents-core';\nimport { createTwoFilesPatch } from 'diff';\nimport type { ProjectPaths } from '../introspect-generator';\n\nexport const beforeCredentialContent = `import { credential } from '@inkeep/agents-sdk';\n\nconst keepMe = () => 'keep-me';\n\nexport const apiCredentials = credential({\n id: 'api-credentials',\n name: 'Old API Credentials',\n type: 'bearer',\n credentialStoreId: 'main-store'\n});\n`.trimStart();\n\nexport function createTestEnvironment(): { testDir: string; projectPaths: ProjectPaths } {\n const testDir = join(\n tmpdir(),\n `introspect-v4-test-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`\n );\n fs.mkdirSync(testDir, { recursive: true });\n\n return {\n testDir,\n projectPaths: {\n projectRoot: testDir,\n agentsDir: join(testDir, 'agents'),\n toolsDir: join(testDir, 'tools'),\n dataComponentsDir: join(testDir, 'data-components'),\n artifactComponentsDir: join(testDir, 'artifact-components'),\n statusComponentsDir: join(testDir, 'status-components'),\n environmentsDir: join(testDir, 'environments'),\n credentialsDir: join(testDir, 'credentials'),\n contextConfigsDir: join(testDir, 'context-configs'),\n externalAgentsDir: join(testDir, 'external-agents'),\n skillsDir: join(testDir, 'skills'),\n },\n };\n}\n\nexport function cleanupTestEnvironment(testDir: string): void {\n fs.rmSync(testDir, { recursive: true, force: true });\n}\n\nexport function getTestPath(): string {\n return `../__tests__/__snapshots__/introspect/${expect.getState().currentTestName?.split(' > ').at(-1)}`;\n}\n\nexport function createProjectFixture(): FullProjectDefinition {\n return {\n id: 'support-project',\n name: 'Support Project',\n description: 'Support project for introspect v4 tests',\n models: {\n base: {\n model: 'gpt-4o-mini',\n },\n },\n credentialReferences: {\n 'api-credentials': {\n id: 'api-credentials',\n name: 'API Credentials',\n type: 'memory',\n credentialStoreId: 'main-store',\n retrievalParams: {\n key: 'token',\n },\n },\n },\n dataComponents: {\n 'customer-profile': {\n id: 'customer-profile',\n name: 'Customer Profile',\n description: 'Customer profile data component',\n props: {\n type: 'object',\n properties: {\n // @ts-expect-error -- fixme\n fullName: { type: 'string' },\n // @ts-expect-error -- fixme\n avatarUrl: { type: 'string' },\n },\n },\n render: {\n component: '<img src=\"{{avatarUrl}}\" alt=\"{{fullName}}\" />',\n mockData: {\n fullName: 'Ada Lovelace',\n avatarUrl: 'https://example.com/avatar.png',\n },\n },\n },\n },\n artifactComponents: {\n 'ticket-summary': {\n id: 'ticket-summary',\n name: 'Ticket Summary',\n props: {\n type: 'object',\n properties: {\n // @ts-expect-error -- fixme\n title: { type: 'string' },\n },\n },\n },\n },\n agents: {\n 'support-agent': {\n id: 'support-agent',\n name: 'Support Agent',\n defaultSubAgentId: 'tier-one',\n subAgents: {\n // @ts-expect-error -- fixme\n 'tier-one': {\n id: 'tier-one',\n name: 'Tier One',\n canUse: [],\n },\n },\n contextConfig: {\n id: 'support-context',\n headersSchema: {\n type: 'object',\n properties: {\n user_id: {\n type: 'string',\n },\n },\n },\n contextVariables: {\n userInfo: {\n id: 'user-info',\n name: 'User Information',\n trigger: 'initialization',\n fetchConfig: {\n // biome-ignore lint/suspicious/noTemplateCurlyInString: snapshot should produce template string\n url: 'https://api.example.com/users/${headersSchema.toTemplate(\"user_id\")}',\n method: 'GET',\n },\n responseSchema: {\n type: 'object',\n properties: {\n name: {\n type: 'string',\n },\n },\n },\n defaultValue: 'Unable to fetch user information',\n },\n },\n },\n triggers: {\n 'github-webhook': {\n id: 'github-webhook',\n name: 'GitHub Webhook',\n messageTemplate: 'New webhook event',\n },\n },\n statusUpdates: {\n numEvents: 1,\n statusComponents: [\n {\n // @ts-expect-error -- fixme\n id: 'tool-summary',\n type: 'tool_summary',\n description: 'Tool summary status component',\n detailsSchema: {\n type: 'object',\n properties: {\n tool_name: {\n type: 'string',\n },\n },\n },\n },\n ],\n },\n },\n },\n createdAt: new Date().toISOString(),\n updatedAt: new Date().toISOString(),\n };\n}\n\nexport async function createUnifiedDiff(\n filePath: string,\n before: string,\n after: string\n): Promise<string> {\n return createTwoFilesPatch(filePath, filePath, before, after, 'before', 'after', {\n context: 3,\n });\n}\n"],"mappings":"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"}
|
|
@@ -2,6 +2,7 @@ import { buildComponentRegistryFromParsing } from "./component-parser.js";
|
|
|
2
2
|
import { GenerationResolver } from "./generation-resolver.js";
|
|
3
3
|
import { collectCompleteAgentIds, validateProject } from "./generation-types.js";
|
|
4
4
|
import { generationTasks } from "./generators/index.js";
|
|
5
|
+
import { writeTextFile } from "./text-file-writer.js";
|
|
5
6
|
import { writeTypeScriptFile } from "./typescript-file-writer.js";
|
|
6
7
|
|
|
7
8
|
//#region src/commands/pull-v4/introspect-generator.ts
|
|
@@ -26,8 +27,9 @@ async function introspectGenerate({ project, paths, writeMode = "merge", debug =
|
|
|
26
27
|
for (const task of Object.values(generationTasks)) {
|
|
27
28
|
const records = task.collect(context);
|
|
28
29
|
for (const record of records) {
|
|
29
|
-
const
|
|
30
|
-
|
|
30
|
+
const generatedOutput = task.generate(record.payload);
|
|
31
|
+
if (typeof generatedOutput === "string") writeTextFile(record.filePath, generatedOutput);
|
|
32
|
+
else writeTypeScriptFile(record.filePath, generatedOutput.getFullText(), writeMode);
|
|
31
33
|
generatedFiles.push(record.filePath);
|
|
32
34
|
}
|
|
33
35
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"introspect-generator.js","names":[],"sources":["../../../src/commands/pull-v4/introspect-generator.ts"],"sourcesContent":["import type { FullProjectDefinition } from '@inkeep/agents-core';\nimport { buildComponentRegistryFromParsing } from './component-parser';\nimport { GenerationResolver } from './generation-resolver';\nimport {\n collectCompleteAgentIds,\n type GenerationContext,\n type ProjectPaths,\n type SkippedAgent,\n validateProject,\n} from './generation-types';\nimport { generationTasks } from './generators';\nimport { writeTypeScriptFile } from './typescript-file-writer';\n\nexport type { ProjectPaths } from './generation-types';\n\nexport interface IntrospectOptions {\n project: FullProjectDefinition;\n paths: ProjectPaths;\n writeMode?: 'merge' | 'overwrite';\n debug?: boolean;\n}\n\nexport async function introspectGenerate({\n project,\n paths,\n writeMode = 'merge',\n debug = false,\n}: IntrospectOptions): Promise<void> {\n validateProject(project);\n\n const skippedAgents: SkippedAgent[] = [];\n const completeAgentIds = collectCompleteAgentIds(project, skippedAgents);\n const existingComponentRegistry =\n writeMode === 'merge' ? buildComponentRegistryFromParsing(paths.projectRoot, debug) : undefined;\n const resolver = new GenerationResolver({\n project,\n projectRoot: paths.projectRoot,\n completeAgentIds,\n existingComponentRegistry,\n });\n const context: GenerationContext = {\n project,\n paths,\n completeAgentIds,\n existingComponentRegistry,\n resolver,\n };\n const generatedFiles: string[] = [];\n\n for (const task of Object.values(generationTasks)) {\n const records = task.collect(context);\n for (const record of records) {\n const
|
|
1
|
+
{"version":3,"file":"introspect-generator.js","names":[],"sources":["../../../src/commands/pull-v4/introspect-generator.ts"],"sourcesContent":["import type { FullProjectDefinition } from '@inkeep/agents-core';\nimport { buildComponentRegistryFromParsing } from './component-parser';\nimport { GenerationResolver } from './generation-resolver';\nimport {\n collectCompleteAgentIds,\n type GenerationContext,\n type ProjectPaths,\n type SkippedAgent,\n validateProject,\n} from './generation-types';\nimport { generationTasks } from './generators';\nimport { writeTextFile } from './text-file-writer';\nimport { writeTypeScriptFile } from './typescript-file-writer';\n\nexport type { ProjectPaths } from './generation-types';\n\nexport interface IntrospectOptions {\n project: FullProjectDefinition;\n paths: ProjectPaths;\n writeMode?: 'merge' | 'overwrite';\n debug?: boolean;\n}\n\nexport async function introspectGenerate({\n project,\n paths,\n writeMode = 'merge',\n debug = false,\n}: IntrospectOptions): Promise<void> {\n validateProject(project);\n\n const skippedAgents: SkippedAgent[] = [];\n const completeAgentIds = collectCompleteAgentIds(project, skippedAgents);\n const existingComponentRegistry =\n writeMode === 'merge' ? buildComponentRegistryFromParsing(paths.projectRoot, debug) : undefined;\n const resolver = new GenerationResolver({\n project,\n projectRoot: paths.projectRoot,\n completeAgentIds,\n existingComponentRegistry,\n });\n const context: GenerationContext = {\n project,\n paths,\n completeAgentIds,\n existingComponentRegistry,\n resolver,\n };\n const generatedFiles: string[] = [];\n\n for (const task of Object.values(generationTasks)) {\n const records = task.collect(context);\n for (const record of records) {\n const generatedOutput = task.generate(record.payload);\n if (typeof generatedOutput === 'string') {\n writeTextFile(record.filePath, generatedOutput);\n } else {\n writeTypeScriptFile(record.filePath, generatedOutput.getFullText(), writeMode);\n }\n generatedFiles.push(record.filePath);\n }\n }\n\n if (debug) {\n console.log(`Generated ${generatedFiles.length} files`);\n if (skippedAgents.length) {\n console.log(\n `Skipped ${skippedAgents.length} agent(s): ${skippedAgents\n .map((agent) => `${agent.id} (${agent.reason})`)\n .join(', ')}`\n );\n }\n }\n}\n"],"mappings":";;;;;;;;AAuBA,eAAsB,mBAAmB,EACvC,SACA,OACA,YAAY,SACZ,QAAQ,SAC2B;AACnC,iBAAgB,QAAQ;CAExB,MAAM,gBAAgC,EAAE;CACxC,MAAM,mBAAmB,wBAAwB,SAAS,cAAc;CACxE,MAAM,4BACJ,cAAc,UAAU,kCAAkC,MAAM,aAAa,MAAM,GAAG;CAOxF,MAAM,UAA6B;EACjC;EACA;EACA;EACA;EACA,UAXe,IAAI,mBAAmB;GACtC;GACA,aAAa,MAAM;GACnB;GACA;GACD,CAAC;EAOD;CACD,MAAM,iBAA2B,EAAE;AAEnC,MAAK,MAAM,QAAQ,OAAO,OAAO,gBAAgB,EAAE;EACjD,MAAM,UAAU,KAAK,QAAQ,QAAQ;AACrC,OAAK,MAAM,UAAU,SAAS;GAC5B,MAAM,kBAAkB,KAAK,SAAS,OAAO,QAAQ;AACrD,OAAI,OAAO,oBAAoB,SAC7B,eAAc,OAAO,UAAU,gBAAgB;OAE/C,qBAAoB,OAAO,UAAU,gBAAgB,aAAa,EAAE,UAAU;AAEhF,kBAAe,KAAK,OAAO,SAAS;;;AAIxC,KAAI,OAAO;AACT,UAAQ,IAAI,aAAa,eAAe,OAAO,QAAQ;AACvD,MAAI,cAAc,OAChB,SAAQ,IACN,WAAW,cAAc,OAAO,aAAa,cAC1C,KAAK,UAAU,GAAG,MAAM,GAAG,IAAI,MAAM,OAAO,GAAG,CAC/C,KAAK,KAAK,GACd"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { dirname } from "node:path";
|
|
2
|
+
import { mkdirSync, writeFileSync } from "node:fs";
|
|
3
|
+
|
|
4
|
+
//#region src/commands/pull-v4/text-file-writer.ts
|
|
5
|
+
function writeTextFile(filePath, content) {
|
|
6
|
+
mkdirSync(dirname(filePath), { recursive: true });
|
|
7
|
+
writeFileSync(filePath, content.endsWith("\n") ? content : `${content}\n`);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
//#endregion
|
|
11
|
+
export { writeTextFile };
|
|
12
|
+
//# sourceMappingURL=text-file-writer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text-file-writer.js","names":[],"sources":["../../../src/commands/pull-v4/text-file-writer.ts"],"sourcesContent":["import { mkdirSync, writeFileSync } from 'node:fs';\nimport { dirname } from 'node:path';\n\nexport function writeTextFile(filePath: string, content: string): void {\n mkdirSync(dirname(filePath), { recursive: true });\n writeFileSync(filePath, content.endsWith('\\n') ? content : `${content}\\n`);\n}\n"],"mappings":";;;;AAGA,SAAgB,cAAc,UAAkB,SAAuB;AACrE,WAAU,QAAQ,SAAS,EAAE,EAAE,WAAW,MAAM,CAAC;AACjD,eAAc,UAAU,QAAQ,SAAS,KAAK,GAAG,UAAU,GAAG,QAAQ,IAAI"}
|
|
@@ -68,9 +68,8 @@ function moveVariableDeclarationsBeforeUsage(sourceFile) {
|
|
|
68
68
|
return sourceFile;
|
|
69
69
|
}
|
|
70
70
|
function isReferenceInsideFunctionLike(referenceNode) {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}));
|
|
71
|
+
const ancestor = referenceNode.getFirstAncestor((ancestor$1) => Node.isArrowFunction(ancestor$1) || Node.isFunctionDeclaration(ancestor$1) || Node.isFunctionExpression(ancestor$1) || Node.isMethodDeclaration(ancestor$1) || Node.isGetAccessorDeclaration(ancestor$1) || Node.isSetAccessorDeclaration(ancestor$1));
|
|
72
|
+
return Boolean(ancestor);
|
|
74
73
|
}
|
|
75
74
|
|
|
76
75
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"typescript-file-writer.js","names":[],"sources":["../../../src/commands/pull-v4/typescript-file-writer.ts"],"sourcesContent":["import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { dirname } from 'node:path';\nimport { Node, type SourceFile, SyntaxKind } from 'ts-morph';\nimport { mergeGeneratedModule } from './module-merge';\nimport { createInMemoryProject } from './utils';\n\nexport function writeTypeScriptFile(\n filePath: string,\n content: string,\n writeMode: 'merge' | 'overwrite'\n): void {\n mkdirSync(dirname(filePath), { recursive: true });\n\n const processedContent =\n writeMode === 'merge' && existsSync(filePath)\n ? mergeSafely(readFileSync(filePath, 'utf8'), content)\n : content;\n\n const sourceFile = createInMemoryProject().createSourceFile('generated.ts', processedContent, {\n overwrite: true,\n });\n\n const normalizedSourceFile = moveVariableDeclarationsBeforeUsage(\n applyObjectShorthand(sourceFile)\n );\n sourceFile.formatText();\n writeFileSync(filePath, `${normalizedSourceFile.getFullText().trimEnd()}\\n`);\n}\n\nfunction mergeSafely(existingContent: string, generatedContent: string): string {\n try {\n return mergeGeneratedModule(existingContent, generatedContent);\n } catch (error) {\n console.warn(\n `Warning: Failed to merge file, using generated content. Manual changes may be lost. Reason: ${error instanceof Error ? error.message : String(error)}`\n );\n return generatedContent;\n }\n}\n\nfunction applyObjectShorthand(sourceFile: SourceFile): SourceFile {\n for (const objectLiteral of sourceFile.getDescendantsOfKind(SyntaxKind.ObjectLiteralExpression)) {\n for (const property of objectLiteral.getProperties()) {\n if (!Node.isPropertyAssignment(property)) {\n continue;\n }\n const nameNode = property.getNameNode();\n const initializer = property.getInitializer();\n if (!Node.isIdentifier(nameNode) || !initializer || !Node.isIdentifier(initializer)) {\n continue;\n }\n if (nameNode.getText() !== initializer.getText()) {\n continue;\n }\n property.replaceWithText(nameNode.getText());\n }\n }\n return sourceFile;\n}\n\nfunction moveVariableDeclarationsBeforeUsage(sourceFile: SourceFile): SourceFile {\n let moved = true;\n while (moved) {\n moved = false;\n const variableStatements = sourceFile.getVariableStatements();\n for (const variableStatement of variableStatements) {\n const statementStart = variableStatement.getStart();\n const sourceStatements = sourceFile.getStatements();\n const statementIndex = sourceStatements.indexOf(variableStatement);\n if (statementIndex <= 0) {\n continue;\n }\n\n let targetIndex: number | undefined;\n for (const declaration of variableStatement.getDeclarations()) {\n for (const referenceNode of declaration.findReferencesAsNodes()) {\n if (referenceNode.getSourceFile() !== sourceFile) {\n continue;\n }\n\n const parentNode = referenceNode.getParent();\n if (parentNode === declaration) {\n continue;\n }\n\n if (referenceNode.getStart() >= statementStart) {\n continue;\n }\n\n if (isReferenceInsideFunctionLike(referenceNode)) {\n continue;\n }\n // @ts-expect-error\n const topLevelStatement = referenceNode.getFirstAncestor((ancestor) => {\n return Node.isStatement(ancestor) && ancestor.getParentIfKind(SyntaxKind.SourceFile);\n });\n if (!topLevelStatement) {\n continue;\n }\n // @ts-expect-error\n const topLevelStatementIndex = sourceStatements.indexOf(topLevelStatement);\n if (topLevelStatementIndex === -1 || topLevelStatementIndex >= statementIndex) {\n continue;\n }\n\n targetIndex =\n targetIndex === undefined\n ? topLevelStatementIndex\n : Math.min(targetIndex, topLevelStatementIndex);\n }\n }\n\n if (targetIndex === undefined) {\n continue;\n }\n\n const statementText = variableStatement.getText();\n variableStatement.remove();\n sourceFile.insertStatements(targetIndex, [statementText]);\n moved = true;\n break;\n }\n }\n return sourceFile;\n}\n\nfunction isReferenceInsideFunctionLike(referenceNode: Node): boolean {\n
|
|
1
|
+
{"version":3,"file":"typescript-file-writer.js","names":["ancestor"],"sources":["../../../src/commands/pull-v4/typescript-file-writer.ts"],"sourcesContent":["import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { dirname } from 'node:path';\nimport { Node, type SourceFile, SyntaxKind } from 'ts-morph';\nimport { mergeGeneratedModule } from './module-merge';\nimport { createInMemoryProject } from './utils';\n\nexport function writeTypeScriptFile(\n filePath: string,\n content: string,\n writeMode: 'merge' | 'overwrite'\n): void {\n mkdirSync(dirname(filePath), { recursive: true });\n\n const processedContent =\n writeMode === 'merge' && existsSync(filePath)\n ? mergeSafely(readFileSync(filePath, 'utf8'), content)\n : content;\n\n const sourceFile = createInMemoryProject().createSourceFile('generated.ts', processedContent, {\n overwrite: true,\n });\n\n const normalizedSourceFile = moveVariableDeclarationsBeforeUsage(\n applyObjectShorthand(sourceFile)\n );\n sourceFile.formatText();\n writeFileSync(filePath, `${normalizedSourceFile.getFullText().trimEnd()}\\n`);\n}\n\nfunction mergeSafely(existingContent: string, generatedContent: string): string {\n try {\n return mergeGeneratedModule(existingContent, generatedContent);\n } catch (error) {\n console.warn(\n `Warning: Failed to merge file, using generated content. Manual changes may be lost. Reason: ${error instanceof Error ? error.message : String(error)}`\n );\n return generatedContent;\n }\n}\n\nfunction applyObjectShorthand(sourceFile: SourceFile): SourceFile {\n for (const objectLiteral of sourceFile.getDescendantsOfKind(SyntaxKind.ObjectLiteralExpression)) {\n for (const property of objectLiteral.getProperties()) {\n if (!Node.isPropertyAssignment(property)) {\n continue;\n }\n const nameNode = property.getNameNode();\n const initializer = property.getInitializer();\n if (!Node.isIdentifier(nameNode) || !initializer || !Node.isIdentifier(initializer)) {\n continue;\n }\n if (nameNode.getText() !== initializer.getText()) {\n continue;\n }\n property.replaceWithText(nameNode.getText());\n }\n }\n return sourceFile;\n}\n\nfunction moveVariableDeclarationsBeforeUsage(sourceFile: SourceFile): SourceFile {\n let moved = true;\n while (moved) {\n moved = false;\n const variableStatements = sourceFile.getVariableStatements();\n for (const variableStatement of variableStatements) {\n const statementStart = variableStatement.getStart();\n const sourceStatements = sourceFile.getStatements();\n const statementIndex = sourceStatements.indexOf(variableStatement);\n if (statementIndex <= 0) {\n continue;\n }\n\n let targetIndex: number | undefined;\n for (const declaration of variableStatement.getDeclarations()) {\n for (const referenceNode of declaration.findReferencesAsNodes()) {\n if (referenceNode.getSourceFile() !== sourceFile) {\n continue;\n }\n\n const parentNode = referenceNode.getParent();\n if (parentNode === declaration) {\n continue;\n }\n\n if (referenceNode.getStart() >= statementStart) {\n continue;\n }\n\n if (isReferenceInsideFunctionLike(referenceNode)) {\n continue;\n }\n // @ts-expect-error\n const topLevelStatement = referenceNode.getFirstAncestor((ancestor) => {\n return Node.isStatement(ancestor) && ancestor.getParentIfKind(SyntaxKind.SourceFile);\n });\n if (!topLevelStatement) {\n continue;\n }\n // @ts-expect-error\n const topLevelStatementIndex = sourceStatements.indexOf(topLevelStatement);\n if (topLevelStatementIndex === -1 || topLevelStatementIndex >= statementIndex) {\n continue;\n }\n\n targetIndex =\n targetIndex === undefined\n ? topLevelStatementIndex\n : Math.min(targetIndex, topLevelStatementIndex);\n }\n }\n\n if (targetIndex === undefined) {\n continue;\n }\n\n const statementText = variableStatement.getText();\n variableStatement.remove();\n sourceFile.insertStatements(targetIndex, [statementText]);\n moved = true;\n break;\n }\n }\n return sourceFile;\n}\n\nfunction isReferenceInsideFunctionLike(referenceNode: Node): boolean {\n const ancestor = referenceNode.getFirstAncestor(\n (ancestor) =>\n Node.isArrowFunction(ancestor) ||\n Node.isFunctionDeclaration(ancestor) ||\n Node.isFunctionExpression(ancestor) ||\n Node.isMethodDeclaration(ancestor) ||\n Node.isGetAccessorDeclaration(ancestor) ||\n Node.isSetAccessorDeclaration(ancestor)\n );\n\n return Boolean(ancestor);\n}\n"],"mappings":";;;;;;;;AAMA,SAAgB,oBACd,UACA,SACA,WACM;AACN,WAAU,QAAQ,SAAS,EAAE,EAAE,WAAW,MAAM,CAAC;CAEjD,MAAM,mBACJ,cAAc,WAAW,WAAW,SAAS,GACzC,YAAY,aAAa,UAAU,OAAO,EAAE,QAAQ,GACpD;CAEN,MAAM,aAAa,uBAAuB,CAAC,iBAAiB,gBAAgB,kBAAkB,EAC5F,WAAW,MACZ,CAAC;CAEF,MAAM,uBAAuB,oCAC3B,qBAAqB,WAAW,CACjC;AACD,YAAW,YAAY;AACvB,eAAc,UAAU,GAAG,qBAAqB,aAAa,CAAC,SAAS,CAAC,IAAI;;AAG9E,SAAS,YAAY,iBAAyB,kBAAkC;AAC9E,KAAI;AACF,SAAO,qBAAqB,iBAAiB,iBAAiB;UACvD,OAAO;AACd,UAAQ,KACN,+FAA+F,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,GACtJ;AACD,SAAO;;;AAIX,SAAS,qBAAqB,YAAoC;AAChE,MAAK,MAAM,iBAAiB,WAAW,qBAAqB,WAAW,wBAAwB,CAC7F,MAAK,MAAM,YAAY,cAAc,eAAe,EAAE;AACpD,MAAI,CAAC,KAAK,qBAAqB,SAAS,CACtC;EAEF,MAAM,WAAW,SAAS,aAAa;EACvC,MAAM,cAAc,SAAS,gBAAgB;AAC7C,MAAI,CAAC,KAAK,aAAa,SAAS,IAAI,CAAC,eAAe,CAAC,KAAK,aAAa,YAAY,CACjF;AAEF,MAAI,SAAS,SAAS,KAAK,YAAY,SAAS,CAC9C;AAEF,WAAS,gBAAgB,SAAS,SAAS,CAAC;;AAGhD,QAAO;;AAGT,SAAS,oCAAoC,YAAoC;CAC/E,IAAI,QAAQ;AACZ,QAAO,OAAO;AACZ,UAAQ;EACR,MAAM,qBAAqB,WAAW,uBAAuB;AAC7D,OAAK,MAAM,qBAAqB,oBAAoB;GAClD,MAAM,iBAAiB,kBAAkB,UAAU;GACnD,MAAM,mBAAmB,WAAW,eAAe;GACnD,MAAM,iBAAiB,iBAAiB,QAAQ,kBAAkB;AAClE,OAAI,kBAAkB,EACpB;GAGF,IAAI;AACJ,QAAK,MAAM,eAAe,kBAAkB,iBAAiB,CAC3D,MAAK,MAAM,iBAAiB,YAAY,uBAAuB,EAAE;AAC/D,QAAI,cAAc,eAAe,KAAK,WACpC;AAIF,QADmB,cAAc,WAAW,KACzB,YACjB;AAGF,QAAI,cAAc,UAAU,IAAI,eAC9B;AAGF,QAAI,8BAA8B,cAAc,CAC9C;IAGF,MAAM,oBAAoB,cAAc,kBAAkB,aAAa;AACrE,YAAO,KAAK,YAAY,SAAS,IAAI,SAAS,gBAAgB,WAAW,WAAW;MACpF;AACF,QAAI,CAAC,kBACH;IAGF,MAAM,yBAAyB,iBAAiB,QAAQ,kBAAkB;AAC1E,QAAI,2BAA2B,MAAM,0BAA0B,eAC7D;AAGF,kBACE,gBAAgB,SACZ,yBACA,KAAK,IAAI,aAAa,uBAAuB;;AAIvD,OAAI,gBAAgB,OAClB;GAGF,MAAM,gBAAgB,kBAAkB,SAAS;AACjD,qBAAkB,QAAQ;AAC1B,cAAW,iBAAiB,aAAa,CAAC,cAAc,CAAC;AACzD,WAAQ;AACR;;;AAGJ,QAAO;;AAGT,SAAS,8BAA8B,eAA8B;CACnE,MAAM,WAAW,cAAc,kBAC5B,eACC,KAAK,gBAAgBA,WAAS,IAC9B,KAAK,sBAAsBA,WAAS,IACpC,KAAK,qBAAqBA,WAAS,IACnC,KAAK,oBAAoBA,WAAS,IAClC,KAAK,yBAAyBA,WAAS,IACvC,KAAK,yBAAyBA,WAAS,CAC1C;AAED,QAAO,QAAQ,SAAS"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inkeep/agents-cli",
|
|
3
|
-
"version": "0.63.
|
|
3
|
+
"version": "0.63.2",
|
|
4
4
|
"description": "Inkeep CLI tool",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -39,8 +39,8 @@
|
|
|
39
39
|
"tsx": "^4.20.5",
|
|
40
40
|
"yaml": "^2.7.0",
|
|
41
41
|
"zod": "^4.3.6",
|
|
42
|
-
"@inkeep/agents-
|
|
43
|
-
"@inkeep/agents-
|
|
42
|
+
"@inkeep/agents-core": "^0.63.2",
|
|
43
|
+
"@inkeep/agents-sdk": "^0.63.2"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@types/degit": "^2.8.6",
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { validateGeneratorInput } from "./simple-factory-generator.js";
|
|
2
|
-
import { FullProjectDefinitionSchema } from "@inkeep/agents-core";
|
|
3
|
-
import { z } from "zod";
|
|
4
|
-
import { join } from "node:path";
|
|
5
|
-
import { stringify } from "yaml";
|
|
6
|
-
import { mkdir, writeFile } from "node:fs/promises";
|
|
7
|
-
|
|
8
|
-
//#region src/commands/pull-v4/skill.ts
|
|
9
|
-
const MySchema = FullProjectDefinitionSchema.shape.skills.unwrap().valueType;
|
|
10
|
-
const SkillsSchema = z.record(z.string(), MySchema);
|
|
11
|
-
const SkillsDirSchema = z.string().nonempty();
|
|
12
|
-
function formatMetadata(metadata) {
|
|
13
|
-
return `metadata:\n${stringify(metadata).split("\n").filter((line) => line.trim() !== "").map((line) => ` ${line}`).join("\n")}`;
|
|
14
|
-
}
|
|
15
|
-
async function generateSkills(skills, skillsDir) {
|
|
16
|
-
const validatedSkills = validateGeneratorInput(skills, {
|
|
17
|
-
schema: SkillsSchema,
|
|
18
|
-
errorLabel: "skills"
|
|
19
|
-
});
|
|
20
|
-
const validatedSkillsDir = validateGeneratorInput(skillsDir, {
|
|
21
|
-
schema: SkillsDirSchema,
|
|
22
|
-
errorLabel: "skills directory"
|
|
23
|
-
});
|
|
24
|
-
await mkdir(validatedSkillsDir, { recursive: true });
|
|
25
|
-
for (const [skillId, skill] of Object.entries(validatedSkills)) {
|
|
26
|
-
const parts = ["---", `name: ${JSON.stringify(skill.name)}`];
|
|
27
|
-
parts.push(`description: ${JSON.stringify(skill.description ?? "")}`);
|
|
28
|
-
if (skill.metadata && Object.keys(skill.metadata).length > 0) parts.push(formatMetadata(skill.metadata));
|
|
29
|
-
parts.push("---", "", skill.content || "");
|
|
30
|
-
const skillDir = join(validatedSkillsDir, skillId);
|
|
31
|
-
await mkdir(skillDir, { recursive: true });
|
|
32
|
-
await writeFile(join(skillDir, "SKILL.md"), parts.join("\n"), "utf8");
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
//#endregion
|
|
37
|
-
export { generateSkills };
|
|
38
|
-
//# sourceMappingURL=skill.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"skill.js","names":[],"sources":["../../../src/commands/pull-v4/skill.ts"],"sourcesContent":["import { mkdir, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { FullProjectDefinitionSchema } from '@inkeep/agents-core';\nimport { stringify } from 'yaml';\nimport { z } from 'zod';\nimport { validateGeneratorInput } from './simple-factory-generator';\n\nconst MySchema = FullProjectDefinitionSchema.shape.skills.unwrap().valueType;\nconst SkillsSchema = z.record(z.string(), MySchema);\nconst SkillsDirSchema = z.string().nonempty();\n\ntype SkillInput = z.input<typeof MySchema>;\n\ntype SkillMap = Record<string, SkillInput>;\n\nfunction formatMetadata(metadata: NonNullable<SkillInput['metadata']>): string {\n const yaml = stringify(metadata);\n const indented = yaml\n .split('\\n')\n .filter((line) => line.trim() !== '')\n .map((line) => ` ${line}`)\n .join('\\n');\n return `metadata:\\n${indented}`;\n}\n\nexport async function generateSkills(skills: SkillMap, skillsDir: string): Promise<void> {\n const validatedSkills = validateGeneratorInput(skills, {\n schema: SkillsSchema,\n errorLabel: 'skills',\n });\n const validatedSkillsDir = validateGeneratorInput(skillsDir, {\n schema: SkillsDirSchema,\n errorLabel: 'skills directory',\n });\n\n await mkdir(validatedSkillsDir, { recursive: true });\n\n for (const [skillId, skill] of Object.entries(validatedSkills)) {\n const parts: string[] = ['---', `name: ${JSON.stringify(skill.name)}`];\n parts.push(`description: ${JSON.stringify(skill.description ?? '')}`);\n\n if (skill.metadata && Object.keys(skill.metadata).length > 0) {\n parts.push(formatMetadata(skill.metadata));\n }\n\n parts.push('---', '', skill.content || '');\n\n const skillDir = join(validatedSkillsDir, skillId);\n await mkdir(skillDir, { recursive: true });\n\n const filePath = join(skillDir, 'SKILL.md');\n await writeFile(filePath, parts.join('\\n'), 'utf8');\n }\n}\n"],"mappings":";;;;;;;;AAOA,MAAM,WAAW,4BAA4B,MAAM,OAAO,QAAQ,CAAC;AACnE,MAAM,eAAe,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS;AACnD,MAAM,kBAAkB,EAAE,QAAQ,CAAC,UAAU;AAM7C,SAAS,eAAe,UAAuD;AAO7E,QAAO,cANM,UAAU,SAAS,CAE7B,MAAM,KAAK,CACX,QAAQ,SAAS,KAAK,MAAM,KAAK,GAAG,CACpC,KAAK,SAAS,KAAK,OAAO,CAC1B,KAAK,KAAK;;AAIf,eAAsB,eAAe,QAAkB,WAAkC;CACvF,MAAM,kBAAkB,uBAAuB,QAAQ;EACrD,QAAQ;EACR,YAAY;EACb,CAAC;CACF,MAAM,qBAAqB,uBAAuB,WAAW;EAC3D,QAAQ;EACR,YAAY;EACb,CAAC;AAEF,OAAM,MAAM,oBAAoB,EAAE,WAAW,MAAM,CAAC;AAEpD,MAAK,MAAM,CAAC,SAAS,UAAU,OAAO,QAAQ,gBAAgB,EAAE;EAC9D,MAAM,QAAkB,CAAC,OAAO,SAAS,KAAK,UAAU,MAAM,KAAK,GAAG;AACtE,QAAM,KAAK,gBAAgB,KAAK,UAAU,MAAM,eAAe,GAAG,GAAG;AAErE,MAAI,MAAM,YAAY,OAAO,KAAK,MAAM,SAAS,CAAC,SAAS,EACzD,OAAM,KAAK,eAAe,MAAM,SAAS,CAAC;AAG5C,QAAM,KAAK,OAAO,IAAI,MAAM,WAAW,GAAG;EAE1C,MAAM,WAAW,KAAK,oBAAoB,QAAQ;AAClD,QAAM,MAAM,UAAU,EAAE,WAAW,MAAM,CAAC;AAG1C,QAAM,UADW,KAAK,UAAU,WAAW,EACjB,MAAM,KAAK,KAAK,EAAE,OAAO"}
|