@imbrace/cli 0.2.0 → 0.4.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 (71) hide show
  1. package/README.md +7 -0
  2. package/dist/base-command.js +20 -18
  3. package/dist/commands/ai-agent/create.js +8 -7
  4. package/dist/commands/ai-agent/delete.js +6 -4
  5. package/dist/commands/ai-agent/get.js +5 -5
  6. package/dist/commands/ai-agent/list-files.js +7 -5
  7. package/dist/commands/ai-agent/list-folders.js +7 -6
  8. package/dist/commands/ai-agent/list-models.js +5 -5
  9. package/dist/commands/ai-agent/list-providers.js +5 -5
  10. package/dist/commands/ai-agent/list.js +7 -5
  11. package/dist/commands/ai-agent/update.js +5 -4
  12. package/dist/commands/data-board/create-field.js +6 -4
  13. package/dist/commands/data-board/create-item.js +10 -8
  14. package/dist/commands/data-board/create.js +8 -6
  15. package/dist/commands/data-board/delete-item.js +6 -4
  16. package/dist/commands/data-board/export-csv.js +3 -2
  17. package/dist/commands/data-board/list-items.js +9 -11
  18. package/dist/commands/data-board/list.js +7 -5
  19. package/dist/commands/data-board/update-item.js +8 -6
  20. package/dist/commands/docs.d.ts +10 -0
  21. package/dist/commands/docs.js +39 -0
  22. package/dist/commands/login.d.ts +0 -1
  23. package/dist/commands/login.js +39 -55
  24. package/dist/commands/whoami.js +0 -2
  25. package/dist/commands/workflow/conn/create.js +33 -16
  26. package/dist/commands/workflow/conn/delete.js +6 -4
  27. package/dist/commands/workflow/conn/get.js +5 -4
  28. package/dist/commands/workflow/conn/list.js +7 -5
  29. package/dist/commands/workflow/create.js +16 -14
  30. package/dist/commands/workflow/delete.js +6 -4
  31. package/dist/commands/workflow/disable.js +9 -4
  32. package/dist/commands/workflow/enable.js +9 -4
  33. package/dist/commands/workflow/folder/create.js +11 -10
  34. package/dist/commands/workflow/folder/delete.js +6 -4
  35. package/dist/commands/workflow/folder/get.js +5 -4
  36. package/dist/commands/workflow/folder/list.js +7 -5
  37. package/dist/commands/workflow/folder/update.js +6 -4
  38. package/dist/commands/workflow/get.js +5 -4
  39. package/dist/commands/workflow/list.js +8 -6
  40. package/dist/commands/workflow/mcp/create.js +10 -9
  41. package/dist/commands/workflow/mcp/delete.js +6 -4
  42. package/dist/commands/workflow/mcp/get.js +5 -4
  43. package/dist/commands/workflow/mcp/list.js +9 -5
  44. package/dist/commands/workflow/mcp/rotate-token.js +7 -5
  45. package/dist/commands/workflow/move.js +10 -4
  46. package/dist/commands/workflow/node/add-raw.js +6 -4
  47. package/dist/commands/workflow/node/add.js +70 -21
  48. package/dist/commands/workflow/node/delete.js +12 -4
  49. package/dist/commands/workflow/node/list.js +8 -5
  50. package/dist/commands/workflow/node/update.js +44 -8
  51. package/dist/commands/workflow/piece/detail.js +5 -4
  52. package/dist/commands/workflow/piece/list.js +22 -6
  53. package/dist/commands/workflow/publish.js +9 -4
  54. package/dist/commands/workflow/run-detail.js +5 -4
  55. package/dist/commands/workflow/run.js +10 -7
  56. package/dist/commands/workflow/runs.js +7 -5
  57. package/dist/config.d.ts +5 -5
  58. package/dist/config.js +6 -12
  59. package/dist/lib/ai-agent.d.ts +40 -0
  60. package/dist/lib/ai-agent.js +150 -0
  61. package/dist/lib/client.d.ts +7 -0
  62. package/dist/lib/client.js +21 -0
  63. package/dist/lib/gateway.d.ts +3 -0
  64. package/dist/lib/gateway.js +31 -0
  65. package/dist/lib/workflow.d.ts +20 -0
  66. package/dist/lib/workflow.js +71 -0
  67. package/dist/select-board.js +4 -3
  68. package/llms.txt +626 -0
  69. package/package.json +4 -3
  70. package/dist/http.d.ts +0 -9
  71. package/dist/http.js +0 -40
@@ -0,0 +1,39 @@
1
+ import { Command, Flags } from "@oclif/core";
2
+ import { readFileSync, existsSync } from "node:fs";
3
+ import { fileURLToPath } from "node:url";
4
+ import { dirname, resolve } from "node:path";
5
+ export default class Docs extends Command {
6
+ static description = "Print the bundled llms.txt — a comprehensive command reference designed to be fed into a coding agent's context (Claude, Cursor, ...). Pipe to a file: `imbrace docs > llms.txt`.";
7
+ static examples = [
8
+ "imbrace docs # print full llms.txt to stdout",
9
+ "imbrace docs --path # print absolute path to bundled llms.txt",
10
+ "imbrace docs > /tmp/imbrace-llms.txt # save for an AI agent's context",
11
+ ];
12
+ static flags = {
13
+ path: Flags.boolean({ description: "Print only the absolute path to llms.txt (don't print contents)" }),
14
+ json: Flags.boolean({ description: "Output as JSON: { path, content }" }),
15
+ };
16
+ async run() {
17
+ const { flags } = await this.parse(Docs);
18
+ const here = dirname(fileURLToPath(import.meta.url));
19
+ const candidates = [
20
+ resolve(here, "../../llms.txt"),
21
+ resolve(here, "../llms.txt"),
22
+ resolve(here, "../../../llms.txt"),
23
+ ];
24
+ const llmsPath = candidates.find((p) => existsSync(p));
25
+ if (!llmsPath) {
26
+ this.error(`llms.txt not found. Looked in:\n${candidates.map((p) => ` - ${p}`).join("\n")}\n\nReinstall the package or fetch from https://github.com/imbraceltd/imbrace-cli/blob/main/llms.txt`);
27
+ }
28
+ if (flags.path && !flags.json) {
29
+ this.log(llmsPath);
30
+ return;
31
+ }
32
+ const content = readFileSync(llmsPath, "utf8");
33
+ if (flags.json) {
34
+ this.log(JSON.stringify({ path: llmsPath, content }, null, 2));
35
+ return;
36
+ }
37
+ this.log(content);
38
+ }
39
+ }
@@ -6,7 +6,6 @@ export default class Login extends Command {
6
6
  email: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
7
7
  password: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
8
8
  "api-key": import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
9
- "api-url": import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
10
9
  };
11
10
  run(): Promise<void>;
12
11
  }
@@ -1,71 +1,55 @@
1
1
  import { Command, Flags } from "@oclif/core";
2
- import { saveCredential, config } from "../config.js";
3
- import { apiRequest } from "../http.js";
2
+ import { ImbraceClient } from "@imbrace/sdk";
3
+ import { saveCredential } from "../config.js";
4
+ import { resetClient } from "../lib/client.js";
4
5
  export default class Login extends Command {
5
6
  static description = "Login to Imbrace platform";
6
7
  static examples = [
7
8
  "imbrace login --email user@example.com --password mypass",
8
- "imbrace login --api-key sk-xxx...",
9
+ "imbrace login --api-key api_xxx...",
9
10
  ];
10
11
  static flags = {
11
- email: Flags.string({
12
- char: "e",
13
- description: "Email address",
14
- }),
15
- password: Flags.string({
16
- char: "p",
17
- description: "Password",
18
- }),
19
- "api-key": Flags.string({
20
- char: "k",
21
- description: "API key (starts with sk-)",
22
- }),
23
- "api-url": Flags.string({
24
- description: "Custom API URL",
25
- default: "http://localhost:3456",
26
- }),
12
+ email: Flags.string({ char: "e", description: "Email address" }),
13
+ password: Flags.string({ char: "p", description: "Password" }),
14
+ "api-key": Flags.string({ char: "k", description: "API key (starts with api_ or sk-)" }),
27
15
  };
28
16
  async run() {
29
17
  const { flags } = await this.parse(Login);
30
- // Set API URL
31
- if (flags["api-url"]) {
32
- config.set("apiUrl", flags["api-url"]);
33
- }
34
- let body;
35
18
  if (flags["api-key"]) {
36
- // Method 1: API Key
37
- body = { apiKey: flags["api-key"] };
38
- this.log("🔑 Logging in with API key...");
19
+ this.log("🔑 Verifying API key...");
20
+ try {
21
+ const client = new ImbraceClient({ apiKey: flags["api-key"] });
22
+ // Lightweight verification — list boards rejects an invalid key.
23
+ await client.boards.list();
24
+ saveCredential({ credential: flags["api-key"], method: "api-key" });
25
+ resetClient();
26
+ this.log(`\n✅ Authenticated with API key\n Method: api-key\n`);
27
+ }
28
+ catch (error) {
29
+ this.error(`Invalid API key: ${error?.message}`);
30
+ }
31
+ return;
39
32
  }
40
- else if (flags.email && flags.password) {
41
- // Method 2: Email + Password
42
- body = { email: flags.email, password: flags.password };
33
+ if (flags.email && flags.password) {
43
34
  this.log(`📧 Logging in as ${flags.email}...`);
35
+ try {
36
+ const client = new ImbraceClient();
37
+ await client.login(flags.email, flags.password);
38
+ // Internal: read the access token the SDK just stored.
39
+ const token = client.tokenManager?.getToken();
40
+ if (!token)
41
+ this.error("Login succeeded but no token was issued");
42
+ saveCredential({ credential: token, method: "password", email: flags.email });
43
+ resetClient();
44
+ this.log(`\n✅ Logged in as ${flags.email}\n Method: password\n`);
45
+ }
46
+ catch (error) {
47
+ this.error(`Login failed: ${error?.message}`);
48
+ }
49
+ return;
44
50
  }
45
- else {
46
- this.error("Provide --email + --password, or --api-key\n" +
47
- " imbrace login --api-key sk-xxx...\n" +
48
- " imbrace login --email user@example.com --password mypass");
49
- }
50
- console.log("[login] POST /auth/login →", JSON.stringify(body));
51
- try {
52
- const res = await apiRequest("/auth/login", { method: "POST", body });
53
- console.log("[login] response →", JSON.stringify(res));
54
- saveCredential({
55
- credential: res.credential,
56
- method: res.method,
57
- email: res.email,
58
- });
59
- this.log(`\n✅ ${res.message}`);
60
- this.log(` Method: ${res.method}`);
61
- // this.log(` API URL: ${config.get("apiUrl")}`);
62
- // this.log(` Config: ${config.path}\n`);
63
- }
64
- catch (error) {
65
- console.log("[login] error →", error);
66
- this.error(`Login failed: ${error.message}`);
67
- }
51
+ this.error("Provide --email + --password, or --api-key\n" +
52
+ " imbrace login --api-key api_xxx...\n" +
53
+ " imbrace login --email user@example.com --password mypass");
68
54
  }
69
55
  }
70
- // imbrace login --api-key api_108f337f-a4a8-445e-8e24-9c6bf96fb72b
71
- // imbrace login --email user@example.com --password mypass
@@ -16,14 +16,12 @@ export default class Whoami extends Command {
16
16
  this.log(JSON.stringify({
17
17
  email: info.email || null,
18
18
  method: info.method,
19
- apiUrl: info.apiUrl,
20
19
  authenticated: true,
21
20
  }, null, 2));
22
21
  return;
23
22
  }
24
23
  this.log(`\n Email: ${info.email || "(api-key)"}`);
25
24
  this.log(` Method: ${info.method}`);
26
- this.log(` API URL: ${info.apiUrl}`);
27
25
  this.log(` Status: authenticated\n`);
28
26
  }
29
27
  }
@@ -1,6 +1,7 @@
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
+ import { normalizePieceName, resolveProjectId } from "../../../lib/workflow.js";
4
5
  export default class WorkflowConnCreate extends BaseCommand {
5
6
  static description = "Create a connection (save credential for an external service)";
6
7
  static examples = [
@@ -38,28 +39,44 @@ export default class WorkflowConnCreate extends BaseCommand {
38
39
  this.error(`--value must be valid JSON for type ${flags.type}: ${e.message}`);
39
40
  }
40
41
  }
41
- const body = {
42
- piece: flags.piece,
43
- type: flags.type,
44
- value,
45
- };
46
- if (flags["display-name"])
47
- body.displayName = flags["display-name"];
48
- if (flags["external-id"])
49
- body.externalId = flags["external-id"];
50
42
  try {
51
- const res = await apiRequest("/workflow/conn/create", { method: "POST", body });
43
+ const client = getClient();
44
+ const pieceName = normalizePieceName(flags.piece);
45
+ const projectId = await resolveProjectId(client);
46
+ const externalId = flags["external-id"] || `cli_${Date.now()}`;
47
+ // Activepieces requires `value.type` to match the connection type.
48
+ let apValue;
49
+ if (flags.type === "SECRET_TEXT" && typeof value === "string") {
50
+ apValue = { type: "SECRET_TEXT", secret_text: value };
51
+ }
52
+ else if (flags.type === "BASIC_AUTH" && typeof value === "object") {
53
+ apValue = { type: "BASIC_AUTH", username: value.username, password: value.password };
54
+ }
55
+ else {
56
+ apValue = typeof value === "object" && value.type
57
+ ? value
58
+ : { type: flags.type, ...(typeof value === "object" ? value : {}) };
59
+ }
60
+ const data = await client.workflows.upsertConnection({
61
+ pieceName,
62
+ projectId,
63
+ externalId,
64
+ displayName: flags["display-name"] || `${pieceName.split("/").pop()} (${externalId})`,
65
+ type: flags.type,
66
+ value: apValue,
67
+ });
68
+ const message = "Connection created";
52
69
  if (flags["id-only"]) {
53
- this.log(res.data?.id ?? "");
70
+ this.log(data?.id ?? "");
54
71
  return;
55
72
  }
56
73
  if (flags.json) {
57
- this.log(JSON.stringify(res, null, 2));
74
+ this.log(JSON.stringify({ ok: true, message, data }, null, 2));
58
75
  return;
59
76
  }
60
- this.log(`\n✅ ${res.message}`);
61
- if (res.data?.id)
62
- this.log(` ID: ${res.data.id}`);
77
+ this.log(`\n✅ ${message}`);
78
+ if (data?.id)
79
+ this.log(` ID: ${data.id}`);
63
80
  this.log("");
64
81
  }
65
82
  catch (error) {
@@ -1,7 +1,7 @@
1
1
  import { Args, Flags } from "@oclif/core";
2
2
  import { BaseCommand } from "../../../base-command.js";
3
3
  import { confirm } from "@inquirer/prompts";
4
- import { apiRequest } from "../../../http.js";
4
+ import { getClient } from "../../../lib/client.js";
5
5
  export default class WorkflowConnDelete extends BaseCommand {
6
6
  static description = "Delete a connection";
7
7
  static examples = [
@@ -25,12 +25,14 @@ export default class WorkflowConnDelete extends BaseCommand {
25
25
  }
26
26
  }
27
27
  try {
28
- const res = await apiRequest(`/workflow/conn/${args.connId}`, { method: "DELETE" });
28
+ const client = getClient();
29
+ await client.workflows.deleteConnection(args.connId);
30
+ const message = "Connection deleted";
29
31
  if (flags.json) {
30
- this.log(JSON.stringify(res, null, 2));
32
+ this.log(JSON.stringify({ ok: true, message }, null, 2));
31
33
  return;
32
34
  }
33
- this.log(`\n✅ ${res.message}\n`);
35
+ this.log(`\n✅ ${message}\n`);
34
36
  }
35
37
  catch (error) {
36
38
  this.error(`Failed: ${error.message}`);
@@ -1,7 +1,7 @@
1
1
  import { Args, Flags } from "@oclif/core";
2
2
  import { BaseCommand } from "../../../base-command.js";
3
3
  import { input } from "@inquirer/prompts";
4
- import { apiRequest } from "../../../http.js";
4
+ import { getClient } from "../../../lib/client.js";
5
5
  export default class WorkflowConnGet extends BaseCommand {
6
6
  static description = "Get details of a single connection (credential metadata, status, piece info)";
7
7
  static examples = [
@@ -18,12 +18,13 @@ export default class WorkflowConnGet extends BaseCommand {
18
18
  const { args, flags } = await this.parse(WorkflowConnGet);
19
19
  const connId = args.connId ?? (flags.json ? this.error("Connection ID is required") : await input({ message: "Connection ID:" }));
20
20
  try {
21
- const res = await apiRequest(`/workflow/conn/${connId}`);
21
+ const client = getClient();
22
+ const data = await client.workflows.getConnection(connId);
22
23
  if (flags.json) {
23
- this.log(JSON.stringify(res, null, 2));
24
+ this.log(JSON.stringify({ ok: true, data }, null, 2));
24
25
  return;
25
26
  }
26
- const c = res.data || {};
27
+ const c = data || {};
27
28
  this.log(`\n ID: ${c.id || ""}`);
28
29
  this.log(` Display name: ${c.displayName || ""}`);
29
30
  this.log(` External ID: ${c.externalId || ""}`);
@@ -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 WorkflowConnList extends BaseCommand {
5
5
  static description = "List all connections (saved credentials for external services)";
6
6
  static examples = [
@@ -13,15 +13,17 @@ export default class WorkflowConnList extends BaseCommand {
13
13
  async run() {
14
14
  const { flags } = await this.parse(WorkflowConnList);
15
15
  try {
16
- const res = await apiRequest("/workflow/conn/list");
16
+ const client = getClient();
17
+ const res = await client.workflows.listConnections();
18
+ const data = res?.data ?? [];
17
19
  if (flags.json) {
18
- this.log(JSON.stringify(res, null, 2));
20
+ this.log(JSON.stringify({ ok: true, count: data.length, data }, null, 2));
19
21
  return;
20
22
  }
21
- this.log(`\n Found ${res.count} connection(s):\n`);
23
+ this.log(`\n Found ${data.length} connection(s):\n`);
22
24
  this.log(" ID DISPLAY NAME PIECE TYPE");
23
25
  this.log(" ─────────────────────────────────────────────────────────────────────────────────────────────");
24
- for (const c of res.data || []) {
26
+ for (const c of data) {
25
27
  const id = (c.id || "").padEnd(31);
26
28
  const name = (c.displayName || "").padEnd(28);
27
29
  const piece = (c.pieceName || "").padEnd(28);
@@ -1,7 +1,8 @@
1
1
  import { Flags } from "@oclif/core";
2
2
  import { BaseCommand } from "../../base-command.js";
3
3
  import { input } from "@inquirer/prompts";
4
- import { apiRequest } from "../../http.js";
4
+ import { getClient } from "../../lib/client.js";
5
+ import { resolveProjectId } from "../../lib/workflow.js";
5
6
  export default class WorkflowCreate extends BaseCommand {
6
7
  static description = "Create a new workflow (empty — add nodes via UI builder or `workflow node add`)";
7
8
  static examples = [
@@ -20,26 +21,27 @@ export default class WorkflowCreate extends BaseCommand {
20
21
  const { flags } = await this.parse(WorkflowCreate);
21
22
  const nonInteractive = flags.json || flags["id-only"];
22
23
  const name = flags.name ?? (nonInteractive ? this.error("--name is required with --json or --id-only") : await input({ message: "Workflow name:" }));
23
- const body = { name };
24
- if (flags["project-id"])
25
- body.projectId = flags["project-id"];
26
- if (flags["folder-id"])
27
- body.folderId = flags["folder-id"];
28
24
  try {
29
- const res = await apiRequest("/workflow/create", { method: "POST", body });
25
+ const client = getClient();
26
+ const projectId = flags["project-id"] || (await resolveProjectId(client));
27
+ const createBody = { displayName: name, projectId };
28
+ if (flags["folder-id"])
29
+ createBody.folderId = flags["folder-id"];
30
+ const data = await client.workflows.createFlow(createBody);
31
+ const message = `Workflow "${name}" created`;
30
32
  if (flags["id-only"]) {
31
- this.log(res.data?.id ?? "");
33
+ this.log(data?.id ?? "");
32
34
  return;
33
35
  }
34
36
  if (flags.json) {
35
- this.log(JSON.stringify(res, null, 2));
37
+ this.log(JSON.stringify({ ok: true, message, data }, null, 2));
36
38
  return;
37
39
  }
38
- this.log(`\n✅ ${res.message}`);
39
- if (res.data?.id)
40
- this.log(` ID: ${res.data.id}`);
41
- if (res.data?.projectId)
42
- this.log(` Project: ${res.data.projectId}`);
40
+ this.log(`\n✅ ${message}`);
41
+ if (data?.id)
42
+ this.log(` ID: ${data.id}`);
43
+ if (data?.projectId)
44
+ this.log(` Project: ${data.projectId}`);
43
45
  this.log("");
44
46
  }
45
47
  catch (error) {
@@ -1,7 +1,7 @@
1
1
  import { Args, Flags } from "@oclif/core";
2
2
  import { BaseCommand } from "../../base-command.js";
3
3
  import { confirm, input } from "@inquirer/prompts";
4
- import { apiRequest } from "../../http.js";
4
+ import { getClient } from "../../lib/client.js";
5
5
  export default class WorkflowDelete extends BaseCommand {
6
6
  static description = "Delete a workflow";
7
7
  static examples = [
@@ -26,12 +26,14 @@ export default class WorkflowDelete extends BaseCommand {
26
26
  }
27
27
  }
28
28
  try {
29
- const res = await apiRequest(`/workflow/${id}`, { method: "DELETE" });
29
+ const client = getClient();
30
+ await client.workflows.deleteFlow(id);
31
+ const message = "Workflow deleted";
30
32
  if (flags.json) {
31
- this.log(JSON.stringify(res, null, 2));
33
+ this.log(JSON.stringify({ ok: true, message }, null, 2));
32
34
  return;
33
35
  }
34
- this.log(`\n✅ ${res.message}\n`);
36
+ this.log(`\n✅ ${message}\n`);
35
37
  }
36
38
  catch (error) {
37
39
  this.error(`Failed: ${error.message}`);
@@ -1,6 +1,6 @@
1
1
  import { Args, 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 WorkflowDisable extends BaseCommand {
5
5
  static description = "Stop auto-trigger on a workflow (keeps published version intact)";
6
6
  static examples = [
@@ -16,12 +16,17 @@ export default class WorkflowDisable extends BaseCommand {
16
16
  async run() {
17
17
  const { args, flags } = await this.parse(WorkflowDisable);
18
18
  try {
19
- const res = await apiRequest(`/workflow/${args.flowId}/disable`, { method: "POST", body: {} });
19
+ const client = getClient();
20
+ const data = await client.workflows.applyFlowOperation(args.flowId, {
21
+ type: "CHANGE_STATUS",
22
+ request: { status: "DISABLED" },
23
+ });
24
+ const message = "Workflow disabled";
20
25
  if (flags.json) {
21
- this.log(JSON.stringify(res, null, 2));
26
+ this.log(JSON.stringify({ ok: true, message, data }, null, 2));
22
27
  return;
23
28
  }
24
- this.log(`\n✅ ${res.message}\n`);
29
+ this.log(`\n✅ ${message}\n`);
25
30
  }
26
31
  catch (error) {
27
32
  this.error(`Failed: ${error.message}`);
@@ -1,6 +1,6 @@
1
1
  import { Args, 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 WorkflowEnable extends BaseCommand {
5
5
  static description = "Enable auto-trigger on a workflow. Requires `workflow publish` first.";
6
6
  static examples = [
@@ -16,12 +16,17 @@ export default class WorkflowEnable extends BaseCommand {
16
16
  async run() {
17
17
  const { args, flags } = await this.parse(WorkflowEnable);
18
18
  try {
19
- const res = await apiRequest(`/workflow/${args.flowId}/enable`, { method: "POST", body: {} });
19
+ const client = getClient();
20
+ const data = await client.workflows.applyFlowOperation(args.flowId, {
21
+ type: "CHANGE_STATUS",
22
+ request: { status: "ENABLED" },
23
+ });
24
+ const message = "Workflow enabled";
20
25
  if (flags.json) {
21
- this.log(JSON.stringify(res, null, 2));
26
+ this.log(JSON.stringify({ ok: true, message, data }, null, 2));
22
27
  return;
23
28
  }
24
- this.log(`\n✅ ${res.message}\n`);
29
+ this.log(`\n✅ ${message}\n`);
25
30
  }
26
31
  catch (error) {
27
32
  // Common error: trying to enable before publish
@@ -1,7 +1,8 @@
1
1
  import { Flags } from "@oclif/core";
2
2
  import { BaseCommand } from "../../../base-command.js";
3
3
  import { input } from "@inquirer/prompts";
4
- import { apiRequest } from "../../../http.js";
4
+ import { getClient } from "../../../lib/client.js";
5
+ import { resolveProjectId } from "../../../lib/workflow.js";
5
6
  export default class WorkflowFolderCreate extends BaseCommand {
6
7
  static description = "Create a new folder for organizing workflows";
7
8
  static examples = [
@@ -18,22 +19,22 @@ export default class WorkflowFolderCreate extends BaseCommand {
18
19
  const { flags } = await this.parse(WorkflowFolderCreate);
19
20
  const nonInteractive = flags.json || flags["id-only"];
20
21
  const name = flags.name ?? (nonInteractive ? this.error("--name is required with --json or --id-only") : await input({ message: "Folder name:" }));
21
- const body = { name };
22
- if (flags["project-id"])
23
- body.projectId = flags["project-id"];
24
22
  try {
25
- const res = await apiRequest("/workflow/folder/create", { method: "POST", body });
23
+ const client = getClient();
24
+ const projectId = flags["project-id"] || (await resolveProjectId(client));
25
+ const data = await client.workflows.createFolder({ displayName: name, projectId });
26
+ const message = `Folder "${name}" created`;
26
27
  if (flags["id-only"]) {
27
- this.log(res.data?.id ?? "");
28
+ this.log(data?.id ?? "");
28
29
  return;
29
30
  }
30
31
  if (flags.json) {
31
- this.log(JSON.stringify(res, null, 2));
32
+ this.log(JSON.stringify({ ok: true, message, data }, null, 2));
32
33
  return;
33
34
  }
34
- this.log(`\n✅ ${res.message}`);
35
- if (res.data?.id)
36
- this.log(` ID: ${res.data.id}`);
35
+ this.log(`\n✅ ${message}`);
36
+ if (data?.id)
37
+ this.log(` ID: ${data.id}`);
37
38
  this.log("");
38
39
  }
39
40
  catch (error) {
@@ -1,7 +1,7 @@
1
1
  import { Args, Flags } from "@oclif/core";
2
2
  import { BaseCommand } from "../../../base-command.js";
3
3
  import { confirm } from "@inquirer/prompts";
4
- import { apiRequest } from "../../../http.js";
4
+ import { getClient } from "../../../lib/client.js";
5
5
  export default class WorkflowFolderDelete extends BaseCommand {
6
6
  static description = "Delete a folder. Flows inside the folder are NOT deleted — they become unfiled.";
7
7
  static examples = [
@@ -25,12 +25,14 @@ export default class WorkflowFolderDelete extends BaseCommand {
25
25
  }
26
26
  }
27
27
  try {
28
- const res = await apiRequest(`/workflow/folder/${args.folderId}`, { method: "DELETE" });
28
+ const client = getClient();
29
+ await client.workflows.deleteFolder(args.folderId);
30
+ const message = "Folder deleted";
29
31
  if (flags.json) {
30
- this.log(JSON.stringify(res, null, 2));
32
+ this.log(JSON.stringify({ ok: true, message }, null, 2));
31
33
  return;
32
34
  }
33
- this.log(`\n✅ ${res.message}\n`);
35
+ this.log(`\n✅ ${message}\n`);
34
36
  }
35
37
  catch (error) {
36
38
  this.error(`Failed: ${error.message}`);
@@ -1,7 +1,7 @@
1
1
  import { Args, Flags } from "@oclif/core";
2
2
  import { BaseCommand } from "../../../base-command.js";
3
3
  import { input } from "@inquirer/prompts";
4
- import { apiRequest } from "../../../http.js";
4
+ import { getClient } from "../../../lib/client.js";
5
5
  export default class WorkflowFolderGet extends BaseCommand {
6
6
  static description = "Get details of a single folder";
7
7
  static examples = [
@@ -18,12 +18,13 @@ export default class WorkflowFolderGet extends BaseCommand {
18
18
  const { args, flags } = await this.parse(WorkflowFolderGet);
19
19
  const folderId = args.folderId ?? (flags.json ? this.error("Folder ID is required") : await input({ message: "Folder ID:" }));
20
20
  try {
21
- const res = await apiRequest(`/workflow/folder/${folderId}`);
21
+ const client = getClient();
22
+ const data = await client.workflows.getFolder(folderId);
22
23
  if (flags.json) {
23
- this.log(JSON.stringify(res, null, 2));
24
+ this.log(JSON.stringify({ ok: true, data }, null, 2));
24
25
  return;
25
26
  }
26
- const f = res.data || {};
27
+ const f = data || {};
27
28
  this.log(`\n ID: ${f.id || ""}`);
28
29
  this.log(` Name: ${f.displayName || ""}`);
29
30
  this.log(` Project ID: ${f.projectId || ""}`);
@@ -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 WorkflowFolderList extends BaseCommand {
5
5
  static description = "List all folders (used to organize workflows)";
6
6
  static examples = [
@@ -13,15 +13,17 @@ export default class WorkflowFolderList extends BaseCommand {
13
13
  async run() {
14
14
  const { flags } = await this.parse(WorkflowFolderList);
15
15
  try {
16
- const res = await apiRequest("/workflow/folder/list");
16
+ const client = getClient();
17
+ const res = await client.workflows.listFolders();
18
+ const data = res?.data ?? [];
17
19
  if (flags.json) {
18
- this.log(JSON.stringify(res, null, 2));
20
+ this.log(JSON.stringify({ ok: true, count: data.length, data }, null, 2));
19
21
  return;
20
22
  }
21
- this.log(`\n Found ${res.count} folder(s):\n`);
23
+ this.log(`\n Found ${data.length} folder(s):\n`);
22
24
  this.log(" ID NAME");
23
25
  this.log(" ─────────────────────────────────────────────────────");
24
- for (const f of res.data || []) {
26
+ for (const f of data) {
25
27
  const id = (f.id || "").padEnd(24);
26
28
  const name = f.displayName || "";
27
29
  this.log(` ${id} ${name}`);
@@ -1,6 +1,6 @@
1
1
  import { Args, 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 WorkflowFolderUpdate extends BaseCommand {
5
5
  static description = "Rename a folder";
6
6
  static examples = [
@@ -16,12 +16,14 @@ export default class WorkflowFolderUpdate extends BaseCommand {
16
16
  async run() {
17
17
  const { args, flags } = await this.parse(WorkflowFolderUpdate);
18
18
  try {
19
- const res = await apiRequest(`/workflow/folder/${args.folderId}`, { method: "PUT", body: { name: flags.name } });
19
+ const client = getClient();
20
+ const data = await client.workflows.updateFolder(args.folderId, { displayName: flags.name });
21
+ const message = "Folder renamed";
20
22
  if (flags.json) {
21
- this.log(JSON.stringify(res, null, 2));
23
+ this.log(JSON.stringify({ ok: true, message, data }, null, 2));
22
24
  return;
23
25
  }
24
- this.log(`\n✅ ${res.message}\n`);
26
+ this.log(`\n✅ ${message}\n`);
25
27
  }
26
28
  catch (error) {
27
29
  this.error(`Failed: ${error.message}`);