@inkeep/agents-cli 0.39.4 → 0.40.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/dist/_virtual/rolldown_runtime.js +7 -0
  2. package/dist/api.js +185 -0
  3. package/dist/commands/add.js +139 -0
  4. package/dist/commands/config.js +86 -0
  5. package/dist/commands/dev.js +259 -0
  6. package/dist/commands/init.js +360 -0
  7. package/dist/commands/list-agents.js +56 -0
  8. package/dist/commands/login.js +179 -0
  9. package/dist/commands/logout.js +56 -0
  10. package/dist/commands/profile.js +276 -0
  11. package/dist/{component-parser2.js → commands/pull-v3/component-parser.js} +16 -3
  12. package/dist/commands/pull-v3/component-updater.js +710 -0
  13. package/dist/commands/pull-v3/components/agent-generator.js +241 -0
  14. package/dist/commands/pull-v3/components/artifact-component-generator.js +127 -0
  15. package/dist/commands/pull-v3/components/context-config-generator.js +190 -0
  16. package/dist/commands/pull-v3/components/credential-generator.js +89 -0
  17. package/dist/commands/pull-v3/components/data-component-generator.js +102 -0
  18. package/dist/commands/pull-v3/components/environment-generator.js +170 -0
  19. package/dist/commands/pull-v3/components/external-agent-generator.js +75 -0
  20. package/dist/commands/pull-v3/components/function-tool-generator.js +94 -0
  21. package/dist/commands/pull-v3/components/mcp-tool-generator.js +86 -0
  22. package/dist/commands/pull-v3/components/project-generator.js +145 -0
  23. package/dist/commands/pull-v3/components/status-component-generator.js +92 -0
  24. package/dist/commands/pull-v3/components/sub-agent-generator.js +285 -0
  25. package/dist/commands/pull-v3/index.js +510 -0
  26. package/dist/commands/pull-v3/introspect-generator.js +278 -0
  27. package/dist/commands/pull-v3/llm-content-merger.js +192 -0
  28. package/dist/{new-component-generator.js → commands/pull-v3/new-component-generator.js} +14 -3
  29. package/dist/commands/pull-v3/project-comparator.js +914 -0
  30. package/dist/{project-index-generator.js → commands/pull-v3/project-index-generator.js} +1 -2
  31. package/dist/{project-validator.js → commands/pull-v3/project-validator.js} +4 -4
  32. package/dist/commands/pull-v3/targeted-typescript-placeholders.js +173 -0
  33. package/dist/commands/pull-v3/utils/component-registry.js +369 -0
  34. package/dist/commands/pull-v3/utils/component-tracker.js +165 -0
  35. package/dist/commands/pull-v3/utils/generator-utils.js +146 -0
  36. package/dist/commands/pull-v3/utils/model-provider-detector.js +44 -0
  37. package/dist/commands/push.js +326 -0
  38. package/dist/commands/status.js +89 -0
  39. package/dist/commands/update.js +97 -0
  40. package/dist/commands/whoami.js +38 -0
  41. package/dist/config.js +0 -1
  42. package/dist/env.js +30 -0
  43. package/dist/exports.js +3 -0
  44. package/dist/index.js +28 -196514
  45. package/dist/instrumentation.js +47 -0
  46. package/dist/types/agent.js +1 -0
  47. package/dist/types/tsx.d.d.ts +1 -0
  48. package/dist/utils/background-version-check.js +19 -0
  49. package/dist/utils/ci-environment.js +87 -0
  50. package/dist/utils/cli-pipeline.js +158 -0
  51. package/dist/utils/config.js +290 -0
  52. package/dist/utils/credentials.js +132 -0
  53. package/dist/utils/environment-loader.js +28 -0
  54. package/dist/utils/file-finder.js +62 -0
  55. package/dist/utils/json-comparator.js +185 -0
  56. package/dist/utils/json-comparison.js +232 -0
  57. package/dist/utils/mcp-runner.js +120 -0
  58. package/dist/utils/model-config.js +182 -0
  59. package/dist/utils/package-manager.js +58 -0
  60. package/dist/utils/profile-config.js +85 -0
  61. package/dist/utils/profiles/index.js +4 -0
  62. package/dist/utils/profiles/profile-manager.js +219 -0
  63. package/dist/utils/profiles/types.js +62 -0
  64. package/dist/utils/project-directory.js +33 -0
  65. package/dist/utils/project-loader.js +29 -0
  66. package/dist/utils/schema-introspection.js +44 -0
  67. package/dist/utils/templates.js +198 -0
  68. package/dist/utils/tsx-loader.js +27 -0
  69. package/dist/utils/url.js +26 -0
  70. package/dist/utils/version-check.js +79 -0
  71. package/package.json +4 -19
  72. package/dist/component-parser.js +0 -4
  73. package/dist/component-updater.js +0 -4
  74. package/dist/config2.js +0 -4
  75. package/dist/credential-stores.js +0 -4
  76. package/dist/environment-generator.js +0 -4
  77. package/dist/nodefs.js +0 -27
  78. package/dist/opfs-ahp.js +0 -368
  79. package/dist/project-loader.js +0 -4
  80. package/dist/tsx-loader.js +0 -4
@@ -0,0 +1,62 @@
1
+ import { z } from "zod";
2
+
3
+ //#region src/utils/profiles/types.ts
4
+ /**
5
+ * Baked-in URLs for Inkeep Cloud deployment
6
+ */
7
+ const CLOUD_REMOTE = {
8
+ manageApi: "https://manage-api.inkeep.com",
9
+ manageUi: "https://manage.inkeep.com",
10
+ runApi: "https://run-api.inkeep.com"
11
+ };
12
+ /**
13
+ * Schema for explicit remote URLs (custom/local deployments)
14
+ */
15
+ const explicitRemoteSchema = z.object({
16
+ manageApi: z.string().url("manageApi must be a valid URL"),
17
+ manageUi: z.string().url("manageUi must be a valid URL"),
18
+ runApi: z.string().url("runApi must be a valid URL")
19
+ });
20
+ /**
21
+ * Schema for remote configuration - either 'cloud' shorthand or explicit URLs
22
+ */
23
+ const remoteSchema = z.union([z.literal("cloud"), explicitRemoteSchema]);
24
+ /**
25
+ * Profile name validation - alphanumeric + hyphens only
26
+ */
27
+ const profileNameSchema = z.string().min(1, "Profile name cannot be empty").max(64, "Profile name too long (max 64 characters)").regex(/^[a-z0-9-]+$/, "Profile name must be lowercase alphanumeric with hyphens only");
28
+ /**
29
+ * Schema for a single profile configuration
30
+ */
31
+ const profileSchema = z.object({
32
+ remote: remoteSchema,
33
+ credential: z.string().min(1, "Credential reference cannot be empty"),
34
+ environment: z.string().min(1, "Environment cannot be empty")
35
+ });
36
+ /**
37
+ * Schema for the entire profiles.yaml configuration
38
+ * Note: We use z.record(z.string(), profileSchema) for Zod v4 compatibility
39
+ * Profile name validation is done separately in addProfile
40
+ */
41
+ const profilesConfigSchema = z.object({
42
+ activeProfile: z.string().min(1, "activeProfile cannot be empty"),
43
+ profiles: z.record(z.string(), profileSchema)
44
+ });
45
+ /**
46
+ * Default cloud profile configuration
47
+ */
48
+ const DEFAULT_CLOUD_PROFILE = {
49
+ remote: "cloud",
50
+ credential: "inkeep-cloud",
51
+ environment: "production"
52
+ };
53
+ /**
54
+ * Default profiles.yaml content when creating for the first time
55
+ */
56
+ const DEFAULT_PROFILES_CONFIG = {
57
+ activeProfile: "cloud",
58
+ profiles: { cloud: DEFAULT_CLOUD_PROFILE }
59
+ };
60
+
61
+ //#endregion
62
+ export { CLOUD_REMOTE, DEFAULT_CLOUD_PROFILE, DEFAULT_PROFILES_CONFIG, explicitRemoteSchema, profileNameSchema, profileSchema, profilesConfigSchema, remoteSchema };
@@ -0,0 +1,33 @@
1
+ import { existsSync } from "node:fs";
2
+ import { join, resolve } from "node:path";
3
+ import { findUp } from "find-up";
4
+
5
+ //#region src/utils/project-directory.ts
6
+ /**
7
+ * Find project directory by looking for inkeep.config.ts
8
+ * @param projectId - Optional project ID or path to look for
9
+ * @param configPath - Optional specific config file path to use
10
+ * @returns Path to project directory or null if not found
11
+ */
12
+ async function findProjectDirectory(projectId, configPath) {
13
+ if (configPath) {
14
+ const absoluteConfigPath = resolve(process.cwd(), configPath);
15
+ if (existsSync(absoluteConfigPath)) return resolve(absoluteConfigPath, "..");
16
+ }
17
+ if (projectId) {
18
+ if (projectId.includes("/") || projectId.includes("\\")) {
19
+ const projectPath = resolve(process.cwd(), projectId);
20
+ if (existsSync(join(projectPath, "inkeep.config.ts"))) return projectPath;
21
+ } else {
22
+ const projectPath = join(process.cwd(), projectId);
23
+ if (existsSync(join(projectPath, "inkeep.config.ts"))) return projectPath;
24
+ }
25
+ return null;
26
+ }
27
+ const foundConfigPath = await findUp("inkeep.config.ts");
28
+ if (foundConfigPath) return resolve(foundConfigPath, "..");
29
+ return null;
30
+ }
31
+
32
+ //#endregion
33
+ export { findProjectDirectory };
@@ -0,0 +1,29 @@
1
+ import { importWithTypeScriptSupport } from "./tsx-loader.js";
2
+ import { existsSync } from "node:fs";
3
+ import { join } from "node:path";
4
+
5
+ //#region src/utils/project-loader.ts
6
+ /**
7
+ * Load and validate project from index.ts
8
+ *
9
+ * This utility is shared between push and pull commands to ensure
10
+ * consistent project loading behavior across the CLI.
11
+ *
12
+ * @param projectDir - The directory containing the index.ts file
13
+ * @returns The loaded Project instance
14
+ * @throws Error if index.ts not found or no valid project export found
15
+ */
16
+ async function loadProject(projectDir) {
17
+ const indexPath = join(projectDir, "index.ts");
18
+ if (!existsSync(indexPath)) throw new Error(`index.ts not found in project directory: ${projectDir}`);
19
+ const module = await importWithTypeScriptSupport(indexPath);
20
+ const exports = Object.keys(module);
21
+ for (const exportKey of exports) {
22
+ const value = module[exportKey];
23
+ if (value && typeof value === "object" && value.__type === "project") return value;
24
+ }
25
+ throw new Error("No project export found in index.ts. Expected an export with __type = \"project\"");
26
+ }
27
+
28
+ //#endregion
29
+ export { loadProject };
@@ -0,0 +1,44 @@
1
+ import { z } from "zod";
2
+
3
+ //#region src/utils/schema-introspection.ts
4
+ /**
5
+ * Schema Introspection Utilities
6
+ *
7
+ * Utilities to extract required fields and other metadata from Zod schemas.
8
+ * This ensures CLI generators stay in sync with the actual validation schemas.
9
+ */
10
+ /**
11
+ * Simple utility to get required fields by attempting validation with empty object
12
+ * and analyzing which fields are reported as missing
13
+ */
14
+ function getRequiredFieldsFromValidation(schema) {
15
+ try {
16
+ schema.parse({});
17
+ return [];
18
+ } catch (error) {
19
+ if (error instanceof z.ZodError) return error.issues.filter((err) => err.code === "invalid_type" && err.expected !== "undefined").map((err) => err.path[0]).filter((field) => typeof field === "string").filter((field, index, arr) => arr.indexOf(field) === index);
20
+ return [];
21
+ }
22
+ }
23
+ /**
24
+ * Extract required field names from a Zod object schema
25
+ */
26
+ function getRequiredFields(schema) {
27
+ return getRequiredFieldsFromValidation(schema);
28
+ }
29
+ /**
30
+ * Get a human-readable summary of schema requirements
31
+ */
32
+ function getSchemaInfo(schema) {
33
+ const requiredFields = getRequiredFields(schema);
34
+ let allFields = [];
35
+ if ("shape" in schema && schema.shape) allFields = Object.keys(schema.shape);
36
+ return {
37
+ requiredFields,
38
+ optionalFields: allFields.filter((field) => !requiredFields.includes(field)),
39
+ allFields
40
+ };
41
+ }
42
+
43
+ //#endregion
44
+ export { getRequiredFields, getSchemaInfo };
@@ -0,0 +1,198 @@
1
+ import { getLogger } from "@inkeep/agents-core";
2
+ import path from "node:path";
3
+ import fs from "fs-extra";
4
+ import degit from "degit";
5
+
6
+ //#region src/utils/templates.ts
7
+ getLogger("templates");
8
+ async function cloneTemplate(templatePath, targetPath, replacements) {
9
+ await fs.mkdir(targetPath, { recursive: true });
10
+ const emitter = degit(templatePath.replace("https://github.com/", ""));
11
+ try {
12
+ await emitter.clone(targetPath);
13
+ if (replacements && replacements.length > 0) await replaceContentInFiles(targetPath, replacements);
14
+ } catch (_error) {
15
+ console.log(`❌ Error cloning template: ${_error}`);
16
+ process.exit(1);
17
+ }
18
+ }
19
+ async function cloneTemplateLocal(templatePath, targetPath, replacements) {
20
+ await fs.mkdir(targetPath, { recursive: true });
21
+ try {
22
+ await fs.copy(templatePath, targetPath, {
23
+ overwrite: true,
24
+ errorOnExist: false
25
+ });
26
+ if (replacements && replacements.length > 0) await replaceContentInFiles(targetPath, replacements);
27
+ } catch (error) {
28
+ console.error(`Failed to clone template from ${templatePath}:`, error);
29
+ process.exit(1);
30
+ }
31
+ }
32
+ /**
33
+ * Replace content in cloned template files
34
+ */
35
+ async function replaceContentInFiles(targetPath, replacements) {
36
+ for (const replacement of replacements) {
37
+ const filePath = path.join(targetPath, replacement.filePath);
38
+ if (!await fs.pathExists(filePath)) {
39
+ console.warn(`Warning: File ${filePath} not found, skipping replacements`);
40
+ continue;
41
+ }
42
+ const updatedContent = await replaceObjectProperties(await fs.readFile(filePath, "utf-8"), replacement.replacements);
43
+ await fs.writeFile(filePath, updatedContent, "utf-8");
44
+ }
45
+ }
46
+ /**
47
+ * Replace object properties in TypeScript code content
48
+ */
49
+ async function replaceObjectProperties(content, replacements) {
50
+ let updatedContent = content;
51
+ for (const [propertyPath, replacement] of Object.entries(replacements)) updatedContent = replaceObjectProperty(updatedContent, propertyPath, replacement);
52
+ return updatedContent;
53
+ }
54
+ /**
55
+ * Replace a specific object property in TypeScript code
56
+ * This implementation uses line-by-line parsing for better accuracy
57
+ * If the property doesn't exist, it will be added to the object
58
+ */
59
+ function replaceObjectProperty(content, propertyPath, replacement) {
60
+ if (content.match(new RegExp(`^(.+{[^{}]*${propertyPath}\\s*:\\s*{[^{}]*}[^{}]*}.*)$`, "m"))) {
61
+ const singleLinePattern = /* @__PURE__ */ new RegExp(`((^|\\s|{)${propertyPath}\\s*:\\s*)({[^}]*})`);
62
+ return content.replace(singleLinePattern, `$1${JSON.stringify(replacement).replace(/"/g, "'").replace(/:/g, ": ").replace(/,/g, ", ")}`);
63
+ }
64
+ const replacementStr = JSON.stringify(replacement, null, 2).replace(/"/g, "'");
65
+ const lines = content.split("\n");
66
+ const result = [];
67
+ let inTargetProperty = false;
68
+ let braceCount = 0;
69
+ let targetPropertyIndent = "";
70
+ let foundProperty = false;
71
+ for (let i = 0; i < lines.length; i++) {
72
+ const line = lines[i];
73
+ const trimmedLine = line.trim();
74
+ if (inTargetProperty) {
75
+ for (const char of line) {
76
+ if (char === "{") braceCount++;
77
+ if (char === "}") braceCount--;
78
+ }
79
+ if (braceCount <= 0) {
80
+ const hasTrailingComma = line.includes(",") || i + 1 < lines.length && lines[i + 1].trim().startsWith("}") === false && lines[i + 1].trim() !== "";
81
+ const indentedReplacement = replacementStr.split("\n").map((replacementLine, index) => {
82
+ if (index === 0) return `${targetPropertyIndent}${propertyPath}: ${replacementLine}`;
83
+ return `${targetPropertyIndent}${replacementLine}`;
84
+ }).join("\n");
85
+ result.push(`${indentedReplacement}${hasTrailingComma ? "," : ""}`);
86
+ inTargetProperty = false;
87
+ foundProperty = true;
88
+ continue;
89
+ }
90
+ continue;
91
+ }
92
+ const propertyPattern = /* @__PURE__ */ new RegExp(`(^|\\s+)${propertyPath}\\s*:`);
93
+ if (trimmedLine.startsWith(`${propertyPath}:`) || propertyPattern.test(line)) {
94
+ inTargetProperty = true;
95
+ braceCount = 0;
96
+ if (line.includes(" = { ")) targetPropertyIndent = `${line.match(/^\s*/)?.[0] || ""} `;
97
+ else {
98
+ const propertyMatch = line.match(/* @__PURE__ */ new RegExp(`(.*?)(^|\\s+)${propertyPath}\\s*:`));
99
+ targetPropertyIndent = propertyMatch ? propertyMatch[1] : line.match(/^\s*/)?.[0] || "";
100
+ }
101
+ for (const char of line) {
102
+ if (char === "{") braceCount++;
103
+ if (char === "}") braceCount--;
104
+ }
105
+ if (braceCount <= 0) {
106
+ const hasTrailingComma = line.includes(",");
107
+ const indentedReplacement = replacementStr.split("\n").map((replacementLine, index) => {
108
+ if (index === 0) return `${targetPropertyIndent}${propertyPath}: ${replacementLine}`;
109
+ return `${targetPropertyIndent}${replacementLine}`;
110
+ }).join("\n");
111
+ result.push(`${indentedReplacement}${hasTrailingComma ? "," : ""}`);
112
+ inTargetProperty = false;
113
+ foundProperty = true;
114
+ continue;
115
+ }
116
+ continue;
117
+ }
118
+ result.push(line);
119
+ }
120
+ if (!foundProperty) return injectPropertyIntoObject(result.join("\n"), propertyPath, replacement);
121
+ return result.join("\n");
122
+ }
123
+ /**
124
+ * Inject a new property into a TypeScript object when the property doesn't exist
125
+ */
126
+ function injectPropertyIntoObject(content, propertyPath, replacement) {
127
+ const replacementStr = JSON.stringify(replacement, null, 2).replace(/"/g, "'");
128
+ const lines = content.split("\n");
129
+ const result = [];
130
+ let foundObjectStart = false;
131
+ let objectDepth = 0;
132
+ let insertionPoint = -1;
133
+ let baseIndent = "";
134
+ for (let i = 0; i < lines.length; i++) {
135
+ const line = lines[i];
136
+ const trimmedLine = line.trim();
137
+ if (!foundObjectStart && (trimmedLine.includes("({") || trimmedLine.endsWith(" = {") || line.includes(" = { "))) {
138
+ foundObjectStart = true;
139
+ baseIndent = line.match(/^\s*/)?.[0] || "";
140
+ objectDepth = 0;
141
+ for (const char of line) {
142
+ if (char === "{") objectDepth++;
143
+ if (char === "}") objectDepth--;
144
+ }
145
+ } else if (foundObjectStart) {
146
+ for (const char of line) {
147
+ if (char === "{") objectDepth++;
148
+ if (char === "}") objectDepth--;
149
+ }
150
+ if (objectDepth === 0 && trimmedLine.startsWith("}")) {
151
+ insertionPoint = i;
152
+ break;
153
+ }
154
+ }
155
+ }
156
+ if (insertionPoint !== -1) {
157
+ const propertyIndent = `${baseIndent} `;
158
+ let needsCommaPrefix = false;
159
+ if (insertionPoint > 0) {
160
+ const prevLine = lines[insertionPoint - 1].trim();
161
+ needsCommaPrefix = prevLine !== "" && !prevLine.endsWith(",") && !prevLine.startsWith("}");
162
+ }
163
+ const indentedReplacement = replacementStr.split("\n").map((replacementLine, index) => {
164
+ if (index === 0) return `${propertyIndent}${propertyPath}: ${replacementLine}`;
165
+ return `${propertyIndent}${replacementLine}`;
166
+ }).join("\n");
167
+ for (let i = 0; i < lines.length; i++) {
168
+ if (i === insertionPoint) result.push(indentedReplacement);
169
+ if (i === insertionPoint - 1 && needsCommaPrefix) result.push(`${lines[i]},`);
170
+ else result.push(lines[i]);
171
+ }
172
+ return result.join("\n");
173
+ }
174
+ console.warn(`Could not inject property "${propertyPath}" - no suitable object found in content`);
175
+ return content;
176
+ }
177
+ async function getAvailableTemplates(templatePath = "template-projects", local) {
178
+ if (local && local.length > 0) {
179
+ const fullTemplatePath = path.join(local, templatePath);
180
+ const items = await fs.readdir(fullTemplatePath);
181
+ const directories = [];
182
+ for (const item of items) if ((await fs.stat(path.join(fullTemplatePath, item))).isDirectory() && item !== "weather-project") directories.push(item);
183
+ return directories;
184
+ }
185
+ const response = await fetch(`https://api.github.com/repos/inkeep/agents/contents/agents-cookbook/${templatePath}`);
186
+ if (!response.ok) throw new Error(`Failed to fetch templates. Please check your internet connection and try again.`);
187
+ let contents;
188
+ try {
189
+ contents = await response.json();
190
+ } catch (error) {
191
+ throw new Error(`Failed to parse templates response. Please check your internet connection and try again. ${error}`);
192
+ }
193
+ if (!Array.isArray(contents)) throw new Error("Unexpected response format from templates. Please check your internet connection and try again");
194
+ return contents.filter((item) => item.type === "dir" && item.name !== "weather-project").map((item) => item.name);
195
+ }
196
+
197
+ //#endregion
198
+ export { cloneTemplate, cloneTemplateLocal, getAvailableTemplates, replaceContentInFiles, replaceObjectProperties };
@@ -0,0 +1,27 @@
1
+ import { extname } from "node:path";
2
+ import { pathToFileURL } from "node:url";
3
+ import { register } from "tsx/esm/api";
4
+
5
+ //#region src/utils/tsx-loader.ts
6
+ /**
7
+ * Dynamically imports a file with TypeScript support
8
+ * Registers tsx loader for .ts files automatically
9
+ */
10
+ async function importWithTypeScriptSupport(filePath) {
11
+ if (extname(filePath) === ".ts") try {
12
+ const unregister = register();
13
+ try {
14
+ return await import(pathToFileURL(filePath).href);
15
+ } finally {
16
+ unregister();
17
+ }
18
+ } catch (error) {
19
+ const errorMessage = error instanceof Error ? error.message : String(error);
20
+ if (errorMessage.includes("Dynamic require") || errorMessage.includes("tsx") || errorMessage.includes("register")) throw new Error(`Failed to load TypeScript file ${filePath}. Make sure tsx is installed: ${errorMessage}`);
21
+ throw error;
22
+ }
23
+ return await import(pathToFileURL(filePath).href);
24
+ }
25
+
26
+ //#endregion
27
+ export { importWithTypeScriptSupport };
@@ -0,0 +1,26 @@
1
+ //#region src/utils/url.ts
2
+ /**
3
+ * Normalizes a base URL by removing trailing slashes and validating format
4
+ * @param url The URL to normalize
5
+ * @returns The normalized URL
6
+ * @throws Error if URL is invalid
7
+ */
8
+ function normalizeBaseUrl(url) {
9
+ const trimmedUrl = url.trim();
10
+ if (!trimmedUrl.match(/^https?:\/\//i)) throw new Error(`Invalid URL format: ${url}. Must start with http:// or https://`);
11
+ return trimmedUrl.replace(/\/+$/, "");
12
+ }
13
+ /**
14
+ * Constructs an agent view URL for the management UI
15
+ * @param manageUiUrl The base management UI URL
16
+ * @param tenantId The tenant ID
17
+ * @param projectId The project ID
18
+ * @param agentId The agent ID
19
+ * @returns The complete agent view URL
20
+ */
21
+ function buildAgentViewUrl(manageUiUrl, tenantId, projectId, agentId) {
22
+ return `${normalizeBaseUrl(manageUiUrl || "http://localhost:3000")}/${tenantId}/projects/${projectId}/agents/${agentId}`;
23
+ }
24
+
25
+ //#endregion
26
+ export { buildAgentViewUrl, normalizeBaseUrl };
@@ -0,0 +1,79 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+
5
+ //#region src/utils/version-check.ts
6
+ const __dirname = dirname(fileURLToPath(import.meta.url));
7
+ /**
8
+ * The default package name for version checks and updates
9
+ */
10
+ const DEFAULT_PACKAGE_NAME = "@inkeep/agents-cli";
11
+ /**
12
+ * Get the current installed version from package.json
13
+ */
14
+ function getCurrentVersion() {
15
+ let packageJsonPath = join(__dirname, "..", "package.json");
16
+ if (!existsSync(packageJsonPath)) packageJsonPath = join(__dirname, "..", "..", "package.json");
17
+ return JSON.parse(readFileSync(packageJsonPath, "utf-8")).version;
18
+ }
19
+ /**
20
+ * Fetch the latest version from npm registry
21
+ */
22
+ async function getLatestVersion(packageName = DEFAULT_PACKAGE_NAME) {
23
+ const controller = new AbortController();
24
+ const timeoutId = setTimeout(() => controller.abort(), 1e4);
25
+ try {
26
+ const response = await fetch(`https://registry.npmjs.org/${packageName}/latest`, { signal: controller.signal });
27
+ if (!response.ok) throw new Error(`Failed to fetch latest version: ${response.statusText}`);
28
+ return (await response.json()).version;
29
+ } catch (error) {
30
+ if (error instanceof Error && error.name === "AbortError") throw new Error("Unable to check for updates: Request timed out after 10 seconds");
31
+ throw new Error(`Unable to check for updates: ${error instanceof Error ? error.message : "Unknown error"}`);
32
+ } finally {
33
+ clearTimeout(timeoutId);
34
+ }
35
+ }
36
+ /**
37
+ * Compare two semver versions
38
+ * Returns: -1 if v1 < v2, 0 if v1 === v2, 1 if v1 > v2
39
+ *
40
+ * Note: This is a simplified semver comparison that handles basic major.minor.patch versions.
41
+ * It does NOT handle pre-release versions (e.g., 1.0.0-beta.1) or build metadata (e.g., 1.0.0+build.1).
42
+ * Pre-release tags and build metadata will be stripped before comparison.
43
+ *
44
+ * For the Inkeep CLI use case, this is sufficient as we only publish stable releases.
45
+ */
46
+ function compareVersions(v1, v2) {
47
+ const cleanV1 = v1.split("-")[0].split("+")[0];
48
+ const cleanV2 = v2.split("-")[0].split("+")[0];
49
+ const parts1 = cleanV1.split(".").map(Number);
50
+ const parts2 = cleanV2.split(".").map(Number);
51
+ for (let i = 0; i < Math.max(parts1.length, parts2.length); i++) {
52
+ const part1 = parts1[i] || 0;
53
+ const part2 = parts2[i] || 0;
54
+ if (part1 < part2) return -1;
55
+ if (part1 > part2) return 1;
56
+ }
57
+ return 0;
58
+ }
59
+ /**
60
+ * Check if an update is available
61
+ */
62
+ async function checkForUpdate() {
63
+ const current = getCurrentVersion();
64
+ const latest = await getLatestVersion();
65
+ return {
66
+ current,
67
+ latest,
68
+ needsUpdate: compareVersions(current, latest) < 0
69
+ };
70
+ }
71
+ /**
72
+ * Get the changelog URL for the package
73
+ */
74
+ function getChangelogUrl() {
75
+ return `https://github.com/inkeep/agents/blob/main/agents-cli/CHANGELOG.md`;
76
+ }
77
+
78
+ //#endregion
79
+ export { DEFAULT_PACKAGE_NAME, checkForUpdate, compareVersions, getChangelogUrl, getCurrentVersion, getLatestVersion };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inkeep/agents-cli",
3
- "version": "0.39.4",
3
+ "version": "0.40.0",
4
4
  "description": "Inkeep CLI tool",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -23,47 +23,31 @@
23
23
  "@ai-sdk/anthropic": "3.0.0-beta.66",
24
24
  "@ai-sdk/google": "3.0.0-beta.62",
25
25
  "@ai-sdk/openai": "3.0.0-beta.74",
26
- "@babel/parser": "^7.23.0",
27
- "@babel/types": "^7.23.0",
28
- "@better-auth/sso": "^1.4.0",
29
26
  "@clack/prompts": "^0.11.0",
30
- "@nangohq/node": "^0.69.14",
31
- "@opentelemetry/api-logs": "^0.206.0",
32
- "@opentelemetry/instrumentation": "^0.206.0",
33
- "@opentelemetry/sdk-logs": "^0.206.0",
34
27
  "@vercel/otel": "^2.0.1",
35
28
  "ai": "6.0.0-beta.124",
36
- "ast-types": "^0.14.2",
37
29
  "chalk": "^5.3.0",
38
30
  "cli-table3": "^0.6.3",
39
31
  "commander": "^14.0.0",
40
32
  "degit": "^2.8.4",
41
- "destr": "^2.0.3",
42
33
  "dotenv": "^17.2.1",
43
- "drizzle-orm": "^0.44.5",
44
34
  "find-up": "^7.0.0",
45
35
  "fs-extra": "^11.2.0",
46
36
  "json-schema-to-zod": "^2.6.1",
47
37
  "keytar": "^7.9.0",
48
38
  "langfuse-vercel": "^3.38.6",
49
- "picocolors": "^1.1.1",
50
- "pg": "^8.16.3",
51
- "pino": "^9.11.0",
52
- "recast": "^0.23.0",
53
- "traverse": "^0.6.10",
54
39
  "ts-morph": "^26.0.0",
55
40
  "tsx": "^4.20.5",
56
41
  "open": "^10.2.0",
57
42
  "yaml": "^2.7.0",
58
- "@inkeep/agents-core": "^0.39.4",
59
- "@inkeep/agents-sdk": "^0.39.4"
43
+ "@inkeep/agents-core": "^0.40.0",
44
+ "@inkeep/agents-sdk": "^0.40.0"
60
45
  },
61
46
  "devDependencies": {
62
47
  "@types/degit": "^2.8.6",
63
48
  "@types/fs-extra": "^11.0.4",
64
49
  "@types/node": "^20.10.0",
65
50
  "@vitest/coverage-v8": "^3.2.4",
66
- "pino-pretty": "^13.1.1",
67
51
  "tsdown": "^0.18.0",
68
52
  "typescript": "^5.9.2",
69
53
  "vitest": "^3.2.4"
@@ -88,6 +72,7 @@
88
72
  "directory": "agents-cli"
89
73
  },
90
74
  "scripts": {
75
+ "knip": "knip --directory .. --workspace agents-cli --dependencies",
91
76
  "build": "tsdown",
92
77
  "cli": "node ./dist/index.js",
93
78
  "postinstall": "node scripts/ensure-keytar.mjs || true",
@@ -1,4 +0,0 @@
1
- #!/usr/bin/env node
2
- import { t as buildComponentRegistryFromParsing } from "./component-parser2.js";
3
-
4
- export { buildComponentRegistryFromParsing };
@@ -1,4 +0,0 @@
1
- #!/usr/bin/env node
2
- import { a as copyProjectToTemp, i as cleanupStaleComponents, o as updateModifiedComponents, r as checkAndPromptForStaleComponentCleanup } from "./index.js";
3
-
4
- export { updateModifiedComponents };
package/dist/config2.js DELETED
@@ -1,4 +0,0 @@
1
- #!/usr/bin/env node
2
- import { A as findConfigFile, F as validateConfiguration, M as loadConfig, N as loadConfigFromFile, P as maskSensitiveConfig, j as getConfigFileNames, k as findAllConfigFiles } from "./index.js";
3
-
4
- export { validateConfiguration };
@@ -1,4 +0,0 @@
1
- #!/usr/bin/env node
2
- import { q as KeyChainStore } from "./index.js";
3
-
4
- export { KeyChainStore };
@@ -1,4 +0,0 @@
1
- #!/usr/bin/env node
2
- import { _ as generateEnvironmentIndexFile, b as generateEnvironmentSettingsFile, g as generateEnvironmentIndexDefinition, h as generateEnvironmentFile, v as generateEnvironmentIndexImports, x as generateEnvironmentSettingsImports, y as generateEnvironmentSettingsDefinition } from "./index.js";
3
-
4
- export { generateEnvironmentIndexFile };
package/dist/nodefs.js DELETED
@@ -1,27 +0,0 @@
1
- #!/usr/bin/env node
2
- import { B as ur, G as u, L as C } from "./index.js";
3
- import * as s from "fs";
4
- import * as o from "path";
5
-
6
- //#region ../node_modules/.pnpm/@electric-sql+pglite@0.3.14/node_modules/@electric-sql/pglite/dist/fs/nodefs.js
7
- u();
8
- var m = class extends ur {
9
- constructor(t) {
10
- super(t), this.rootDir = o.resolve(t), s.existsSync(o.join(this.rootDir)) || s.mkdirSync(this.rootDir);
11
- }
12
- async init(t, e) {
13
- return this.pg = t, { emscriptenOpts: {
14
- ...e,
15
- preRun: [...e.preRun || [], (r) => {
16
- let c = r.FS.filesystems.NODEFS;
17
- r.FS.mkdir(C), r.FS.mount(c, { root: this.rootDir }, C);
18
- }]
19
- } };
20
- }
21
- async closeFs() {
22
- this.pg.Module.FS.quit();
23
- }
24
- };
25
-
26
- //#endregion
27
- export { m as NodeFS };