@inkeep/agents-cli 0.47.5 → 0.48.1

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/README.md CHANGED
@@ -1,624 +1,49 @@
1
- # Inkeep CLI
1
+ # @inkeep/agents-cli
2
2
 
3
- A command-line interface for managing and interacting with Inkeep Agent Frameworks.
3
+ CLI for working with the Inkeep Agent Framework.
4
4
 
5
- ## Installation & Setup
6
-
7
- ### Prerequisites
8
-
9
- - Node.js >= 20.x
10
- - pnpm package manager
11
- - Inkeep Agent Framework backend running (default: http://localhost:3002)
12
- - `@inkeep/agents-manage-ui` package installed (for visual agents orchestration)
13
-
14
- ### Quick Start
15
-
16
- > **šŸ“– For detailed setup instructions, see [SETUP.md](./SETUP.md)**
17
-
18
- 1. **Install and build**
19
-
20
- ```bash
21
- # Navigate to the CLI directory
22
- cd /path/to/agent-framework/agents-cli
23
-
24
- # Install dependencies
25
- pnpm install
26
-
27
- # Build the CLI
28
- pnpm build
29
- ```
30
-
31
- 2. **Install globally** (recommended)
32
-
33
- **Option A: Using npm link (for development)**
34
-
35
- ```bash
36
- # Create global symlink from the agents-cli directory
37
- npm link
38
-
39
- # Verify installation
40
- which inkeep # Should show path to inkeep command
41
- ```
42
-
43
- **Option B: Using pnpm/npm global install (after publishing)**
44
-
45
- ```bash
46
- # Install the scoped package globally
47
- pnpm add -g @inkeep/agents-cli
48
- # or
49
- npm install -g @inkeep/agents-cli
50
-
51
- # Verify installation
52
- inkeep --version
53
- ```
54
-
55
- **Note:**
56
-
57
- - For local development, use `npm link` (more reliable than `pnpm link --global`)
58
- - The command is still `inkeep` even though the package name is `@inkeep/agents-cli`
59
- - If linking fails, try unlinking first: `npm unlink -g @inkeep/agents-cli`
60
-
61
- 3. **Install the dashboard package (for visual agents orchestration)**
5
+ ## Install
62
6
 
63
7
  ```bash
64
- # Install the dashboard UI package for visual agents orchestration
65
- npm install @inkeep/agents-manage-ui
8
+ npm install -g @inkeep/agents-cli
66
9
  # or
67
- pnpm add @inkeep/agents-manage-ui
68
- ```
69
-
70
- 4. **Configure your project**
71
-
72
- ```bash
73
- # Create an inkeep.config.ts file with your tenant ID
74
- inkeep init
75
-
76
- # Or manually create inkeep.config.ts:
77
- # export default defineConfig({
78
- # tenantId: "your-tenant-id",
79
- # projectId: "your-project-id",
80
- # agentsApiUrl: "http://localhost:3002",
81
- # });
82
- ```
83
-
84
- ## Configuration
85
-
86
- ### Configuration Sources (priority order)
87
-
88
- 1. **Command-line flags** - Highest priority (e.g., `--tenant-id`, `--agents-api-url`, `--config`)
89
- 2. **Config file** - `inkeep.config.ts` (or file specified with `--config`)
90
- 3. **Environment variables** - `INKEEP_AGENTS_API_URL`
91
- 4. **Defaults** - Lowest priority (defaults to `http://localhost:3002`)
92
-
93
- ### Config File Options
94
-
95
- Most commands support the `--config` option to specify a custom configuration file:
96
-
97
- ```bash
98
- # Use custom config file
99
- inkeep list-graphs --project my-project --config ./staging-config.ts
100
-
101
- # Backward compatibility (deprecated)
102
- inkeep list-graphs --project my-project --config-file-path ./staging-config.ts
103
- ```
104
-
105
- ### Environment Variables
106
-
107
- Create a `.env` file in your project directory:
108
-
109
- ```bash
110
- INKEEP_AGENTS_API_URL=http://localhost:3002
10
+ pnpm add -g @inkeep/agents-cli
111
11
  ```
112
12
 
113
- Or export them in your shell:
13
+ The executable command is `inkeep`.
114
14
 
115
- ```bash
116
- export INKEEP_AGENTS_API_URL=http://localhost:3002
117
- ```
118
-
119
- ## Commands
15
+ ## Docs
120
16
 
121
- ### `inkeep add [template]`
17
+ - CLI overview: <https://docs.inkeep.com/guides/cli/overview>
18
+ - CLI reference: <https://docs.inkeep.com/typescript-sdk/cli-reference>
19
+ - Push guide: <https://docs.inkeep.com/guides/cli/push-to-cloud>
20
+ - Pull guide: <https://docs.inkeep.com/guides/cli/pull-from-cloud>
21
+ - Profile setup: <https://docs.inkeep.com/guides/cli/setup-profile>
122
22
 
123
- Pull a template project from the [Inkeep Agents Cookbook](https://github.com/inkeep/agents/tree/main/agents-cookbook/template-projects).
23
+ ## Quick usage
124
24
 
125
25
  ```bash
126
- # Add a template
127
- inkeep add my-template
128
-
129
- # Add template to specific path
130
- inkeep add my-template --target-path ./src/templates
131
-
132
- # Using config file
133
- inkeep add my-template --config ./my-config.ts
134
- ```
135
-
136
- ### `inkeep init [path]`
137
-
138
- Initialize a new Inkeep configuration file.
139
-
140
- ```bash
141
- # Interactive initialization
142
26
  inkeep init
143
-
144
- # Initialize in specific directory
145
- inkeep init ./my-project
146
-
147
- # Skip interactive prompts
148
- inkeep init --no-interactive
149
-
150
- # Use existing config as template
151
- inkeep init --config ./template-config.ts
152
- ```
153
-
154
- ### `inkeep config`
155
-
156
- Manage Inkeep configuration values.
157
-
158
- ```bash
159
- # Get configuration value
160
- inkeep config get tenantId
161
-
162
- # Set configuration value
163
- inkeep config set tenantId my-tenant-id
164
-
165
- # List all configuration values
166
- inkeep config list
167
-
168
- # Using specific config file
169
- inkeep config get tenantId --config ./my-config.ts
170
- ```
171
-
172
- ### `inkeep pull`
173
-
174
- Pull entire project configuration from backend and update local files.
175
-
176
- ```bash
177
- # Pull current project
178
- inkeep pull
179
-
180
- # Pull specific project
181
- inkeep pull --project my-project-id
182
-
183
- # Generate environment file
184
- inkeep pull --env production
185
-
186
- # Generate JSON file instead of updating files
187
- inkeep pull --json
188
-
189
- # Enable debug logging
190
- inkeep pull --debug
191
-
192
- # Using config file
193
- inkeep pull --project my-project-id --config ./my-config.ts
194
- ```
195
-
196
- ### `inkeep dev`
197
-
198
- Start the Inkeep dashboard server, build for production, or export the Next.js project.
199
-
200
- ```bash
201
- # Start development server
202
- inkeep dev
203
-
204
- # Start on custom port and host
205
- inkeep dev --port 3001 --host 0.0.0.0
206
-
207
- # Build for production (packages standalone build)
208
- inkeep dev --build --output-dir ./build
209
-
210
- # Export Next.js project source files
211
- inkeep dev --export --output-dir ./my-dashboard
212
-
213
- # Get dashboard path for deployment
214
- DASHBOARD_PATH=$(inkeep dev --path)
215
- echo "Dashboard built at: $DASHBOARD_PATH"
216
-
217
- # Use with Vercel
218
- vercel --cwd $(inkeep dev --path) -Q .vercel build
219
-
220
- # Use with Docker
221
- docker build -t inkeep-dashboard $(inkeep dev --path)
222
-
223
- # Use with other deployment tools
224
- rsync -av $(inkeep dev --path)/ user@server:/var/www/dashboard/
225
- ```
226
-
227
- ### `inkeep tenant [tenant-id]` āš ļø NOT IMPLEMENTED
228
-
229
- > **āš ļø WARNING: This command is not yet implemented in the current CLI.**
230
- > Use `inkeep.config.ts` to set your tenant ID instead.
231
-
232
- Manage tenant configuration.
233
-
234
- ```bash
235
- # Set tenant ID
236
- inkeep tenant my-tenant
237
-
238
- # View current tenant ID
239
- inkeep tenant
240
- ```
241
-
242
- ### `inkeep list-graphs`
243
-
244
- List all available graphs for a specific project.
245
-
246
- ```bash
247
- # List graphs for a project (required)
248
- inkeep list-graphs --project my-project-id
249
-
250
- # With custom API URL
251
- inkeep list-graphs --project my-project-id --agent-api-url http://api.example.com:3002
252
-
253
- # With custom tenant ID
254
- inkeep list-graphs --project my-project-id --tenant-id my-tenant-id
255
-
256
- # Using config file
257
- inkeep list-agents --project my-project-id --config ./my-config.ts
258
- ```
259
-
260
- Output:
261
-
262
- ```
263
- ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
264
- │ Agent ID │ Name │ Default Agent │ Created │
265
- ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¤
266
- │ customer-support-graph │ Customer Support │ router │ 1/15/2025 │
267
- │ qa-assistant │ QA Assistant │ qa-agent │ 1/14/2025 │
268
- ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜
269
- ```
270
-
271
- ### `inkeep push`
272
-
273
- Push your project configuration to the backend.
274
-
275
- ```bash
276
- # Push the current project (from the directory with inkeep.config.ts)
277
27
  inkeep push
278
-
279
- # Push specific project
280
- inkeep push --project my-project-id
281
-
282
- # With custom configuration
283
- inkeep push --project my-project-id --config ./my-config.ts
284
-
285
- # With custom API URLs
286
- inkeep push --project my-project-id --agents-api-url http://api.example.com
287
-
288
- # With custom tenant ID
289
- inkeep push --project my-project-id --tenant-id my-tenant-id
290
- ```
291
-
292
- **Features:**
293
-
294
- - Automatically injects tenant ID and API URL from `inkeep.config.ts`
295
- - Validates exactly one Agent is exported
296
- - Warns about dangling resources (unreferenced agents/tools)
297
- - Shows graph summary after successful push
298
- - Handles graph initialization automatically
299
-
300
- **Agent files:** Define your agents in your project (e.g., `agents/*.ts`). The CLI pushes the project containing those agents.
301
-
302
- **Example graph configuration:**
303
-
304
- ```javascript
305
- // customer-support.agent.ts
306
- import { agent, subAgent, tool } from "@inkeep/agents-sdk";
307
-
308
- const assistantSubAgent = subAgent({
309
- id: "assistant",
310
- name: "Assistant",
311
- prompt: "Help users with their questions",
312
- canUse: () => [searchTool],
313
- // No tenantId needed - injected by CLI
314
- });
315
-
316
- // Must export exactly one agent
317
- export const myAgent = agent({
318
- id: "my-assistant",
319
- name: "My Assistant",
320
- defaultSubAgent: assistantSubAgent,
321
- subAgents: () => [assistantSubAgent],
322
- // No tenantId or apiUrl needed - CLI injects from config
323
- });
324
- // No agent.init() call - CLI handles initialization
325
- ```
326
-
327
- ### `inkeep mcp start <graph-file>` āš ļø NOT IMPLEMENTED
328
-
329
- > **āš ļø WARNING: This command is not yet implemented in the current CLI.**
330
- > MCP functionality is planned but not available in the current version.
331
-
332
- Start MCP (Model Context Protocol) servers defined in a graph file.
333
-
334
- ```bash
335
- # Start MCP servers from a TypeScript agent file
336
- inkeep mcp start examples/agent-configurations/weather-agent.ts
337
-
338
- # Start from compiled JavaScript
339
- inkeep mcp start dist/examples/agent-configurations/weather-agent.js
340
-
341
- # Run in detached mode
342
- inkeep mcp start my-agent.ts --detached
343
-
344
- # Show verbose output
345
- inkeep mcp start my-agent.ts --verbose
346
- ```
347
-
348
- **Features:**
349
-
350
- - Supports both TypeScript (`.ts`) and JavaScript (`.js`) files
351
- - Automatically allocates ports for local servers (3100-3200)
352
- - Shows server names, ports, and URLs
353
- - Distinguishes between local (šŸ ) and remote (ā˜ļø) servers
354
-
355
- ### `inkeep mcp stop` āš ļø NOT IMPLEMENTED
356
-
357
- > **āš ļø WARNING: This command is not yet implemented in the current CLI.**
358
-
359
- Stop running MCP servers.
360
-
361
- ```bash
362
- # Stop all servers
363
- inkeep mcp stop --all
364
-
365
- # Stop servers for a specific graph
366
- inkeep mcp stop --graph customer-support-graph
367
- ```
368
-
369
- ### `inkeep mcp status` āš ļø NOT IMPLEMENTED
370
-
371
- > **āš ļø WARNING: This command is not yet implemented in the current CLI.**
372
-
373
- Show status of all MCP servers.
374
-
375
- ```bash
376
- inkeep mcp status
377
- ```
378
-
379
- Output shows:
380
-
381
- - Process ID
382
- - Graph ID
383
- - Tool name
384
- - Port/URL
385
- - Running status
386
- - Uptime
387
-
388
- ### `inkeep mcp list` āš ļø NOT IMPLEMENTED
389
-
390
- > **āš ļø WARNING: This command is not yet implemented in the current CLI.**
391
-
392
- List all MCP servers with detailed information.
393
-
394
- ```bash
395
- # Default tree view
396
- inkeep mcp list
397
-
398
- # Table format
399
- inkeep mcp list --format table
400
-
401
- # Verbose output (includes descriptions)
402
- inkeep mcp list --verbose
28
+ inkeep pull
29
+ inkeep list-agent --project <project-id>
403
30
  ```
404
31
 
405
- ## Complete Workflow Example
406
-
407
- ### Basic Setup
32
+ ## Local development
408
33
 
409
34
  ```bash
410
- # Install and link CLI
411
- cd agents-cli
412
35
  pnpm install
413
36
  pnpm build
414
37
  npm link
415
-
416
- # Initialize configuration
417
- inkeep init
418
- # Edit inkeep.config.ts to set your tenantId and projectId
419
- ```
420
-
421
- ### Working with Graphs and MCP Servers āš ļø NOT AVAILABLE
422
-
423
- > **āš ļø WARNING: MCP commands shown below are not yet implemented.**
424
- > This section shows planned functionality that is not available in the current version.
425
-
426
- 1. **Create an agent with MCP tools** (`my-agent.ts`)
427
-
428
- ```typescript
429
- import {
430
- agent,
431
- subAgent,
432
- mcpServer,
433
- } from "@inkeep/agents-sdk";
434
-
435
- // Define MCP servers (tools)
436
- const randomNumberServer = mcpServer({
437
- name: "random_number",
438
- description: "Generates a random number",
439
- execute: async () => Math.random(),
440
- });
441
-
442
- const weatherServer = mcpServer({
443
- name: "weather_api",
444
- description: "Get weather information",
445
- serverUrl: "https://api.weather.example.com/mcp",
446
- });
447
-
448
- // Define sub-agents
449
- const assistantSubAgent = subAgent({
450
- id: "assistant",
451
- name: "Assistant",
452
- prompt: "Help users with various tasks",
453
- canUse: () => [randomNumberServer, weatherServer],
454
- });
455
-
456
- // Export the agent
457
- export const myAgent = agent({
458
- id: "my-assistant",
459
- name: "My Assistant",
460
- defaultSubAgent: assistantSubAgent,
461
- subAgents: () => [assistantSubAgent],
462
- });
463
-
464
- // Export servers for MCP management
465
- export const servers = [randomNumberServer, weatherServer];
466
- ```
467
-
468
- 2. **Monitor and manage servers**
469
-
470
- ```bash
471
- # Check server status
472
- inkeep mcp status
473
-
474
- # List all servers with details
475
- inkeep mcp list
476
-
477
- # Stop servers when done
478
- inkeep mcp stop --all
38
+ inkeep --version
479
39
  ```
480
40
 
481
- ## Working with Different Environments
41
+ ## Contributing
482
42
 
483
- ### Development
484
-
485
- ```bash
486
- # Using environment variables
487
- INKEEP_AGENTS_MANAGE_API_URL=http://localhost:3002 inkeep list-graphs
488
-
489
- # Using .env file
490
- echo "INKEEP_AGENTS_API_URL=http://localhost:3002" > .env
491
- ```
492
-
493
- ### Staging
494
-
495
- ```bash
496
- # Set in config file
497
- # Edit your inkeep.config.ts:
498
- # agentsApiUrl: 'https://staging-api.example.com'
499
- ```
500
-
501
- ### Production
502
-
503
- ```bash
504
- # Using environment variables
505
- export INKEEP_AGENTS_API_URL=https://inkeep-api.example.com
506
- inkeep list-graphs
507
- ```
508
-
509
- ## Development
510
-
511
- ### Running from Source
512
-
513
- ```bash
514
- # Without building (using tsx)
515
- pnpm tsx src/index.ts <command>
516
-
517
- # After building
518
- node dist/index.js <command>
519
-
520
- # Watch mode (auto-rebuild on changes)
521
- pnpm dev
522
- ```
523
-
524
- ### Testing
525
-
526
- ```bash
527
- # Run tests
528
- pnpm test
529
-
530
- # Watch mode
531
- pnpm test:watch
532
-
533
- # Coverage report
534
- pnpm test:coverage
535
- ```
536
-
537
- ### Type Checking
43
+ Run from `agents-cli/`:
538
44
 
539
45
  ```bash
46
+ pnpm lint
540
47
  pnpm typecheck
48
+ pnpm test --run
541
49
  ```
542
-
543
- ### Project Structure
544
-
545
- ```
546
- agents-cli/
547
- ā”œā”€ā”€ src/
548
- │ ā”œā”€ā”€ index.ts # Main CLI entry point
549
- │ ā”œā”€ā”€ config.ts # Configuration management
550
- │ ā”œā”€ā”€ api.ts # API client for backend
551
- │ ā”œā”€ā”€ commands/ # Command implementations
552
- │ │ ā”œā”€ā”€ push.ts # Push graph configurations
553
- │ │ ā”œā”€ā”€ tenant.ts # Tenant management
554
- │ │ └── list-graphs.ts # List graphs
555
- │ ā”œā”€ā”€ types/ # TypeScript declarations
556
- │ └── __tests__/ # Test files
557
- ā”œā”€ā”€ dist/ # Compiled JavaScript
558
- ā”œā”€ā”€ package.json
559
- ā”œā”€ā”€ tsconfig.json
560
- └── README.md
561
- ```
562
-
563
- ## Troubleshooting
564
-
565
- ### Common Issues
566
-
567
- **"Failed to fetch graphs" or connection errors**
568
-
569
- ```bash
570
- # Check if backend is running
571
- curl http://localhost:3002/health
572
-
573
- # Verify API URLs
574
- echo $INKEEP_AGENTS_API_URL
575
-
576
- # Try with explicit URL and project
577
- inkeep list-graphs --project my-project-id --agents-api-url http://localhost:3002
578
- ```
579
-
580
- **Command not found: inkeep**
581
-
582
- ```bash
583
- # Ensure CLI is linked globally
584
- cd agents-cli
585
- npm link
586
-
587
- # Or if published, install globally
588
- pnpm add -g @inkeep/agents-cli
589
- # or
590
- npm install -g @inkeep/agents-cli
591
-
592
- # Or add to PATH manually (for development)
593
- export PATH="$PATH:/path/to/agents-cli/dist"
594
- ```
595
-
596
- ## Dependencies
597
-
598
- ### Runtime Dependencies
599
-
600
- - **commander**: Command-line framework
601
- - **chalk**: Terminal styling
602
- - **dotenv**: Environment variable loading
603
- - **ora**: Loading spinners
604
- - **cli-table3**: Table formatting
605
- - **inquirer**: Interactive prompts
606
- - **inquirer-autocomplete-prompt**: Searchable selections
607
-
608
- ### Development Dependencies
609
-
610
- - **typescript**: TypeScript compiler
611
- - **@types/node**: Node.js types
612
- - **vitest**: Testing framework
613
- - **@vitest/coverage-v8**: Coverage reporting
614
-
615
- ## Requirements
616
-
617
- - Node.js >= 20.x
618
- - pnpm package manager
619
- - TypeScript 5.x
620
- - Inkeep Agent Framework backend
621
-
622
- ## License
623
-
624
- MIT
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 };
@@ -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) {
@@ -20,6 +20,7 @@ function generateProjectDefinition(projectId, projectData, style = DEFAULT_STYLE
20
20
  lines.push(`${indentation}name: ${formatString(projectData.name, q)},`);
21
21
  if (shouldInclude(projectData.description)) lines.push(`${indentation}description: ${formatString(projectData.description, q, true)},`);
22
22
  if (shouldInclude(projectData.models)) lines.push(`${indentation}models: ${formatObject(projectData.models, style, 2)},`);
23
+ if (shouldInclude(projectData.skills)) lines.push(`${indentation}skills: () => loadSkills(path.join(${formatString(projectId, q)}, 'skills')),`);
23
24
  if (shouldInclude(projectData.stopWhen)) {
24
25
  lines.push(`${indentation}stopWhen: {`);
25
26
  if (projectData.stopWhen.transferCountIs !== void 0) lines.push(`${indentation}${indentation}transferCountIs: ${projectData.stopWhen.transferCountIs}, // Max transfers for agents`);
@@ -64,7 +65,14 @@ function generateProjectDefinition(projectId, projectData, style = DEFAULT_STYLE
64
65
  */
65
66
  function generateProjectImports(projectData, style = DEFAULT_STYLE, registry) {
66
67
  const imports = [];
67
- imports.push(generateImport(["project"], "@inkeep/agents-sdk", style));
68
+ const sdkImports = ["project"];
69
+ if (shouldInclude(projectData.skills)) sdkImports.push("loadSkills");
70
+ imports.push(generateImport(sdkImports, "@inkeep/agents-sdk", style));
71
+ if (shouldInclude(projectData.skills)) {
72
+ const q = style.quotes === "single" ? "'" : "\"";
73
+ const semi = style.semicolons ? ";" : "";
74
+ imports.push(`import path from ${q}node:path${q}${semi}`);
75
+ }
68
76
  if (registry) {
69
77
  const currentFilePath = "index.ts";
70
78
  const referencedComponents = [];
@@ -83,8 +91,8 @@ function generateProjectImports(projectData, style = DEFAULT_STYLE, registry) {
83
91
  else if (typeof projectData.tools === "object") toolIds = Object.keys(projectData.tools);
84
92
  for (const toolId of toolIds) {
85
93
  let componentType = "tools";
86
- if (registry?.get(toolId, "functionTools")) componentType = "functionTools";
87
- else if (registry?.get(toolId, "tools")) componentType = "tools";
94
+ if (registry.get(toolId, "functionTools")) componentType = "functionTools";
95
+ else if (registry.get(toolId, "tools")) componentType = "tools";
88
96
  referencedComponents.push({
89
97
  id: toolId,
90
98
  type: componentType
@@ -138,7 +146,11 @@ function generateProjectImports(projectData, style = DEFAULT_STYLE, registry) {
138
146
  * Generate complete project file (imports + definition)
139
147
  */
140
148
  function generateProjectFile(projectId, projectData, style = DEFAULT_STYLE, registry) {
141
- return generateFileContent(generateProjectImports(projectData, style, registry), [generateProjectDefinition(projectId, projectData, style, registry)]);
149
+ const imports = generateProjectImports(projectData, style, registry);
150
+ const definition = generateProjectDefinition(projectId, projectData, style, registry);
151
+ const definitions = [];
152
+ definitions.push(definition);
153
+ return generateFileContent(imports, definitions);
142
154
  }
143
155
 
144
156
  //#endregion
@@ -0,0 +1,23 @@
1
+ import { join } from "node:path";
2
+ import { stringify } from "yaml";
3
+ import { mkdir, writeFile } from "node:fs/promises";
4
+
5
+ //#region src/commands/pull-v3/components/skill-generator.ts
6
+ function formatMetadata(metadata) {
7
+ return `metadata:\n${stringify(metadata).split("\n").filter((line) => line.trim() !== "").map((line) => ` ${line}`).join("\n")}`;
8
+ }
9
+ async function generateSkills(skills, skillsDir) {
10
+ await mkdir(skillsDir, { recursive: true });
11
+ for (const [skillId, skill] of Object.entries(skills)) {
12
+ const parts = ["---", `name: ${JSON.stringify(skill.name)}`];
13
+ parts.push(`description: ${JSON.stringify(skill.description ?? "")}`);
14
+ if (skill.metadata && Object.keys(skill.metadata).length > 0) parts.push(formatMetadata(skill.metadata));
15
+ parts.push("---", "", skill.content || "");
16
+ const skillDir = join(skillsDir, skillId);
17
+ await mkdir(skillDir, { recursive: true });
18
+ await writeFile(join(skillDir, "SKILL.md"), parts.join("\n"), "utf8");
19
+ }
20
+ }
21
+
22
+ //#endregion
23
+ export { generateSkills };
@@ -94,6 +94,16 @@ function generateSubAgentDefinition(agentId, agentData, style = DEFAULT_STYLE, r
94
94
  removeTrailingComma(lines);
95
95
  lines.push(`${indentation}},`);
96
96
  }
97
+ if (Array.isArray(agentData.skills) && agentData.skills.length) {
98
+ lines.push(`${indentation}skills: () => [`);
99
+ for (const skill of agentData.skills) {
100
+ const parts = [`id: ${formatString(skill.id, q)}`];
101
+ parts.push(`index: ${skill.index}`);
102
+ if (skill.alwaysLoaded) parts.push(`alwaysLoaded: ${skill.alwaysLoaded}`);
103
+ lines.push(`${indentation}${indentation}{ ${parts.join(", ")} },`);
104
+ }
105
+ lines.push(`${indentation}],`);
106
+ }
97
107
  if (agentData.canUse && Array.isArray(agentData.canUse) && agentData.canUse.length > 0) {
98
108
  const toolReferences = [];
99
109
  if (!registry) throw new Error("Registry is required for canUse generation");
@@ -48,7 +48,8 @@ function createProjectStructure(projectDir) {
48
48
  environmentsDir: join(projectRoot, "environments"),
49
49
  credentialsDir: join(projectRoot, "credentials"),
50
50
  contextConfigsDir: join(projectRoot, "context-configs"),
51
- externalAgentsDir: join(projectRoot, "external-agents")
51
+ externalAgentsDir: join(projectRoot, "external-agents"),
52
+ skillsDir: join(projectRoot, "skills")
52
53
  };
53
54
  Object.values(paths).forEach((dir) => {
54
55
  if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
@@ -229,6 +230,10 @@ async function pullV3Command(options) {
229
230
  return;
230
231
  }
231
232
  const paths = createProjectStructure(projectDir);
233
+ if (remoteProject.skills && Object.keys(remoteProject.skills).length) {
234
+ const { generateSkills } = await import("./components/skill-generator.js");
235
+ await generateSkills(remoteProject.skills, paths.skillsDir);
236
+ }
232
237
  if (options.introspect) {
233
238
  console.log(chalk.yellow("\nšŸ” Introspect mode: Regenerating all files from scratch"));
234
239
  s.start("Generating all files deterministically...");
@@ -98,7 +98,8 @@ async function createNewComponents(comparison, remoteProject, localRegistry, pat
98
98
  environmentsDir: join(paths.projectRoot, tempDirName, "environments"),
99
99
  credentialsDir: join(paths.projectRoot, tempDirName, "credentials"),
100
100
  contextConfigsDir: join(paths.projectRoot, tempDirName, "context-configs"),
101
- externalAgentsDir: join(paths.projectRoot, tempDirName, "external-agents")
101
+ externalAgentsDir: join(paths.projectRoot, tempDirName, "external-agents"),
102
+ skillsDir: join(paths.projectRoot, tempDirName, "skills")
102
103
  } : paths;
103
104
  const actionText = tempDirName ? "Creating component files in temp directory..." : "Creating new component files...";
104
105
  console.log(chalk.cyan(`\nšŸ†• ${actionText}`));
@@ -1,5 +1,5 @@
1
- import { randomBytes } from "node:crypto";
2
1
  import { Node, Project } from "ts-morph";
2
+ import { randomBytes } from "node:crypto";
3
3
 
4
4
  //#region src/commands/pull-v3/targeted-typescript-placeholders.ts
5
5
  /**
@@ -293,6 +293,7 @@ function registerAllComponents(project, registry) {
293
293
  if (project.dataComponents) for (const componentId of Object.keys(project.dataComponents)) registry.register(componentId, "dataComponents", `data-components/${componentId}.ts`);
294
294
  if (project.artifactComponents) for (const componentId of Object.keys(project.artifactComponents)) registry.register(componentId, "artifactComponents", `artifact-components/${componentId}.ts`);
295
295
  if (project.externalAgents) for (const extAgentId of Object.keys(project.externalAgents)) registry.register(extAgentId, "externalAgents", `external-agents/${extAgentId}.ts`);
296
+ if (project.skills) for (const skillId of Object.keys(project.skills)) registry.register(skillId, "skills", `skills/${skillId}.md`);
296
297
  const statusComponents = extractStatusComponents(project);
297
298
  for (const statusId of Object.keys(statusComponents)) registry.register(statusId, "statusComponents", `status-components/${statusId}.ts`);
298
299
  if (project.agents) for (const agentId of Object.keys(project.agents)) registry.register(agentId, "agents", `agents/${agentId}.ts`);
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ #!/usr/bin/env node
1
2
  import "./env.js";
2
3
  import "./instrumentation.js";
3
4
  import { addCommand } from "./commands/add.js";
@@ -25,7 +26,7 @@ const packageJsonPath = join(dirname(fileURLToPath(import.meta.url)), "..", "pac
25
26
  const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
26
27
  const program = new Command();
27
28
  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) => {
29
+ 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
30
  await addCommand({
30
31
  template,
31
32
  ...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
 
@@ -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.47.5",
3
+ "version": "0.48.1",
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.47.5",
44
- "@inkeep/agents-sdk": "^0.47.5"
43
+ "@inkeep/agents-core": "^0.48.1",
44
+ "@inkeep/agents-sdk": "^0.48.1"
45
45
  },
46
46
  "devDependencies": {
47
47
  "@types/degit": "^2.8.6",