@imbrace/cli 0.1.0 → 0.3.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 (58) hide show
  1. package/README.md +443 -0
  2. package/dist/commands/ai-agent/create.d.ts +5 -0
  3. package/dist/commands/ai-agent/create.js +11 -0
  4. package/dist/commands/ai-agent/list-files.d.ts +10 -0
  5. package/dist/commands/ai-agent/list-files.js +40 -0
  6. package/dist/commands/ai-agent/list-folders.d.ts +10 -0
  7. package/dist/commands/ai-agent/list-folders.js +39 -0
  8. package/dist/commands/ai-agent/list-providers.js +1 -1
  9. package/dist/commands/ai-agent/update.d.ts +5 -0
  10. package/dist/commands/ai-agent/update.js +16 -0
  11. package/dist/commands/docs.d.ts +10 -0
  12. package/dist/commands/docs.js +39 -0
  13. package/dist/commands/workflow/conn/create.d.ts +15 -0
  14. package/dist/commands/workflow/conn/create.js +69 -0
  15. package/dist/commands/workflow/conn/delete.d.ts +13 -0
  16. package/dist/commands/workflow/conn/delete.js +39 -0
  17. package/dist/commands/workflow/conn/get.d.ts +12 -0
  18. package/dist/commands/workflow/conn/get.js +42 -0
  19. package/dist/commands/workflow/conn/list.d.ts +9 -0
  20. package/dist/commands/workflow/conn/list.js +37 -0
  21. package/dist/commands/workflow/create.d.ts +1 -0
  22. package/dist/commands/workflow/create.js +4 -0
  23. package/dist/commands/workflow/disable.d.ts +12 -0
  24. package/dist/commands/workflow/disable.js +30 -0
  25. package/dist/commands/workflow/enable.d.ts +12 -0
  26. package/dist/commands/workflow/enable.js +34 -0
  27. package/dist/commands/workflow/folder/create.d.ts +12 -0
  28. package/dist/commands/workflow/folder/create.js +43 -0
  29. package/dist/commands/workflow/folder/delete.d.ts +13 -0
  30. package/dist/commands/workflow/folder/delete.js +39 -0
  31. package/dist/commands/workflow/folder/get.d.ts +12 -0
  32. package/dist/commands/workflow/folder/get.js +38 -0
  33. package/dist/commands/workflow/folder/list.d.ts +9 -0
  34. package/dist/commands/workflow/folder/list.js +35 -0
  35. package/dist/commands/workflow/folder/update.d.ts +13 -0
  36. package/dist/commands/workflow/folder/update.js +30 -0
  37. package/dist/commands/workflow/list.d.ts +1 -0
  38. package/dist/commands/workflow/list.js +7 -1
  39. package/dist/commands/workflow/mcp/create.d.ts +12 -0
  40. package/dist/commands/workflow/mcp/create.js +44 -0
  41. package/dist/commands/workflow/mcp/delete.d.ts +13 -0
  42. package/dist/commands/workflow/mcp/delete.js +39 -0
  43. package/dist/commands/workflow/mcp/get.d.ts +12 -0
  44. package/dist/commands/workflow/mcp/get.js +40 -0
  45. package/dist/commands/workflow/mcp/list.d.ts +9 -0
  46. package/dist/commands/workflow/mcp/list.js +36 -0
  47. package/dist/commands/workflow/mcp/rotate-token.d.ts +13 -0
  48. package/dist/commands/workflow/mcp/rotate-token.js +46 -0
  49. package/dist/commands/workflow/move.d.ts +13 -0
  50. package/dist/commands/workflow/move.js +35 -0
  51. package/dist/commands/workflow/node/add-raw.d.ts +15 -0
  52. package/dist/commands/workflow/node/add-raw.js +70 -0
  53. package/dist/commands/workflow/publish.d.ts +12 -0
  54. package/dist/commands/workflow/publish.js +30 -0
  55. package/dist/commands/workflow/run.d.ts +14 -0
  56. package/dist/commands/workflow/run.js +50 -0
  57. package/llms.txt +625 -0
  58. package/package.json +12 -2
package/README.md ADDED
@@ -0,0 +1,443 @@
1
+ # Imbrace CLI
2
+
3
+ > CLI tool for interacting with the Imbrace CRM platform from the terminal. Designed for both developers and coding agents (Claude, Cursor, Copilot, etc.).
4
+
5
+ ## Quick Install
6
+
7
+ ```bash
8
+ # 1. Start the API server (in one terminal, keep running)
9
+ cd api
10
+ bun install
11
+ bun run dev # runs on http://localhost:3456
12
+
13
+ # 2. Install the CLI (in another terminal — one-shot)
14
+ ./install.sh
15
+ ```
16
+
17
+ `install.sh` runs `npm install`, `npm run build`, `npm link`, and then symlinks `imbrace` into `/opt/homebrew/bin` (Apple Silicon) or `/usr/local/bin` so the command is available even from shells that don't load nvm — for example conda's `(base)` env.
18
+
19
+ ---
20
+
21
+ ## Authentication
22
+
23
+ ```bash
24
+ # API Key (recommended for coding agents and CI/CD)
25
+ imbrace login --api-key api_xxx...
26
+
27
+ # Email + Password
28
+ imbrace login --email user@example.com --password mypass
29
+
30
+ # Check current login
31
+ imbrace whoami --json
32
+
33
+ # Logout
34
+ imbrace logout
35
+ ```
36
+
37
+ Credentials are stored via the `conf` package — exact path depends on OS:
38
+
39
+ | OS | Path |
40
+ |---|---|
41
+ | macOS | `~/Library/Preferences/imbrace-nodejs/config.json` |
42
+ | Linux | `~/.config/imbrace-nodejs/config.json` |
43
+ | Windows | `%APPDATA%\imbrace-nodejs\Config\config.json` |
44
+
45
+ ---
46
+
47
+ ## Commands
48
+
49
+ ### Data Board
50
+
51
+ A board is a CRM pipeline — leads, deals, tasks, or any structured data.
52
+
53
+ **Step 1 — List boards** (get Board IDs)
54
+
55
+ ```bash
56
+ imbrace data-board list --json
57
+ ```
58
+
59
+ **Step 2 — Create a board**
60
+
61
+ ```bash
62
+ imbrace data-board create --name "Sales Pipeline" --json
63
+ ```
64
+
65
+ The `create` command is interactive (without `--json`) — after entering the board name you can attach freestyle key-value pairs (e.g. `description`, `email`, or any custom property). With `--json`, only `--name` is required.
66
+
67
+ **Step 3 — Add schema fields to a board**
68
+
69
+ ```bash
70
+ # Valid field types (16):
71
+ # ShortText, LongText, Number, Date, Email, Phone, Currency,
72
+ # SingleSelection, MultipleSelection, Checkbox,
73
+ # Assignee, MultipleAssignee, Link, Notes, Origin, Priority
74
+ # DO NOT use `Dropdown` — backend rejects it (use `SingleSelection` instead).
75
+
76
+ imbrace data-board create-field <boardId> --name "Company" --type ShortText --json
77
+ imbrace data-board create-field <boardId> --name "Revenue" --type Number --json
78
+ imbrace data-board create-field <boardId> --name "Status" --type SingleSelection --json
79
+ ```
80
+
81
+ **Step 4 — Create items (records)**
82
+
83
+ ```bash
84
+ imbrace data-board create-item <boardId> --fields '[
85
+ {"board_field_id": "<fieldId1>", "value": "Acme Corp"},
86
+ {"board_field_id": "<fieldId2>", "value": "50000"},
87
+ {"board_field_id": "<fieldId3>", "value": "Active"}
88
+ ]' --json
89
+ ```
90
+
91
+ **Step 5 — List / search items**
92
+
93
+ ```bash
94
+ # List all items (paginated)
95
+ imbrace data-board list-items --board-id <boardId> --limit 20 --skip 0 --json
96
+
97
+ # Full-text search
98
+ imbrace data-board list-items --board-id <boardId> --q "Acme" --json
99
+ ```
100
+
101
+ **Update an item**
102
+
103
+ ```bash
104
+ imbrace data-board update-item <boardId> <itemId> --data '[
105
+ {"key": "<fieldId>", "value": "Acme Corp — Closed Won"}
106
+ ]' --json
107
+ ```
108
+
109
+ **Delete an item**
110
+
111
+ ```bash
112
+ imbrace data-board delete-item <boardId> <itemId> --yes --json
113
+ ```
114
+
115
+ **Export to CSV**
116
+
117
+ ```bash
118
+ imbrace data-board export-csv --board-id <boardId> --out ./board.csv
119
+ ```
120
+
121
+ ---
122
+
123
+ ### AI Agent
124
+
125
+ An AI agent is a configured assistant (LLM + prompt + behavior) that appears as a card on `cloud.imbrace.co/ai-agent`. Creating one atomically provisions the assistant, a web channel for the chat widget, and the use-case template.
126
+
127
+ > **All content (name, description, instructions, behavior fields) must be in English.** The slug for `workflow_name` is derived from the name; Vietnamese diacritics get stripped and produce unreadable slugs.
128
+
129
+ **CRUD**
130
+
131
+ ```bash
132
+ imbrace ai-agent list --json
133
+ imbrace ai-agent get <agentId> --json
134
+ imbrace ai-agent create --name "Sales Bot" --json
135
+ imbrace ai-agent update <agentId> --name "New Name" --json
136
+ imbrace ai-agent delete <agentId> --yes --json
137
+ ```
138
+
139
+ **Discovery (LLM providers + Knowledge Hub)**
140
+
141
+ ```bash
142
+ # LLM providers + models
143
+ imbrace ai-agent list-providers --json # 3 providers
144
+ imbrace ai-agent list-models --provider-id system --json # models per provider
145
+
146
+ # Knowledge Hub folders + files
147
+ imbrace ai-agent list-folders [--search support] --json
148
+ imbrace ai-agent list-files --folder-id <folderId> --json
149
+ ```
150
+
151
+ **Full create — all settings populated**
152
+
153
+ ```bash
154
+ imbrace ai-agent create \
155
+ --name "Customer Support Specialist" \
156
+ --description "Senior AI customer support agent for an e-commerce company" \
157
+ --instructions "You are a senior customer support specialist..." \
158
+ --personality "Friendly and professional senior customer support agent" \
159
+ --core-task "Answer product inquiries, help track orders" \
160
+ --tone "Polite, professional, warm" \
161
+ --response-length "medium" \
162
+ --banned-words "stupid, idiot" \
163
+ --category "Support" \
164
+ --provider-id "e2629292-7e9f-4d55-ba18-6827747eab33" \
165
+ --model "gpt-4o-mini" \
166
+ --temperature 0.3 \
167
+ --folder-ids "69bb82faa2cc764639bc6bdb" \
168
+ --board-ids "brd_e5450d76-84d4-4c34-8b13-3d0f1873b53b" \
169
+ --json
170
+ ```
171
+
172
+ **Available flags** (`create` + `update` accept the same set; `update` preserves unchanged fields via PUT-merge)
173
+
174
+ | Flag | Maps to | Notes |
175
+ |---|---|---|
176
+ | **Identity** | | |
177
+ | `--name` / `-n` | `name` + `title` | Required for create |
178
+ | `--description` / `-d` | `description` + `short_description` | Shown under title in UI |
179
+ | `--instructions` / `-i` | `instructions` | System prompt |
180
+ | **Model** | | |
181
+ | `--model` | `model_id` | Default `Default` (system provider). Discover via `list-models`. |
182
+ | `--provider-id` | `provider_id` | UUID, default `system`. **Use UUID — not the MongoDB `_id`.** |
183
+ | `--mode` | `mode` | `standard` / `advanced` |
184
+ | `--temperature` | `temperature` | 0.0–2.0, default 0.1 |
185
+ | **Behavior Settings** | | |
186
+ | `--personality` | `personality_role` | |
187
+ | `--core-task` | `core_task` | |
188
+ | `--tone` | `tone_and_style` | |
189
+ | `--response-length` | `response_length` | `short` / `medium` / `long` |
190
+ | `--banned-words` | `banned_words` | Comma-separated, word-level filter on output |
191
+ | `--category` | `category` | `Support` / `Sales` / `Marketing` / `Team` / `Other` |
192
+ | `--guardrail-id` | `guardrail_id` | Attach a guardrail |
193
+ | `--preload-information` | `preload_information` | Static info auto-injected into context |
194
+ | **Knowledge Support** | | |
195
+ | `--folder-ids` | `folder_ids` | Comma-separated KH folder IDs |
196
+ | `--default-folder-id` | `default_folder_id` | |
197
+ | `--knowledge-hubs` | `knowledge_hubs` | Comma-separated KH IDs |
198
+ | `--board-ids` | `board_ids` | Comma-separated data board IDs (Document Models) |
199
+ | `--file-ids` | `file_ids` | Comma-separated file IDs |
200
+ | **Runtime toggles** (boolean, support `--no-X`) | | |
201
+ | `--show-thinking` | `show_thinking_process` | Default false |
202
+ | `--streaming` | `streaming` | Default true |
203
+ | `--use-memory` | `use_memory` | Default true |
204
+ | **Output** | | |
205
+ | `--yes` / `-y` | — | Skip confirm on delete |
206
+ | `--json` | — | Machine-readable output |
207
+ | `--id-only` | — | Print only the new agent ID (pipe-friendly) |
208
+ | `-h` / `--help` | — | Show usage on any command |
209
+
210
+ ---
211
+
212
+ ### Workflow
213
+
214
+ A workflow (Activepieces) is a chain of nodes: a trigger fires, then actions run in sequence. Use it for automation — e.g. "Slack message arrives → ask AI → reply to thread".
215
+
216
+ **Anatomy:** A workflow has 6 layers — `Flow` (container) → `Version` (snapshot) → `Nodes` (trigger + actions) → `Connections` (credentials) → `Runs` (history) → `Pieces` (catalog of 126 integrations).
217
+
218
+ **Node types:**
219
+
220
+ | Type | Role | CLI support |
221
+ |---|---|---|
222
+ | `PIECE_TRIGGER` | "When does the flow run" — Slack message, webhook, cron, ... | ✅ `node add --type trigger` |
223
+ | `PIECE` | "What runs after" — send Slack, ask AI, HTTP call, ... | ✅ `node add --type action` |
224
+ | `EMPTY` | Placeholder before trigger is set | ✅ Read-only |
225
+ | `ROUTER` | Multi-condition switch (replaces legacy BRANCH) | ✅ `node add-raw` |
226
+ | `LOOP_ON_ITEMS` | Loop over an array | ✅ `node add-raw` |
227
+ | `CODE` | Inline JavaScript | ✅ `node add-raw` |
228
+
229
+ **Flow CRUD + run history**
230
+ ```bash
231
+ imbrace workflow list [--folder-id <id|NULL>] # filter by category folder
232
+ imbrace workflow get <id>
233
+ imbrace workflow create --name "X" [--folder-id <id>]
234
+ imbrace workflow move <flowId> --folder-id <id|NULL> # NULL = unfile
235
+ imbrace workflow delete <id> --yes
236
+ imbrace workflow runs # recent runs
237
+ imbrace workflow run-detail <runId>
238
+ ```
239
+
240
+ **Build nodes**
241
+ ```bash
242
+ # Discover integrations
243
+ imbrace workflow piece list [--search slack]
244
+ imbrace workflow piece detail <pieceName> [--only actions|triggers]
245
+
246
+ # Manage nodes
247
+ imbrace workflow node list <flowId>
248
+ imbrace workflow node add <flowId> --type trigger --piece <name> --trigger-name <id> --input '{...}'
249
+ imbrace workflow node add <flowId> --type action --piece <name> --action-name <id> --after <parent> --input '{...}'
250
+ imbrace workflow node update <flowId> <nodeName> --input '{...}'
251
+ imbrace workflow node delete <flowId> <nodeName> --yes
252
+ imbrace workflow node add-raw <flowId> --op-file <path> # advanced types: ROUTER, LOOP_ON_ITEMS, CODE
253
+ ```
254
+
255
+ **Connections (OAuth/API keys for external services)**
256
+ ```bash
257
+ imbrace workflow conn list
258
+ imbrace workflow conn get <connId>
259
+ imbrace workflow conn create --piece slack --type SECRET_TEXT --value "xoxb-..." [--display-name <X>]
260
+ imbrace workflow conn delete <connId> --yes
261
+ ```
262
+
263
+ **Lifecycle**
264
+ ```bash
265
+ imbrace workflow publish <flowId> # lock current draft as production
266
+ imbrace workflow enable <flowId> # auto-trigger on (requires publish first)
267
+ imbrace workflow disable <flowId> # stop auto-trigger
268
+ imbrace workflow run <flowId> --payload '{...}' [--sync]
269
+ ```
270
+
271
+ **Folders (organize flows — UI calls them "Categories")**
272
+ ```bash
273
+ imbrace workflow folder list / get <id> / create --name / update <id> --name / delete <id> --yes
274
+ ```
275
+
276
+ The platform auto-creates 4 system folders that show up as Categories in the UI:
277
+
278
+ | UI Category | Purpose | Folder name in API |
279
+ |---|---|---|
280
+ | Channel Workflow | Messaging / channel automation | `Channel Workflow` |
281
+ | Board Automation | Triggered by data-board events | `Board Automation` |
282
+ | AI Agent Skills | Skills callable by AI agents | `AI Agent Capabilities` |
283
+ | Others | Everything else | `Others` |
284
+
285
+ Use `workflow folder list` to discover their IDs, then `workflow create --folder-id <id>` or `workflow move <flowId> --folder-id <id>` to place a flow in a category. Pass `--folder-id NULL` to unfile.
286
+
287
+ **MCP servers (Model Context Protocol — let AI agents call Activepieces tools)**
288
+ ```bash
289
+ imbrace workflow mcp list / get <id> / create --name / delete <id> --yes
290
+ imbrace workflow mcp rotate-token <mcpId> --yes # token shown once at create + rotate
291
+ ```
292
+
293
+ **Variable syntax inside node `input`**
294
+
295
+ - `{{trigger.body.X}}` — field `X` from webhook payload
296
+ - `{{trigger.X}}` — top-level trigger field (for piece triggers)
297
+ - `{{step_1.output.Y}}` — output field `Y` from step_1
298
+ - `{{connections.<id>.access_token}}` — connection field
299
+
300
+ **Known issue:** `workflow run --sync` may time out at ~30s even when the flow finishes faster. Workaround: use `workflow runs` + `run-detail <runId>` to fetch the result.
301
+
302
+ ---
303
+
304
+ ## For Coding Agents
305
+
306
+ Set up a CRM pipeline with sample data:
307
+
308
+ ```bash
309
+ # 1. Verify login
310
+ imbrace whoami --json
311
+
312
+ # 2. Create a board (--json skips interactive field prompts)
313
+ imbrace data-board create --name "Leads" --json
314
+ # → note the board _id from response
315
+
316
+ # 3. Add schema fields
317
+ imbrace data-board create-field <boardId> --name "Company" --type ShortText --json
318
+ imbrace data-board create-field <boardId> --name "Contact" --type ShortText --json
319
+ imbrace data-board create-field <boardId> --name "Deal Value" --type Number --json
320
+ imbrace data-board create-field <boardId> --name "Stage" --type SingleSelection --json
321
+ # → note each field _id from response
322
+
323
+ # 4. Add records
324
+ imbrace data-board create-item <boardId> --fields '[
325
+ {"board_field_id": "<companyFieldId>", "value": "Acme Corp"},
326
+ {"board_field_id": "<contactFieldId>", "value": "John Doe"},
327
+ {"board_field_id": "<dealValueFieldId>", "value": "75000"},
328
+ {"board_field_id": "<stageFieldId>", "value": "Negotiation"}
329
+ ]' --json
330
+
331
+ # 5. Verify
332
+ imbrace data-board list-items --board-id <boardId> --json
333
+ ```
334
+
335
+ > Always use `--json` flag so output can be parsed programmatically.
336
+ > If a command returns 401, run `imbrace login --api-key api_xxx...` again.
337
+
338
+ For complete CLI reference for coding agents, see [`llms.txt`](./llms.txt).
339
+
340
+ **Tip — one-shot setup for an AI agent:**
341
+ ```bash
342
+ imbrace docs > /tmp/imbrace-llms.txt # ~30 KB reference, bundled with the package
343
+ # then feed /tmp/imbrace-llms.txt into your agent's context (Claude Code, Cursor, ...)
344
+ ```
345
+ The `imbrace docs` command prints the full `llms.txt` shipped inside the npm package — no network or repo clone needed.
346
+
347
+ ---
348
+
349
+ ## Project Structure
350
+
351
+ ```
352
+ imbrace-cli/
353
+ ├── README.md ← This file
354
+ ├── llms.txt ← Reference for coding agents (Claude/Cursor/...)
355
+ ├── install.sh ← One-shot installer (npm link + cross-shell PATH)
356
+ ├── report/ ← Reports (BUG_REPORT, SDK_REPORT, PROMPT_GUIDE)
357
+
358
+ ├── api/ ← Hono REST API (proxy to Imbrace platform)
359
+ │ └── src/
360
+ │ ├── index.ts ← Entry point, port 3456
361
+ │ ├── middleware/auth.ts ← Auth via @imbrace/sdk
362
+ │ └── routes/
363
+ │ ├── auth.ts ← POST /auth/login
364
+ │ ├── data-board.ts ← CRUD /data-board/*
365
+ │ ├── ai-agent.ts ← CRUD /ai-agent/* (uses client.agent.createUseCase)
366
+ │ └── workflow.ts ← CRUD /workflow/*, /workflow/piece/*, /workflow/:id/nodes/*
367
+
368
+ └── cli/ ← oclif CLI
369
+ └── src/
370
+ ├── base-command.ts ← Auto-prompts login if not authenticated
371
+ ├── config.ts ← Credential store (via `conf` package)
372
+ ├── http.ts ← HTTP client → API server
373
+ └── commands/
374
+ ├── login.ts
375
+ ├── logout.ts
376
+ ├── whoami.ts
377
+ ├── data-board/
378
+ │ ├── list.ts
379
+ │ ├── create.ts
380
+ │ ├── create-field.ts
381
+ │ ├── create-item.ts
382
+ │ ├── list-items.ts
383
+ │ ├── update-item.ts
384
+ │ ├── delete-item.ts
385
+ │ └── export-csv.ts
386
+ ├── ai-agent/
387
+ │ ├── list.ts
388
+ │ ├── get.ts
389
+ │ ├── create.ts
390
+ │ ├── update.ts
391
+ │ ├── delete.ts
392
+ │ ├── list-providers.ts ← LLM providers discovery
393
+ │ ├── list-models.ts ← Models per provider
394
+ │ ├── list-folders.ts ← Knowledge Hub folders
395
+ │ └── list-files.ts ← Files in a KH folder
396
+ └── workflow/
397
+ ├── list.ts
398
+ ├── get.ts
399
+ ├── create.ts
400
+ ├── delete.ts
401
+ ├── runs.ts
402
+ ├── run-detail.ts
403
+ ├── publish.ts ← Lifecycle
404
+ ├── enable.ts
405
+ ├── disable.ts
406
+ ├── run.ts ← Trigger flow [--sync]
407
+ ├── piece/
408
+ │ ├── list.ts
409
+ │ └── detail.ts
410
+ ├── node/
411
+ │ ├── add.ts
412
+ │ ├── update.ts
413
+ │ ├── delete.ts
414
+ │ ├── list.ts
415
+ │ └── add-raw.ts ← ROUTER / LOOP_ON_ITEMS / CODE
416
+ ├── conn/ ← Connections (OAuth/API keys)
417
+ │ ├── list.ts
418
+ │ ├── get.ts
419
+ │ ├── create.ts
420
+ │ └── delete.ts
421
+ ├── folder/ ← Organize flows
422
+ │ ├── list.ts
423
+ │ ├── get.ts
424
+ │ ├── create.ts
425
+ │ ├── update.ts
426
+ │ └── delete.ts
427
+ └── mcp/ ← Model Context Protocol servers
428
+ ├── list.ts
429
+ ├── get.ts
430
+ ├── create.ts
431
+ ├── delete.ts
432
+ └── rotate-token.ts
433
+ ```
434
+
435
+ ---
436
+
437
+ ## Adding a New Service
438
+
439
+ 1. Create `api/src/routes/<service>.ts`
440
+ 2. Mount in `api/src/index.ts` with `authMiddleware`
441
+ 3. Create `cli/src/commands/<service>/*.ts`
442
+ 4. Add topic in `cli/package.json` under `oclif.topics`
443
+ 5. Rebuild CLI: `cd cli && npm run build` (or re-run `./install.sh`)
@@ -18,6 +18,11 @@ export default class AiAgentCreate extends BaseCommand {
18
18
  category: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
19
19
  "guardrail-id": import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
20
20
  "preload-information": import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
21
+ "folder-ids": import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
22
+ "default-folder-id": import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
23
+ "knowledge-hubs": import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
24
+ "board-ids": import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
25
+ "file-ids": import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
21
26
  "show-thinking": import("@oclif/core/interfaces").BooleanFlag<boolean>;
22
27
  streaming: import("@oclif/core/interfaces").BooleanFlag<boolean>;
23
28
  "use-memory": import("@oclif/core/interfaces").BooleanFlag<boolean>;
@@ -31,6 +31,12 @@ export default class AiAgentCreate extends BaseCommand {
31
31
  }),
32
32
  "guardrail-id": Flags.string({ description: "Attach a guardrail by ID" }),
33
33
  "preload-information": Flags.string({ description: "Static info auto-injected into context every chat" }),
34
+ // Knowledge Support (UI tab) — comma-separated IDs
35
+ "folder-ids": Flags.string({ description: "Comma-separated Knowledge Hub folder IDs (RAG sources)" }),
36
+ "default-folder-id": Flags.string({ description: "Default folder ID for new files" }),
37
+ "knowledge-hubs": Flags.string({ description: "Comma-separated Knowledge Hub IDs" }),
38
+ "board-ids": Flags.string({ description: "Comma-separated Document Model (data board) IDs" }),
39
+ "file-ids": Flags.string({ description: "Comma-separated file IDs already uploaded to Knowledge Hub" }),
34
40
  // Behavior runtime toggles
35
41
  "show-thinking": Flags.boolean({ description: "Show model's thinking process (default: false)", allowNo: true }),
36
42
  streaming: Flags.boolean({ description: "Stream response token-by-token (default: true)", allowNo: true }),
@@ -60,6 +66,11 @@ export default class AiAgentCreate extends BaseCommand {
60
66
  ...(flags.category && { category: [flags.category] }),
61
67
  ...(flags["guardrail-id"] && { guardrail_id: flags["guardrail-id"] }),
62
68
  ...(flags["preload-information"] && { preload_information: flags["preload-information"] }),
69
+ ...(flags["folder-ids"] && { folder_ids: flags["folder-ids"].split(",").map(s => s.trim()).filter(Boolean) }),
70
+ ...(flags["default-folder-id"] && { default_folder_id: flags["default-folder-id"] }),
71
+ ...(flags["knowledge-hubs"] && { knowledge_hubs: flags["knowledge-hubs"].split(",").map(s => s.trim()).filter(Boolean) }),
72
+ ...(flags["board-ids"] && { board_ids: flags["board-ids"].split(",").map(s => s.trim()).filter(Boolean) }),
73
+ ...(flags["file-ids"] && { file_ids: flags["file-ids"].split(",").map(s => s.trim()).filter(Boolean) }),
63
74
  ...(flags["show-thinking"] !== undefined && { show_thinking_process: flags["show-thinking"] }),
64
75
  ...(flags.streaming !== undefined && { streaming: flags.streaming }),
65
76
  ...(flags["use-memory"] !== undefined && { use_memory: flags["use-memory"] }),
@@ -0,0 +1,10 @@
1
+ import { BaseCommand } from "../../base-command.js";
2
+ export default class AiAgentListFiles extends BaseCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {
6
+ "folder-id": import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
7
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
8
+ };
9
+ run(): Promise<void>;
10
+ }
@@ -0,0 +1,40 @@
1
+ import { Flags } from "@oclif/core";
2
+ import { BaseCommand } from "../../base-command.js";
3
+ import { apiRequest } from "../../http.js";
4
+ export default class AiAgentListFiles extends BaseCommand {
5
+ static description = "List files inside a Knowledge Hub folder (use IDs with --file-ids on create/update)";
6
+ static examples = [
7
+ "imbrace ai-agent list-files --folder-id <folderId>",
8
+ "imbrace ai-agent list-files --folder-id <folderId> --json",
9
+ ];
10
+ static flags = {
11
+ "folder-id": Flags.string({
12
+ description: "Knowledge Hub folder ID. Use 'imbrace ai-agent list-folders' to discover.",
13
+ required: true,
14
+ }),
15
+ json: Flags.boolean({ description: "Output as JSON" }),
16
+ };
17
+ async run() {
18
+ const { flags } = await this.parse(AiAgentListFiles);
19
+ try {
20
+ const res = await apiRequest(`/ai-agent/folders/${encodeURIComponent(flags["folder-id"])}/files`);
21
+ if (flags.json) {
22
+ this.log(JSON.stringify(res, null, 2));
23
+ return;
24
+ }
25
+ this.log(`\n Found ${res.count} file(s) in folder "${flags["folder-id"]}":\n`);
26
+ this.log(" ID NAME STATUS");
27
+ this.log(" ─────────────────────────────────────────────────────────────────────────────────────");
28
+ for (const f of res.data || []) {
29
+ const id = (f._id || f.id || "").padEnd(40);
30
+ const name = (f.original_name || f.name || "").padEnd(36);
31
+ const status = f.embedding_status || f.status || "";
32
+ this.log(` ${id} ${name} ${status}`);
33
+ }
34
+ this.log("");
35
+ }
36
+ catch (error) {
37
+ this.error(`Failed: ${error.message}`);
38
+ }
39
+ }
40
+ }
@@ -0,0 +1,10 @@
1
+ import { BaseCommand } from "../../base-command.js";
2
+ export default class AiAgentListFolders extends BaseCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {
6
+ search: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
7
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
8
+ };
9
+ run(): Promise<void>;
10
+ }
@@ -0,0 +1,39 @@
1
+ import { Flags } from "@oclif/core";
2
+ import { BaseCommand } from "../../base-command.js";
3
+ import { apiRequest } from "../../http.js";
4
+ export default class AiAgentListFolders extends BaseCommand {
5
+ static description = "List Knowledge Hub folders (use IDs with --folder-ids on create/update)";
6
+ static examples = [
7
+ "imbrace ai-agent list-folders",
8
+ "imbrace ai-agent list-folders --search support",
9
+ "imbrace ai-agent list-folders --json",
10
+ ];
11
+ static flags = {
12
+ search: Flags.string({ char: "s", description: "Filter by name (case-insensitive)" }),
13
+ json: Flags.boolean({ description: "Output as JSON" }),
14
+ };
15
+ async run() {
16
+ const { flags } = await this.parse(AiAgentListFolders);
17
+ const qs = flags.search ? `?q=${encodeURIComponent(flags.search)}` : "";
18
+ try {
19
+ const res = await apiRequest(`/ai-agent/folders${qs}`);
20
+ if (flags.json) {
21
+ this.log(JSON.stringify(res, null, 2));
22
+ return;
23
+ }
24
+ this.log(`\n Found ${res.count} folder(s):\n`);
25
+ this.log(" ID NAME FILES");
26
+ this.log(" ──────────────────────────────────────────────────────────────────────────────");
27
+ for (const f of res.data || []) {
28
+ const id = (f._id || f.id || "").padEnd(40);
29
+ const name = (f.name || "").padEnd(28);
30
+ const files = String(f.file_count ?? 0).padStart(5);
31
+ this.log(` ${id} ${name} ${files}`);
32
+ }
33
+ this.log(`\n Use 'imbrace ai-agent list-files --folder-id <id>' to see files.\n`);
34
+ }
35
+ catch (error) {
36
+ this.error(`Failed: ${error.message}`);
37
+ }
38
+ }
39
+ }
@@ -22,7 +22,7 @@ export default class AiAgentListProviders extends BaseCommand {
22
22
  this.log(" ID NAME TYPE MODELS");
23
23
  this.log(" ─────────────────────────────────────────────────────────────────────────────");
24
24
  for (const p of res.data || []) {
25
- const id = (p._id || "").padEnd(40);
25
+ const id = (p.id || p.provider_id || p._id || "").padEnd(40);
26
26
  const name = (p.name || "").padEnd(16);
27
27
  const type = (p.type || "").padEnd(11);
28
28
  const models = (p.models || []).slice(0, 3).join(", ") + ((p.models || []).length > 3 ? `, +${p.models.length - 3} more` : "");
@@ -21,6 +21,11 @@ export default class AiAgentUpdate extends BaseCommand {
21
21
  category: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
22
22
  "guardrail-id": import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
23
23
  "preload-information": import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
24
+ "folder-ids": import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
25
+ "default-folder-id": import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
26
+ "knowledge-hubs": import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
27
+ "board-ids": import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
28
+ "file-ids": import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
24
29
  "show-thinking": import("@oclif/core/interfaces").BooleanFlag<boolean>;
25
30
  streaming: import("@oclif/core/interfaces").BooleanFlag<boolean>;
26
31
  "use-memory": import("@oclif/core/interfaces").BooleanFlag<boolean>;
@@ -35,6 +35,12 @@ export default class AiAgentUpdate extends BaseCommand {
35
35
  }),
36
36
  "guardrail-id": Flags.string({ description: "Guardrail ID (set to empty string to remove)" }),
37
37
  "preload-information": Flags.string({ description: "Preload information" }),
38
+ // Knowledge Support
39
+ "folder-ids": Flags.string({ description: "Comma-separated Knowledge Hub folder IDs" }),
40
+ "default-folder-id": Flags.string({ description: "Default folder ID" }),
41
+ "knowledge-hubs": Flags.string({ description: "Comma-separated Knowledge Hub IDs" }),
42
+ "board-ids": Flags.string({ description: "Comma-separated Document Model (data board) IDs" }),
43
+ "file-ids": Flags.string({ description: "Comma-separated file IDs" }),
38
44
  // Runtime toggles
39
45
  "show-thinking": Flags.boolean({ description: "Show thinking process", allowNo: true }),
40
46
  streaming: Flags.boolean({ description: "Stream response", allowNo: true }),
@@ -76,6 +82,16 @@ export default class AiAgentUpdate extends BaseCommand {
76
82
  body.guardrail_id = flags["guardrail-id"];
77
83
  if (flags["preload-information"] !== undefined)
78
84
  body.preload_information = flags["preload-information"];
85
+ if (flags["folder-ids"] !== undefined)
86
+ body.folder_ids = flags["folder-ids"].split(",").map(s => s.trim()).filter(Boolean);
87
+ if (flags["default-folder-id"] !== undefined)
88
+ body.default_folder_id = flags["default-folder-id"];
89
+ if (flags["knowledge-hubs"] !== undefined)
90
+ body.knowledge_hubs = flags["knowledge-hubs"].split(",").map(s => s.trim()).filter(Boolean);
91
+ if (flags["board-ids"] !== undefined)
92
+ body.board_ids = flags["board-ids"].split(",").map(s => s.trim()).filter(Boolean);
93
+ if (flags["file-ids"] !== undefined)
94
+ body.file_ids = flags["file-ids"].split(",").map(s => s.trim()).filter(Boolean);
79
95
  if (flags["show-thinking"] !== undefined)
80
96
  body.show_thinking_process = flags["show-thinking"];
81
97
  if (flags.streaming !== undefined)
@@ -0,0 +1,10 @@
1
+ import { Command } from "@oclif/core";
2
+ export default class Docs extends Command {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {
6
+ path: import("@oclif/core/interfaces").BooleanFlag<boolean>;
7
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
8
+ };
9
+ run(): Promise<void>;
10
+ }