@inkeep/agents-cli 0.0.0-dev-20260212002106 → 0.0.0-dev-20260212003026
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/api.js +60 -0
- package/dist/commands/add-ui.js +179 -0
- package/dist/commands/add.js +11 -0
- package/dist/commands/pull-v3/targeted-typescript-placeholders.js +1 -1
- package/dist/index.js +1 -1
- package/dist/utils/cli-pipeline.js +2 -2
- package/dist/utils/config.js +19 -2
- package/package.json +4 -4
package/dist/api.js
CHANGED
|
@@ -141,6 +141,66 @@ var ManagementApiClient = class ManagementApiClient extends BaseApiClient {
|
|
|
141
141
|
}
|
|
142
142
|
return allProjects;
|
|
143
143
|
}
|
|
144
|
+
async getDataComponent(componentId) {
|
|
145
|
+
const tenantId = this.checkTenantId();
|
|
146
|
+
const projectId = this.getProjectId();
|
|
147
|
+
const response = await this.authenticatedFetch(`${this.apiUrl}/manage/tenants/${tenantId}/projects/${projectId}/data-components/${componentId}`, { method: "GET" });
|
|
148
|
+
if (response.status === 404) return null;
|
|
149
|
+
if (!response.ok) {
|
|
150
|
+
const err = await response.text().catch(() => "");
|
|
151
|
+
throw new Error(`Failed to fetch data component: ${response.statusText}${err ? `\n${err}` : ""}`);
|
|
152
|
+
}
|
|
153
|
+
return (await response.json()).data ?? null;
|
|
154
|
+
}
|
|
155
|
+
async listDataComponents() {
|
|
156
|
+
const tenantId = this.checkTenantId();
|
|
157
|
+
const projectId = this.getProjectId();
|
|
158
|
+
const all = [];
|
|
159
|
+
let page = 1;
|
|
160
|
+
const limit = 100;
|
|
161
|
+
let result;
|
|
162
|
+
do {
|
|
163
|
+
const response = await this.authenticatedFetch(`${this.apiUrl}/manage/tenants/${tenantId}/projects/${projectId}/data-components?page=${page}&limit=${limit}`, { method: "GET" });
|
|
164
|
+
if (!response.ok) {
|
|
165
|
+
const err = await response.text().catch(() => "");
|
|
166
|
+
throw new Error(`Failed to list data components: ${response.statusText}${err ? `\n${err}` : ""}`);
|
|
167
|
+
}
|
|
168
|
+
result = await response.json();
|
|
169
|
+
all.push(...result.data || []);
|
|
170
|
+
page++;
|
|
171
|
+
} while (result.data?.length === limit && all.length < (result.pagination?.total ?? 0));
|
|
172
|
+
return all;
|
|
173
|
+
}
|
|
174
|
+
async getArtifactComponent(componentId) {
|
|
175
|
+
const tenantId = this.checkTenantId();
|
|
176
|
+
const projectId = this.getProjectId();
|
|
177
|
+
const response = await this.authenticatedFetch(`${this.apiUrl}/manage/tenants/${tenantId}/projects/${projectId}/artifact-components/${componentId}`, { method: "GET" });
|
|
178
|
+
if (response.status === 404) return null;
|
|
179
|
+
if (!response.ok) {
|
|
180
|
+
const err = await response.text().catch(() => "");
|
|
181
|
+
throw new Error(`Failed to fetch artifact component: ${response.statusText}${err ? `\n${err}` : ""}`);
|
|
182
|
+
}
|
|
183
|
+
return (await response.json()).data ?? null;
|
|
184
|
+
}
|
|
185
|
+
async listArtifactComponents() {
|
|
186
|
+
const tenantId = this.checkTenantId();
|
|
187
|
+
const projectId = this.getProjectId();
|
|
188
|
+
const all = [];
|
|
189
|
+
let page = 1;
|
|
190
|
+
const limit = 100;
|
|
191
|
+
let result;
|
|
192
|
+
do {
|
|
193
|
+
const response = await this.authenticatedFetch(`${this.apiUrl}/manage/tenants/${tenantId}/projects/${projectId}/artifact-components?page=${page}&limit=${limit}`, { method: "GET" });
|
|
194
|
+
if (!response.ok) {
|
|
195
|
+
const err = await response.text().catch(() => "");
|
|
196
|
+
throw new Error(`Failed to list artifact components: ${response.statusText}${err ? `\n${err}` : ""}`);
|
|
197
|
+
}
|
|
198
|
+
result = await response.json();
|
|
199
|
+
all.push(...result.data || []);
|
|
200
|
+
page++;
|
|
201
|
+
} while (result.data?.length === limit && all.length < (result.pagination?.total ?? 0));
|
|
202
|
+
return all;
|
|
203
|
+
}
|
|
144
204
|
};
|
|
145
205
|
var ExecutionApiClient = class ExecutionApiClient extends BaseApiClient {
|
|
146
206
|
constructor(apiUrl, tenantId, projectId, apiKey, isCI = false) {
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { ManagementApiClient } from "../api.js";
|
|
2
|
+
import { findConfigFile, findProjectConfig } from "../utils/config.js";
|
|
3
|
+
import { initializeCommand } from "../utils/cli-pipeline.js";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import * as p from "@clack/prompts";
|
|
6
|
+
import chalk from "chalk";
|
|
7
|
+
import { findUp } from "find-up";
|
|
8
|
+
import fs from "fs-extra";
|
|
9
|
+
import { Project } from "ts-morph";
|
|
10
|
+
|
|
11
|
+
//#region src/commands/add-ui.ts
|
|
12
|
+
const UI_DIR_RELATIVE = "apps/agents-ui/src/ui";
|
|
13
|
+
function toPascalCase(name) {
|
|
14
|
+
if (!name?.trim()) return "Component";
|
|
15
|
+
return name.trim().replace(/[-_]+/g, " ").split(/\s+/).map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join("");
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Ensures the component declaration is exported using AST. Finds the first
|
|
19
|
+
* function or const component (PascalCase name) and adds export if missing.
|
|
20
|
+
*/
|
|
21
|
+
function ensureExported(code) {
|
|
22
|
+
try {
|
|
23
|
+
const sourceFile = new Project({
|
|
24
|
+
useInMemoryFileSystem: true,
|
|
25
|
+
compilerOptions: { jsx: 1 }
|
|
26
|
+
}).createSourceFile("temp.tsx", code);
|
|
27
|
+
const candidates = [];
|
|
28
|
+
for (const fn of sourceFile.getFunctions()) if (fn.getName()) candidates.push({
|
|
29
|
+
start: fn.getStart(),
|
|
30
|
+
type: "function",
|
|
31
|
+
node: fn
|
|
32
|
+
});
|
|
33
|
+
for (const stmt of sourceFile.getVariableStatements()) {
|
|
34
|
+
const name = stmt.getDeclarationList().getDeclarations()[0]?.getName?.();
|
|
35
|
+
if (typeof name === "string" && name.length > 0 && name[0] === name[0].toUpperCase()) candidates.push({
|
|
36
|
+
start: stmt.getStart(),
|
|
37
|
+
type: "variable",
|
|
38
|
+
node: stmt
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
candidates.sort((a, b) => a.start - b.start);
|
|
42
|
+
const first = candidates[0];
|
|
43
|
+
if (!first) return code;
|
|
44
|
+
if (first.type === "function") {
|
|
45
|
+
if (!first.node.isExported()) first.node.setIsExported(true);
|
|
46
|
+
} else if (!first.node.hasExportKeyword()) first.node.toggleModifier("export", true);
|
|
47
|
+
return sourceFile.getFullText();
|
|
48
|
+
} catch {
|
|
49
|
+
return code;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
async function findUiDirectory() {
|
|
53
|
+
const cwd = process.cwd();
|
|
54
|
+
const uiDir = path.join(cwd, UI_DIR_RELATIVE);
|
|
55
|
+
if (await fs.pathExists(uiDir)) return uiDir;
|
|
56
|
+
const found = await findUp(UI_DIR_RELATIVE, { type: "directory" });
|
|
57
|
+
if (found) return found;
|
|
58
|
+
const agentsUi = await findUp("apps/agents-ui", { type: "directory" });
|
|
59
|
+
if (agentsUi) return path.join(agentsUi, "src", "ui");
|
|
60
|
+
return path.join(cwd, UI_DIR_RELATIVE);
|
|
61
|
+
}
|
|
62
|
+
async function fetchAllComponentsWithRender(client) {
|
|
63
|
+
const [dataComponents, artifactComponents] = await Promise.all([client.listDataComponents(), client.listArtifactComponents()]);
|
|
64
|
+
return {
|
|
65
|
+
data: dataComponents,
|
|
66
|
+
artifact: artifactComponents
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
function formatComponentList(data, artifact) {
|
|
70
|
+
const withRender = (c) => c.render?.component?.trim();
|
|
71
|
+
const lines = [];
|
|
72
|
+
for (const c of data.filter(withRender)) lines.push(` ${chalk.cyan(c.id)} ${chalk.gray("(data)")} ${c.name}`);
|
|
73
|
+
for (const c of artifact.filter(withRender)) lines.push(` ${chalk.cyan(c.id)} ${chalk.gray("(artifact)")} ${c.name}`);
|
|
74
|
+
return lines.length ? lines.join("\n") : " (none with render code)";
|
|
75
|
+
}
|
|
76
|
+
async function addUiCommand(options) {
|
|
77
|
+
const componentId = typeof options.ui === "string" ? options.ui : void 0;
|
|
78
|
+
const configPath = options.config ? path.resolve(process.cwd(), options.config) : findConfigFile(process.cwd());
|
|
79
|
+
if (!configPath) {
|
|
80
|
+
console.error(chalk.red("No Inkeep config found. Run from a project directory with inkeep.config.ts or pass --config <path>."));
|
|
81
|
+
process.exit(1);
|
|
82
|
+
}
|
|
83
|
+
const { config, isCI } = await initializeCommand({
|
|
84
|
+
configPath,
|
|
85
|
+
profileName: options.profile,
|
|
86
|
+
showSpinner: true,
|
|
87
|
+
spinnerText: "Loading configuration...",
|
|
88
|
+
logConfig: !options.quiet,
|
|
89
|
+
quiet: options.quiet
|
|
90
|
+
});
|
|
91
|
+
const projectId = (await findProjectConfig(path.dirname(configPath)))?.projectId ?? null;
|
|
92
|
+
if (!projectId) {
|
|
93
|
+
console.error(chalk.red("Project ID not found in config. Set projectId in your inkeep.config.ts."));
|
|
94
|
+
process.exit(1);
|
|
95
|
+
}
|
|
96
|
+
if (!config.agentsApiKey) {
|
|
97
|
+
console.error(chalk.red("Not authenticated. Run \"inkeep login\" or set agentsApi.apiKey in your config."));
|
|
98
|
+
process.exit(1);
|
|
99
|
+
}
|
|
100
|
+
let client;
|
|
101
|
+
try {
|
|
102
|
+
client = await ManagementApiClient.create(config.agentsApiUrl, configPath, config.tenantId, projectId, isCI ?? false, config.agentsApiKey);
|
|
103
|
+
} catch (err) {
|
|
104
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
105
|
+
console.error(chalk.red(`Failed to create API client: ${message}`));
|
|
106
|
+
process.exit(1);
|
|
107
|
+
}
|
|
108
|
+
const toWrite = [];
|
|
109
|
+
const s = p.spinner();
|
|
110
|
+
if (options.list) {
|
|
111
|
+
s.start("Fetching components...");
|
|
112
|
+
const { data: dataComponents, artifact: artifactComponents } = await fetchAllComponentsWithRender(client);
|
|
113
|
+
s.stop();
|
|
114
|
+
console.log(chalk.cyan("\nAvailable UI components (use id with inkeep add --ui <id>):\n"));
|
|
115
|
+
console.log(formatComponentList(dataComponents, artifactComponents));
|
|
116
|
+
console.log("");
|
|
117
|
+
process.exit(0);
|
|
118
|
+
}
|
|
119
|
+
s.start("Resolving UI directory...");
|
|
120
|
+
const uiDir = await findUiDirectory();
|
|
121
|
+
await fs.ensureDir(uiDir);
|
|
122
|
+
s.stop();
|
|
123
|
+
if (componentId) {
|
|
124
|
+
let comp = await client.getDataComponent(componentId);
|
|
125
|
+
let kind = "data";
|
|
126
|
+
if (!comp) {
|
|
127
|
+
comp = await client.getArtifactComponent(componentId);
|
|
128
|
+
kind = "artifact";
|
|
129
|
+
}
|
|
130
|
+
if (!comp) {
|
|
131
|
+
s.start("Fetching available components...");
|
|
132
|
+
const { data: dataComponents, artifact: artifactComponents } = await fetchAllComponentsWithRender(client);
|
|
133
|
+
s.stop();
|
|
134
|
+
console.error(chalk.red(`Component "${componentId}" not found (tried data and artifact components).`));
|
|
135
|
+
console.log(chalk.cyan("\nAvailable UI components (use id with inkeep add --ui <id>):\n"));
|
|
136
|
+
console.log(formatComponentList(dataComponents, artifactComponents));
|
|
137
|
+
console.log("");
|
|
138
|
+
process.exit(1);
|
|
139
|
+
}
|
|
140
|
+
if (!comp.render?.component?.trim()) {
|
|
141
|
+
console.error(chalk.red(`Component "${comp.name}" (${kind}) has no render code. Generate a render in the dashboard first.`));
|
|
142
|
+
process.exit(1);
|
|
143
|
+
}
|
|
144
|
+
const pascalName = toPascalCase(comp.name);
|
|
145
|
+
toWrite.push({
|
|
146
|
+
pascalName,
|
|
147
|
+
code: ensureExported(comp.render.component)
|
|
148
|
+
});
|
|
149
|
+
} else {
|
|
150
|
+
s.start("Fetching data and artifact components...");
|
|
151
|
+
const [dataComponents, artifactComponents] = await Promise.all([client.listDataComponents(), client.listArtifactComponents()]);
|
|
152
|
+
s.stop();
|
|
153
|
+
const withRender = (c) => c.render?.component?.trim() ? {
|
|
154
|
+
pascalName: toPascalCase(c.name),
|
|
155
|
+
code: ensureExported(c.render.component)
|
|
156
|
+
} : null;
|
|
157
|
+
for (const c of dataComponents) {
|
|
158
|
+
const item = withRender(c);
|
|
159
|
+
if (item) toWrite.push(item);
|
|
160
|
+
}
|
|
161
|
+
for (const c of artifactComponents) {
|
|
162
|
+
const item = withRender(c);
|
|
163
|
+
if (item) toWrite.push(item);
|
|
164
|
+
}
|
|
165
|
+
if (toWrite.length === 0) {
|
|
166
|
+
console.log(chalk.yellow("No components with render code found. Generate renders in the dashboard first."));
|
|
167
|
+
process.exit(0);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
s.start(`Writing ${toWrite.length} component(s) to ${uiDir}...`);
|
|
171
|
+
for (const { pascalName, code } of toWrite) {
|
|
172
|
+
const filePath = path.join(uiDir, `${pascalName}.tsx`);
|
|
173
|
+
await fs.writeFile(filePath, code, "utf-8");
|
|
174
|
+
}
|
|
175
|
+
s.stop(chalk.green(`Added ${toWrite.length} component(s) to ${path.relative(process.cwd(), uiDir)}. Import with: import { <Name> } from './ui/<Name>';`));
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
//#endregion
|
|
179
|
+
export { addUiCommand, ensureExported };
|
package/dist/commands/add.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { cloneTemplate, cloneTemplateLocal, getAvailableTemplates } from "../utils/templates.js";
|
|
2
|
+
import { addUiCommand } from "./add-ui.js";
|
|
2
3
|
import { ANTHROPIC_MODELS, GOOGLE_MODELS, OPENAI_MODELS } from "@inkeep/agents-core";
|
|
3
4
|
import path from "node:path";
|
|
4
5
|
import * as p from "@clack/prompts";
|
|
@@ -23,6 +24,16 @@ const defaultAnthropicModelConfigurations = {
|
|
|
23
24
|
summarizer: { model: ANTHROPIC_MODELS.CLAUDE_SONNET_4_5 }
|
|
24
25
|
};
|
|
25
26
|
async function addCommand(options) {
|
|
27
|
+
if (options.ui !== void 0) {
|
|
28
|
+
await addUiCommand({
|
|
29
|
+
ui: options.ui,
|
|
30
|
+
list: options.list,
|
|
31
|
+
config: options.config,
|
|
32
|
+
profile: options.profile,
|
|
33
|
+
quiet: options.quiet
|
|
34
|
+
});
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
26
37
|
const projectTemplates = await getAvailableTemplates("template-projects", options.localPrefix);
|
|
27
38
|
const mcpTemplates = await getAvailableTemplates("template-mcps", options.localPrefix);
|
|
28
39
|
if (!options.project && !options.mcp) {
|
package/dist/index.js
CHANGED
|
@@ -25,7 +25,7 @@ const packageJsonPath = join(dirname(fileURLToPath(import.meta.url)), "..", "pac
|
|
|
25
25
|
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
|
|
26
26
|
const program = new Command();
|
|
27
27
|
program.name("inkeep").description("CLI tool for Inkeep Agent Framework").version(packageJson.version);
|
|
28
|
-
program.command("add [template]").description("Add a new template to the project").option("--project <template>", "Project template to add").option("--mcp <template>", "MCP template to add").option("--target-path <path>", "Target path to add the template to").option("--local-prefix <path_prefix>", "Use local templates from the given path prefix").option("--config <path>", "Path to configuration file").action(async (template, options) => {
|
|
28
|
+
program.command("add [template]").description("Add a new template to the project").option("--project <template>", "Project template to add").option("--mcp <template>", "MCP template to add").option("--ui [component-id]", "Add UI component(s) to apps/agents-ui/src/ui (omit id to add all)").option("--list", "List available UI components (use with --ui)").option("--target-path <path>", "Target path to add the template to").option("--local-prefix <path_prefix>", "Use local templates from the given path prefix").option("--config <path>", "Path to configuration file").option("--profile <name>", "Profile to use for authentication").option("--quiet", "Suppress profile/config logging").action(async (template, options) => {
|
|
29
29
|
await addCommand({
|
|
30
30
|
template,
|
|
31
31
|
...options
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { getCredentialExpiryInfo, loadCredentials } from "./credentials.js";
|
|
2
|
-
import { ProfileManager } from "./profiles/profile-manager.js";
|
|
3
|
-
import "./profiles/index.js";
|
|
4
2
|
import { detectCIEnvironment, loadCIEnvironmentConfig, logCIConfig } from "./ci-environment.js";
|
|
5
3
|
import { validateConfiguration } from "./config.js";
|
|
4
|
+
import { ProfileManager } from "./profiles/profile-manager.js";
|
|
5
|
+
import "./profiles/index.js";
|
|
6
6
|
import * as p from "@clack/prompts";
|
|
7
7
|
import chalk from "chalk";
|
|
8
8
|
|
package/dist/utils/config.js
CHANGED
|
@@ -23,19 +23,28 @@ function isNestedConfig(config) {
|
|
|
23
23
|
return config && config.agentsApi !== void 0;
|
|
24
24
|
}
|
|
25
25
|
/**
|
|
26
|
+
* Ensure URL has a scheme so fetch() works. Bare host:port gets http://.
|
|
27
|
+
*/
|
|
28
|
+
function ensureUrlScheme(url) {
|
|
29
|
+
if (!url?.trim()) return url;
|
|
30
|
+
const u = url.trim();
|
|
31
|
+
if (/^https?:\/\//i.test(u)) return u;
|
|
32
|
+
return `http://${u}`;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
26
35
|
* Normalize config from either flat or nested format to internal format
|
|
27
36
|
*/
|
|
28
37
|
function normalizeConfig(config) {
|
|
29
38
|
if (isNestedConfig(config)) return {
|
|
30
39
|
tenantId: config.tenantId,
|
|
31
|
-
agentsApiUrl: config.agentsApi?.url,
|
|
40
|
+
agentsApiUrl: ensureUrlScheme(config.agentsApi?.url),
|
|
32
41
|
agentsApiKey: config.agentsApi?.apiKey,
|
|
33
42
|
manageUiUrl: config.manageUiUrl,
|
|
34
43
|
outputDirectory: config.outputDirectory
|
|
35
44
|
};
|
|
36
45
|
return {
|
|
37
46
|
tenantId: config.tenantId,
|
|
38
|
-
agentsApiUrl: config.agentsApiUrl,
|
|
47
|
+
agentsApiUrl: ensureUrlScheme(config.agentsApiUrl),
|
|
39
48
|
manageUiUrl: config.manageUiUrl,
|
|
40
49
|
outputDirectory: config.outputDirectory
|
|
41
50
|
};
|
|
@@ -254,6 +263,14 @@ async function validateConfiguration(configPath, tag) {
|
|
|
254
263
|
config.agentsApiKey = cliCredentials.accessToken;
|
|
255
264
|
logger.info({}, "Using CLI session token as API key");
|
|
256
265
|
}
|
|
266
|
+
if (!config.agentsApiKey && !cliCredentials) {
|
|
267
|
+
const cloudCreds = await loadCredentials("inkeep-cloud");
|
|
268
|
+
if (cloudCreds?.accessToken) {
|
|
269
|
+
config.agentsApiKey = cloudCreds.accessToken;
|
|
270
|
+
if (!config.tenantId) config.tenantId = cloudCreds.organizationId;
|
|
271
|
+
logger.info({}, "Using CLI login credentials (inkeep-cloud)");
|
|
272
|
+
}
|
|
273
|
+
}
|
|
257
274
|
if (!config.tenantId && cliCredentials) {
|
|
258
275
|
config.tenantId = cliCredentials.organizationId;
|
|
259
276
|
logger.info({}, "Using CLI organization ID as tenant ID");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inkeep/agents-cli",
|
|
3
|
-
"version": "0.0.0-dev-
|
|
3
|
+
"version": "0.0.0-dev-20260212003026",
|
|
4
4
|
"description": "Inkeep CLI tool",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -40,8 +40,8 @@
|
|
|
40
40
|
"tsx": "^4.20.5",
|
|
41
41
|
"yaml": "^2.7.0",
|
|
42
42
|
"zod": "^4.3.6",
|
|
43
|
-
"@inkeep/agents-core": "^0.0.0-dev-
|
|
44
|
-
"@inkeep/agents-sdk": "^0.0.0-dev-
|
|
43
|
+
"@inkeep/agents-core": "^0.0.0-dev-20260212003026",
|
|
44
|
+
"@inkeep/agents-sdk": "^0.0.0-dev-20260212003026"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@types/degit": "^2.8.6",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"vitest": "^3.2.4"
|
|
53
53
|
},
|
|
54
54
|
"peerDependencies": {
|
|
55
|
-
"@inkeep/agents-manage-ui": "0.0.0-dev-
|
|
55
|
+
"@inkeep/agents-manage-ui": "0.0.0-dev-20260212003026"
|
|
56
56
|
},
|
|
57
57
|
"publishConfig": {
|
|
58
58
|
"access": "public",
|