@imbrace/cli 0.3.0 → 0.4.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.
Files changed (68) hide show
  1. package/dist/base-command.js +20 -18
  2. package/dist/commands/ai-agent/create.js +8 -7
  3. package/dist/commands/ai-agent/delete.js +6 -4
  4. package/dist/commands/ai-agent/get.js +5 -5
  5. package/dist/commands/ai-agent/list-files.js +7 -5
  6. package/dist/commands/ai-agent/list-folders.js +7 -6
  7. package/dist/commands/ai-agent/list-models.js +5 -5
  8. package/dist/commands/ai-agent/list-providers.js +5 -5
  9. package/dist/commands/ai-agent/list.js +7 -5
  10. package/dist/commands/ai-agent/update.js +5 -4
  11. package/dist/commands/data-board/create-field.js +6 -4
  12. package/dist/commands/data-board/create-item.js +10 -8
  13. package/dist/commands/data-board/create.js +8 -6
  14. package/dist/commands/data-board/delete-item.js +6 -4
  15. package/dist/commands/data-board/export-csv.js +3 -2
  16. package/dist/commands/data-board/list-items.js +9 -11
  17. package/dist/commands/data-board/list.js +7 -5
  18. package/dist/commands/data-board/update-item.js +8 -6
  19. package/dist/commands/login.d.ts +0 -1
  20. package/dist/commands/login.js +39 -55
  21. package/dist/commands/whoami.js +0 -2
  22. package/dist/commands/workflow/conn/create.js +33 -16
  23. package/dist/commands/workflow/conn/delete.js +6 -4
  24. package/dist/commands/workflow/conn/get.js +5 -4
  25. package/dist/commands/workflow/conn/list.js +7 -5
  26. package/dist/commands/workflow/create.js +16 -14
  27. package/dist/commands/workflow/delete.js +6 -4
  28. package/dist/commands/workflow/disable.js +9 -4
  29. package/dist/commands/workflow/enable.js +9 -4
  30. package/dist/commands/workflow/folder/create.js +11 -10
  31. package/dist/commands/workflow/folder/delete.js +6 -4
  32. package/dist/commands/workflow/folder/get.js +5 -4
  33. package/dist/commands/workflow/folder/list.js +7 -5
  34. package/dist/commands/workflow/folder/update.js +6 -4
  35. package/dist/commands/workflow/get.js +5 -4
  36. package/dist/commands/workflow/list.js +8 -6
  37. package/dist/commands/workflow/mcp/create.js +10 -9
  38. package/dist/commands/workflow/mcp/delete.js +6 -4
  39. package/dist/commands/workflow/mcp/get.js +5 -4
  40. package/dist/commands/workflow/mcp/list.js +9 -5
  41. package/dist/commands/workflow/mcp/rotate-token.js +7 -5
  42. package/dist/commands/workflow/move.js +10 -4
  43. package/dist/commands/workflow/node/add-raw.js +6 -4
  44. package/dist/commands/workflow/node/add.js +70 -21
  45. package/dist/commands/workflow/node/delete.js +12 -4
  46. package/dist/commands/workflow/node/list.js +8 -5
  47. package/dist/commands/workflow/node/update.js +44 -8
  48. package/dist/commands/workflow/piece/detail.js +5 -4
  49. package/dist/commands/workflow/piece/list.js +22 -6
  50. package/dist/commands/workflow/publish.js +9 -4
  51. package/dist/commands/workflow/run-detail.js +5 -4
  52. package/dist/commands/workflow/run.js +10 -7
  53. package/dist/commands/workflow/runs.js +7 -5
  54. package/dist/config.d.ts +5 -5
  55. package/dist/config.js +6 -12
  56. package/dist/lib/ai-agent.d.ts +40 -0
  57. package/dist/lib/ai-agent.js +150 -0
  58. package/dist/lib/client.d.ts +7 -0
  59. package/dist/lib/client.js +21 -0
  60. package/dist/lib/gateway.d.ts +3 -0
  61. package/dist/lib/gateway.js +31 -0
  62. package/dist/lib/workflow.d.ts +20 -0
  63. package/dist/lib/workflow.js +71 -0
  64. package/dist/select-board.js +4 -3
  65. package/llms.txt +1 -0
  66. package/package.json +2 -2
  67. package/dist/http.d.ts +0 -9
  68. package/dist/http.js +0 -40
@@ -1,6 +1,6 @@
1
1
  import { Flags } from "@oclif/core";
2
2
  import { BaseCommand } from "../../base-command.js";
3
- import { apiRequest } from "../../http.js";
3
+ import { getClient } from "../../lib/client.js";
4
4
  export default class WorkflowRuns extends BaseCommand {
5
5
  static description = "List recent workflow runs (execution history)";
6
6
  static examples = [
@@ -14,15 +14,17 @@ export default class WorkflowRuns extends BaseCommand {
14
14
  async run() {
15
15
  const { flags } = await this.parse(WorkflowRuns);
16
16
  try {
17
- const res = await apiRequest(`/workflow/runs?limit=${flags.limit}`);
17
+ const client = getClient();
18
+ const res = await client.workflows.listRuns({ limit: flags.limit });
19
+ const data = res?.data ?? [];
18
20
  if (flags.json) {
19
- this.log(JSON.stringify(res, null, 2));
21
+ this.log(JSON.stringify({ ok: true, count: data.length, data }, null, 2));
20
22
  return;
21
23
  }
22
- this.log(`\n Found ${res.count} run(s):\n`);
24
+ this.log(`\n Found ${data.length} run(s):\n`);
23
25
  this.log(" RUN ID FLOW ID STATUS DURATION");
24
26
  this.log(" ───────────────────────────────────────────────────────────────────────");
25
- for (const run of res.data || []) {
27
+ for (const run of data) {
26
28
  const id = (run.id || "").padEnd(24);
27
29
  const flowId = (run.flowId || "").padEnd(24);
28
30
  const status = (run.status || "").padEnd(12);
package/dist/config.d.ts CHANGED
@@ -3,11 +3,13 @@ interface ImbraceConfig {
3
3
  credential?: string;
4
4
  method?: "api-key" | "password";
5
5
  email?: string;
6
- apiUrl?: string;
7
6
  }
8
7
  /**
9
- * Saves credentials to ~/.config/imbrace/config.json
10
- * Uses `conf` package — cross-platform, auto-create
8
+ * Saves credentials via the `conf` package — cross-platform, auto-create.
9
+ * Path depends on OS:
10
+ * macOS: ~/Library/Preferences/imbrace-nodejs/config.json
11
+ * Linux: ~/.config/imbrace-nodejs/config.json
12
+ * Windows: %APPDATA%/imbrace-nodejs/Config/config.json
11
13
  */
12
14
  export declare const config: Conf<ImbraceConfig>;
13
15
  export declare function saveCredential(opts: {
@@ -16,12 +18,10 @@ export declare function saveCredential(opts: {
16
18
  email?: string;
17
19
  }): void;
18
20
  export declare function getCredential(): string | undefined;
19
- export declare function getApiUrl(): string;
20
21
  export declare function clearCredential(): void;
21
22
  export declare function getAuthInfo(): {
22
23
  credential: string | undefined;
23
24
  method: "api-key" | "password" | undefined;
24
25
  email: string | undefined;
25
- apiUrl: string | undefined;
26
26
  };
27
27
  export {};
package/dist/config.js CHANGED
@@ -1,14 +1,12 @@
1
1
  import Conf from "conf";
2
2
  /**
3
- * Saves credentials to ~/.config/imbrace/config.json
4
- * Uses `conf` package — cross-platform, auto-create
3
+ * Saves credentials via the `conf` package — cross-platform, auto-create.
4
+ * Path depends on OS:
5
+ * macOS: ~/Library/Preferences/imbrace-nodejs/config.json
6
+ * Linux: ~/.config/imbrace-nodejs/config.json
7
+ * Windows: %APPDATA%/imbrace-nodejs/Config/config.json
5
8
  */
6
- export const config = new Conf({
7
- projectName: "imbrace",
8
- defaults: {
9
- apiUrl: "http://localhost:3456",
10
- },
11
- });
9
+ export const config = new Conf({ projectName: "imbrace" });
12
10
  export function saveCredential(opts) {
13
11
  config.set("credential", opts.credential);
14
12
  config.set("method", opts.method);
@@ -18,9 +16,6 @@ export function saveCredential(opts) {
18
16
  export function getCredential() {
19
17
  return config.get("credential");
20
18
  }
21
- export function getApiUrl() {
22
- return config.get("apiUrl") || "http://localhost:3456";
23
- }
24
19
  export function clearCredential() {
25
20
  config.delete("credential");
26
21
  config.delete("method");
@@ -31,6 +26,5 @@ export function getAuthInfo() {
31
26
  credential: config.get("credential"),
32
27
  method: config.get("method"),
33
28
  email: config.get("email"),
34
- apiUrl: config.get("apiUrl"),
35
29
  };
36
30
  }
@@ -0,0 +1,40 @@
1
+ import { GW } from "./gateway.js";
2
+ export interface CreateAgentInput {
3
+ name: string;
4
+ description?: string;
5
+ instructions?: string;
6
+ model?: string;
7
+ provider_id?: string;
8
+ mode?: string;
9
+ channel?: string;
10
+ category?: string[] | string;
11
+ personality_role?: string;
12
+ core_task?: string;
13
+ tone_and_style?: string;
14
+ response_length?: string;
15
+ banned_words?: string;
16
+ preload_information?: string;
17
+ guardrail_id?: string;
18
+ show_thinking_process?: boolean;
19
+ streaming?: boolean;
20
+ use_memory?: boolean;
21
+ temperature?: number;
22
+ knowledge_hubs?: string[];
23
+ folder_ids?: string[];
24
+ default_folder_id?: string;
25
+ board_ids?: string[];
26
+ file_ids?: string[];
27
+ }
28
+ export declare function createAgent(body: CreateAgentInput): Promise<any>;
29
+ export declare function updateAgent(id: string, body: Record<string, any>): Promise<any>;
30
+ export declare function listProviders(): Promise<{
31
+ id: any;
32
+ _id: any;
33
+ provider_id: any;
34
+ name: any;
35
+ type: any;
36
+ is_default: boolean;
37
+ models: any;
38
+ }[]>;
39
+ export declare function listProviderModels(providerId: string): Promise<any>;
40
+ export { GW };
@@ -0,0 +1,150 @@
1
+ // AI Agent payload builders — mirror the legacy api/src/routes/ai-agent.ts
2
+ // behavior so command output stays consistent across the api→sdk migration.
3
+ import { getClient } from "./client.js";
4
+ import { fetchSystemModels, gatewayFetch, GW } from "./gateway.js";
5
+ export async function createAgent(body) {
6
+ const client = getClient();
7
+ const slug = body.name.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
8
+ const workflowName = `${slug}_v${Date.now()}`;
9
+ const data = await client.agent.createUseCase({
10
+ usecase: {
11
+ title: body.name,
12
+ short_description: body.description || "",
13
+ agent_type: "agent",
14
+ demo_url: "https://chat-widgetv2.imbrace.co",
15
+ supported_channels: [{ title: "channel_", icon: "" }],
16
+ },
17
+ assistant: {
18
+ name: body.name,
19
+ description: body.description || "",
20
+ instructions: body.instructions || "",
21
+ workflow_name: workflowName,
22
+ credential_name: `${body.mode || "standard"} | ${body.name}`,
23
+ provider_id: body.provider_id || "system",
24
+ model_id: body.model || "Default",
25
+ agent_type: "agent",
26
+ mode: body.mode || "standard",
27
+ version: 2,
28
+ channel: body.channel || "",
29
+ category: body.category || ["Support"],
30
+ personality_role: body.personality_role || "",
31
+ core_task: body.core_task || "",
32
+ tone_and_style: body.tone_and_style || "",
33
+ response_length: body.response_length || "",
34
+ banned_words: body.banned_words || "",
35
+ preload_information: body.preload_information || "",
36
+ guardrail_id: body.guardrail_id || "",
37
+ show_thinking_process: body.show_thinking_process ?? false,
38
+ streaming: body.streaming ?? true,
39
+ use_memory: body.use_memory ?? true,
40
+ temperature: typeof body.temperature === "number" ? body.temperature : 0.1,
41
+ knowledge_hubs: body.knowledge_hubs || [],
42
+ folder_ids: body.folder_ids || [],
43
+ default_folder_id: body.default_folder_id || "",
44
+ board_ids: body.board_ids || [],
45
+ file_ids: body.file_ids || [],
46
+ workflow_function_call: [],
47
+ sub_agents: [],
48
+ team_leads: [],
49
+ metadata: {
50
+ other_requirements: [],
51
+ channel_id: "",
52
+ team_ids: [],
53
+ tool_server: null,
54
+ enable_echart: false,
55
+ top_k_relevant_results: 3,
56
+ top_k: 40,
57
+ max_steps: 10,
58
+ },
59
+ },
60
+ });
61
+ return data?.data ?? data;
62
+ }
63
+ const ASSISTANT_FIELDS = [
64
+ "instructions", "description", "provider_id",
65
+ "personality_role", "core_task", "tone_and_style", "response_length",
66
+ "banned_words", "category", "guardrail_id", "preload_information", "channel",
67
+ "folder_ids", "default_folder_id", "knowledge_hubs", "board_ids", "file_ids",
68
+ ];
69
+ export async function updateAgent(id, body) {
70
+ const client = getClient();
71
+ const tpl = (await client.agent.get(id))?.data ?? {};
72
+ const assistantId = tpl.assistant_id;
73
+ const results = {};
74
+ const hasAssistantUpdate = assistantId && (body.name || body.model || typeof body.temperature === "number" ||
75
+ typeof body.streaming === "boolean" || typeof body.use_memory === "boolean" ||
76
+ typeof body.show_thinking_process === "boolean" || body.mode ||
77
+ ASSISTANT_FIELDS.some((f) => body[f] !== undefined));
78
+ if (hasAssistantUpdate) {
79
+ // chatAi.updateAiAgent uses PUT (full replace) — fetch+merge so unchanged
80
+ // fields aren't reset to null.
81
+ const currentAssistant = await gatewayFetch(`/v3/ai/assistants/${assistantId}`);
82
+ const aUpdate = {
83
+ ...currentAssistant,
84
+ name: body.name ?? currentAssistant.name,
85
+ workflow_name: currentAssistant.workflow_name ||
86
+ `${(body.name ?? currentAssistant.name).toLowerCase().replace(/[^a-z0-9]+/g, "_")}_v${Date.now()}`,
87
+ };
88
+ if (body.model)
89
+ aUpdate.model_id = body.model;
90
+ if (body.mode)
91
+ aUpdate.mode = body.mode;
92
+ if (typeof body.temperature === "number")
93
+ aUpdate.temperature = body.temperature;
94
+ if (typeof body.streaming === "boolean")
95
+ aUpdate.streaming = body.streaming;
96
+ if (typeof body.use_memory === "boolean")
97
+ aUpdate.use_memory = body.use_memory;
98
+ if (typeof body.show_thinking_process === "boolean")
99
+ aUpdate.show_thinking_process = body.show_thinking_process;
100
+ for (const f of ASSISTANT_FIELDS) {
101
+ if (body[f] !== undefined)
102
+ aUpdate[f] = body[f];
103
+ }
104
+ results.assistant = await client.chatAi.updateAiAgent(assistantId, aUpdate);
105
+ }
106
+ if (body.name || body.description) {
107
+ const tUpdate = {};
108
+ if (body.name)
109
+ tUpdate.title = body.name;
110
+ if (body.description)
111
+ tUpdate.short_description = body.description;
112
+ results.template = await client.agent.updateUseCase(id, tUpdate);
113
+ }
114
+ if (Object.keys(results).length === 0) {
115
+ throw new Error("No update fields provided");
116
+ }
117
+ return results;
118
+ }
119
+ export async function listProviders() {
120
+ const client = getClient();
121
+ const [r, systemModels] = await Promise.all([
122
+ client.ai.listProviders(),
123
+ fetchSystemModels(),
124
+ ]);
125
+ const arr = (r?.data || r);
126
+ return [
127
+ { id: "system", _id: "system", provider_id: "system", name: "system", type: "system", is_default: true, models: systemModels },
128
+ ...arr.map((p) => ({
129
+ id: p.provider_id || p._id,
130
+ _id: p._id,
131
+ provider_id: p.provider_id || p._id,
132
+ name: p.name,
133
+ type: p.type,
134
+ is_default: false,
135
+ models: (p.models || []).map((m) => typeof m === "string" ? m : m.name),
136
+ })),
137
+ ];
138
+ }
139
+ export async function listProviderModels(providerId) {
140
+ if (providerId === "system")
141
+ return fetchSystemModels();
142
+ const client = getClient();
143
+ const r = await client.ai.listProviders();
144
+ const arr = (r?.data || r);
145
+ const provider = arr.find((p) => p.provider_id === providerId || p._id === providerId);
146
+ if (!provider)
147
+ throw new Error(`Provider "${providerId}" not found`);
148
+ return (provider.models || []).map((m) => typeof m === "string" ? m : m.name);
149
+ }
150
+ export { GW };
@@ -0,0 +1,7 @@
1
+ import { ImbraceClient } from "@imbrace/sdk";
2
+ /**
3
+ * Build an authenticated ImbraceClient from the saved credential.
4
+ * Caches per-process — re-call to refresh after login.
5
+ */
6
+ export declare function getClient(): ImbraceClient;
7
+ export declare function resetClient(): void;
@@ -0,0 +1,21 @@
1
+ import { ImbraceClient } from "@imbrace/sdk";
2
+ import { getCredential } from "../config.js";
3
+ let cachedClient = null;
4
+ /**
5
+ * Build an authenticated ImbraceClient from the saved credential.
6
+ * Caches per-process — re-call to refresh after login.
7
+ */
8
+ export function getClient() {
9
+ if (cachedClient)
10
+ return cachedClient;
11
+ const credential = getCredential();
12
+ if (!credential) {
13
+ throw new Error("Not logged in. Run: imbrace login --api-key api_xxx...");
14
+ }
15
+ const isApiKey = credential.startsWith("sk-") || credential.startsWith("api_");
16
+ cachedClient = new ImbraceClient(isApiKey ? { apiKey: credential } : { accessToken: credential });
17
+ return cachedClient;
18
+ }
19
+ export function resetClient() {
20
+ cachedClient = null;
21
+ }
@@ -0,0 +1,3 @@
1
+ export declare const GW = "https://app-gatewayv2.imbrace.co";
2
+ export declare function gatewayFetch<T = any>(path: string, init?: RequestInit): Promise<T>;
3
+ export declare function fetchSystemModels(): Promise<string[]>;
@@ -0,0 +1,31 @@
1
+ // Direct gateway fetch for routes the SDK doesn't expose (e.g. workflow-agent
2
+ // system models, raw assistant fetch for PUT-merge).
3
+ import { getCredential } from "../config.js";
4
+ export const GW = "https://app-gatewayv2.imbrace.co";
5
+ function authHeader() {
6
+ const cred = getCredential();
7
+ if (!cred)
8
+ throw new Error("Not logged in. Run: imbrace login --api-key api_xxx...");
9
+ return cred.startsWith("api_") ? { "x-api-key": cred } : { authorization: `Bearer ${cred}` };
10
+ }
11
+ export async function gatewayFetch(path, init) {
12
+ const res = await fetch(`${GW}${path}`, {
13
+ ...init,
14
+ headers: { ...authHeader(), ...init?.headers },
15
+ });
16
+ if (!res.ok)
17
+ throw new Error(`[${res.status}] ${await res.text()}`);
18
+ return res.json();
19
+ }
20
+ // System provider only exposes one model "Default" via /workflow-agent endpoint.
21
+ // Empty/error → fall back to ["Default"] so create commands still work.
22
+ export async function fetchSystemModels() {
23
+ try {
24
+ const j = await gatewayFetch("/ai/v3/workflow-agent/models");
25
+ const arr = j?.data || j?.message?.data || [];
26
+ return arr.map((m) => (typeof m === "string" ? m : m.name)).filter(Boolean);
27
+ }
28
+ catch {
29
+ return ["Default"];
30
+ }
31
+ }
@@ -0,0 +1,20 @@
1
+ import { ImbraceClient } from "@imbrace/sdk";
2
+ export declare const PIECE_PREFIX = "@activepieces/";
3
+ export declare function normalizePieceName(input: string): string;
4
+ export declare function resolveProjectId(client: ImbraceClient): Promise<string>;
5
+ export declare function fetchPieceMeta(pieceName: string): Promise<{
6
+ version: string;
7
+ }>;
8
+ export declare function buildPropertySettings(input: Record<string, any>): Record<string, any>;
9
+ export interface FlatNode {
10
+ name: string;
11
+ type: string;
12
+ displayName?: string;
13
+ pieceName?: string;
14
+ actionName?: string;
15
+ triggerName?: string;
16
+ input?: any;
17
+ valid?: boolean;
18
+ }
19
+ export declare function flattenNodes(trigger: any): FlatNode[];
20
+ export declare function nextStepName(trigger: any): string;
@@ -0,0 +1,71 @@
1
+ import { gatewayFetch } from "./gateway.js";
2
+ export const PIECE_PREFIX = "@activepieces/";
3
+ // "slack" → "@activepieces/piece-slack" (idempotent)
4
+ export function normalizePieceName(input) {
5
+ if (input.startsWith(PIECE_PREFIX))
6
+ return input;
7
+ return `${PIECE_PREFIX}piece-${input.toLowerCase()}`;
8
+ }
9
+ // Resolve projectId by reusing the project of any existing flow.
10
+ export async function resolveProjectId(client) {
11
+ const flows = await client.workflows.listFlows();
12
+ const first = flows?.data?.[0];
13
+ if (!first?.projectId) {
14
+ throw new Error("Cannot resolve projectId — no existing flows to derive from. " +
15
+ "Create your first flow via the UI (cloud.imbrace.co/workflow-v2) once.");
16
+ }
17
+ return first.projectId;
18
+ }
19
+ // Backend rejects ops without correct pieceVersion + propertySettings,
20
+ // so we fetch piece metadata directly from the gateway.
21
+ export async function fetchPieceMeta(pieceName) {
22
+ const data = await gatewayFetch(`/activepieces/v1/pieces/${pieceName}`);
23
+ return { version: data.version };
24
+ }
25
+ // Each input key gets a `propertySettings: { type: "MANUAL" }` entry.
26
+ // authFields is the only special case — its schema lives one level deeper.
27
+ export function buildPropertySettings(input) {
28
+ const ps = {};
29
+ for (const k of Object.keys(input || {})) {
30
+ ps[k] = (k === "authFields" && typeof input[k] === "object")
31
+ ? { type: "MANUAL", schema: {} }
32
+ : { type: "MANUAL" };
33
+ }
34
+ return ps;
35
+ }
36
+ export function flattenNodes(trigger) {
37
+ const nodes = [];
38
+ function visit(node) {
39
+ if (!node)
40
+ return;
41
+ nodes.push({
42
+ name: node.name,
43
+ type: node.type,
44
+ displayName: node.displayName,
45
+ pieceName: node.settings?.pieceName,
46
+ actionName: node.settings?.actionName,
47
+ triggerName: node.settings?.triggerName,
48
+ input: node.settings?.input,
49
+ valid: node.valid,
50
+ });
51
+ if (node.nextAction)
52
+ visit(node.nextAction);
53
+ for (const ch of (node.children || [])) {
54
+ if (ch)
55
+ visit(ch);
56
+ }
57
+ if (node.firstLoopAction)
58
+ visit(node.firstLoopAction);
59
+ }
60
+ visit(trigger);
61
+ return nodes;
62
+ }
63
+ // Generate next available step_N name given the existing tree.
64
+ export function nextStepName(trigger) {
65
+ const nodes = flattenNodes(trigger);
66
+ const used = new Set(nodes.map((n) => n.name));
67
+ let i = 1;
68
+ while (used.has(`step_${i}`))
69
+ i++;
70
+ return `step_${i}`;
71
+ }
@@ -1,8 +1,9 @@
1
1
  import { select } from "@inquirer/prompts";
2
- import { apiRequest } from "./http.js";
2
+ import { getClient } from "./lib/client.js";
3
3
  export async function selectBoard() {
4
- const res = await apiRequest("/data-board/list");
5
- const boards = res.data || [];
4
+ const client = getClient();
5
+ const res = await client.boards.list();
6
+ const boards = res?.data ?? [];
6
7
  if (!boards.length)
7
8
  throw new Error("No boards found. Create a board first.");
8
9
  return select({
package/llms.txt CHANGED
@@ -27,6 +27,7 @@ Things to remember when using Imbrace CLI:
27
27
  - `imbrace help [command]` — Show help for any command
28
28
  - `imbrace autocomplete [shell]` — Display shell completion install instructions (bash, zsh, fish, powershell)
29
29
  - `imbrace --version` — Print CLI version
30
+ - `imbrace docs` — Print the bundled `llms.txt` (this file). Pipe to a file (`imbrace docs > llms.txt`) and feed into a coding agent's context for one-shot reference. `--path` prints just the absolute path; `--json` outputs `{ path, content }`.
30
31
 
31
32
  ## Data Board Commands
32
33
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@imbrace/cli",
3
- "version": "0.3.0",
3
+ "version": "0.4.1",
4
4
  "type": "module",
5
5
  "description": "CLI tool for interacting with the Imbrace CRM platform from the terminal",
6
6
  "repository": {
@@ -24,7 +24,7 @@
24
24
  "prepack": "oclif manifest"
25
25
  },
26
26
  "dependencies": {
27
- "@imbrace/sdk": "1.0.2",
27
+ "@imbrace/sdk": "^1.0.4",
28
28
  "@inquirer/prompts": "^7.10.1",
29
29
  "@oclif/core": "^4.2.0",
30
30
  "@oclif/plugin-autocomplete": "^3.2.0",
package/dist/http.d.ts DELETED
@@ -1,9 +0,0 @@
1
- /**
2
- * HTTP client for the local Hono API server
3
- * Automatically attaches the Bearer token from config
4
- */
5
- export declare function apiRequest<T = any>(path: string, opts?: {
6
- method?: string;
7
- body?: any;
8
- }): Promise<T>;
9
- export declare function apiRequestText(path: string): Promise<string>;
package/dist/http.js DELETED
@@ -1,40 +0,0 @@
1
- import { getCredential, getApiUrl } from "./config.js";
2
- /**
3
- * HTTP client for the local Hono API server
4
- * Automatically attaches the Bearer token from config
5
- */
6
- export async function apiRequest(path, opts) {
7
- const credential = getCredential();
8
- const baseUrl = getApiUrl();
9
- const headers = {
10
- "Content-Type": "application/json",
11
- };
12
- if (credential) {
13
- headers["Authorization"] = `Bearer ${credential}`;
14
- }
15
- const res = await fetch(`${baseUrl}${path}`, {
16
- method: opts?.method || "GET",
17
- headers,
18
- body: opts?.body ? JSON.stringify(opts.body) : undefined,
19
- });
20
- const data = await res.json();
21
- if (!res.ok) {
22
- throw new Error(data?.message || `HTTP ${res.status}`);
23
- }
24
- return data;
25
- }
26
- export async function apiRequestText(path) {
27
- const credential = getCredential();
28
- const baseUrl = getApiUrl();
29
- const headers = {
30
- "Content-Type": "application/json",
31
- };
32
- if (credential) {
33
- headers["Authorization"] = `Bearer ${credential}`;
34
- }
35
- const res = await fetch(`${baseUrl}${path}`, { method: "GET", headers });
36
- if (!res.ok) {
37
- throw new Error(`HTTP ${res.status}`);
38
- }
39
- return res.text();
40
- }