@oxagen/cli 0.2.3 → 0.3.3

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 (72) hide show
  1. package/README.md +447 -0
  2. package/dist/commands/__tests__/cli-parity.test.js +2 -2
  3. package/dist/commands/__tests__/cli-parity.test.js.map +1 -1
  4. package/dist/commands/agent.plan.create.d.ts +3 -0
  5. package/dist/commands/agent.plan.create.d.ts.map +1 -0
  6. package/dist/commands/agent.plan.create.js +41 -0
  7. package/dist/commands/agent.plan.create.js.map +1 -0
  8. package/dist/commands/api-key.create.js +3 -2
  9. package/dist/commands/api-key.create.js.map +1 -1
  10. package/dist/commands/api-key.revoke.js +3 -2
  11. package/dist/commands/api-key.revoke.js.map +1 -1
  12. package/dist/commands/auth.login.js +2 -1
  13. package/dist/commands/auth.login.js.map +1 -1
  14. package/dist/commands/auth.whoami.js +3 -2
  15. package/dist/commands/auth.whoami.js.map +1 -1
  16. package/dist/commands/billing.status.js +3 -2
  17. package/dist/commands/billing.status.js.map +1 -1
  18. package/dist/commands/chat.send.js +3 -2
  19. package/dist/commands/chat.send.js.map +1 -1
  20. package/dist/commands/conversation.archive.js +3 -2
  21. package/dist/commands/conversation.archive.js.map +1 -1
  22. package/dist/commands/conversation.delete.js +3 -2
  23. package/dist/commands/conversation.delete.js.map +1 -1
  24. package/dist/commands/conversation.list.js +3 -2
  25. package/dist/commands/conversation.list.js.map +1 -1
  26. package/dist/commands/conversation.rename.js +3 -2
  27. package/dist/commands/conversation.rename.js.map +1 -1
  28. package/dist/commands/documents.generate.js +1 -1
  29. package/dist/commands/documents.generate.js.map +1 -1
  30. package/dist/commands/notifications.list.js +3 -2
  31. package/dist/commands/notifications.list.js.map +1 -1
  32. package/dist/commands/notifications.mark.js +3 -2
  33. package/dist/commands/notifications.mark.js.map +1 -1
  34. package/dist/commands/org.create.js +3 -2
  35. package/dist/commands/org.create.js.map +1 -1
  36. package/dist/commands/org.list.js +3 -2
  37. package/dist/commands/org.list.js.map +1 -1
  38. package/dist/commands/org.member.add.js +3 -2
  39. package/dist/commands/org.member.add.js.map +1 -1
  40. package/dist/commands/org.member.remove.js +3 -2
  41. package/dist/commands/org.member.remove.js.map +1 -1
  42. package/dist/commands/plugin.catalog.browse.js +1 -1
  43. package/dist/commands/plugin.catalog.browse.js.map +1 -1
  44. package/dist/commands/plugin.install.js +3 -2
  45. package/dist/commands/plugin.install.js.map +1 -1
  46. package/dist/commands/plugin.list.js +3 -2
  47. package/dist/commands/plugin.list.js.map +1 -1
  48. package/dist/commands/plugin.registry.list.js +1 -1
  49. package/dist/commands/plugin.registry.list.js.map +1 -1
  50. package/dist/commands/plugin.uninstall.js +3 -2
  51. package/dist/commands/plugin.uninstall.js.map +1 -1
  52. package/dist/commands/privacy.erase.d.ts +3 -0
  53. package/dist/commands/privacy.erase.d.ts.map +1 -0
  54. package/dist/commands/privacy.erase.js +60 -0
  55. package/dist/commands/privacy.erase.js.map +1 -0
  56. package/dist/commands/privacy.export.d.ts +3 -0
  57. package/dist/commands/privacy.export.d.ts.map +1 -0
  58. package/dist/commands/privacy.export.js +36 -0
  59. package/dist/commands/privacy.export.js.map +1 -0
  60. package/dist/commands/workspace.create.js +3 -2
  61. package/dist/commands/workspace.create.js.map +1 -1
  62. package/dist/commands/workspace.list.js +3 -2
  63. package/dist/commands/workspace.list.js.map +1 -1
  64. package/dist/commands/workspace.member.list.d.ts.map +1 -1
  65. package/dist/commands/workspace.member.list.js +2 -1
  66. package/dist/commands/workspace.member.list.js.map +1 -1
  67. package/dist/commands.test.js +472 -0
  68. package/dist/commands.test.js.map +1 -1
  69. package/dist/index.js +10 -1
  70. package/dist/index.js.map +1 -1
  71. package/package.json +12 -12
  72. package/LICENSE +0 -3
@@ -1 +1 @@
1
- {"version":3,"file":"workspace.list.js","sourceRoot":"","sources":["../../src/commands/workspace.list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAa/D,MAAM,CAAC,MAAM,oBAAoB,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC;KACpD,WAAW,CAAC,yCAAyC,CAAC;KACtD,MAAM,CAAC,cAAc,EAAE,mBAAmB,CAAC;KAC3C,MAAM,CAAC,KAAK,EAAE,OAAyB,EAAE,EAAE;IAC1C,WAAW,EAAE,CAAC;IACd,IAAI,CAAC;QACH,MAAM,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACpD,MAAM,IAAI,GAAG,MAAM,UAAU,CAAqB,cAAc,EAAE,EAAE,CAAC,CAAC;QACtE,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;QACtD,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC5B,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;YACpC,OAAO;QACT,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;QAC3B,KAAK,MAAM,EAAE,IAAI,UAAU,EAAE,CAAC;YAC5B,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,EAAE,IAAI,SAAS,KAAK,EAAE,CAAC,IAAI,IAAI,EAAE,GAAG,CAAC,CAAC;QACzE,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,UAAU,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACvC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"workspace.list.js","sourceRoot":"","sources":["../../src/commands/workspace.list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAazE,MAAM,CAAC,MAAM,oBAAoB,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC;KACpD,WAAW,CAAC,yCAAyC,CAAC;KACtD,MAAM,CAAC,cAAc,EAAE,mBAAmB,CAAC;KAC3C,MAAM,CAAC,KAAK,EAAE,OAAyB,EAAE,EAAE;IAC1C,WAAW,EAAE,CAAC;IACd,IAAI,CAAC;QACH,MAAM,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACpD,MAAM,IAAI,GAAG,MAAM,UAAU,CAAqB,cAAc,EAAE,EAAE,CAAC,CAAC;QACtE,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;QACtD,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC5B,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;YACpC,OAAO;QACT,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;QAC3B,KAAK,MAAM,EAAE,IAAI,UAAU,EAAE,CAAC;YAC5B,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,EAAE,IAAI,SAAS,KAAK,EAAE,CAAC,IAAI,IAAI,EAAE,GAAG,CAAC,CAAC;QACzE,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,GAAG,GAAG,YAAY,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAAC,OAAO,CAAC,KAAK,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC;QAClG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"workspace.member.list.d.ts","sourceRoot":"","sources":["../../src/commands/workspace.member.list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUpC,eAAO,MAAM,0BAA0B,SAuBnC,CAAC"}
1
+ {"version":3,"file":"workspace.member.list.d.ts","sourceRoot":"","sources":["../../src/commands/workspace.member.list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUpC,eAAO,MAAM,0BAA0B,SAwBnC,CAAC"}
@@ -13,7 +13,8 @@ export const workspaceMemberListCommand = new Command("list")
13
13
  }
14
14
  console.log(`✓ ${data.length} member(s)`);
15
15
  for (const m of data) {
16
- console.log(` ${m.email} role=${m.role} joined=${m.joined_at} id=${m.id}`);
16
+ const emailPart = process.stdout.isTTY ? `${m.email} ` : "";
17
+ console.log(` ${emailPart}role=${m.role} joined=${m.joined_at} id=${m.id}`);
17
18
  }
18
19
  }
19
20
  catch (err) {
@@ -1 +1 @@
1
- {"version":3,"file":"workspace.member.list.js","sourceRoot":"","sources":["../../src/commands/workspace.member.list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAS5D,MAAM,CAAC,MAAM,0BAA0B,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC;KAC1D,WAAW,CAAC,6BAA6B,CAAC;KAC1C,MAAM,CAAC,sBAAsB,EAAE,8CAA8C,CAAC;KAC9E,MAAM,CAAC,KAAK,EAAE,OAA+B,EAAE,EAAE;IAChD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,iBAAiB,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7E,MAAM,IAAI,GAAG,MAAM,UAAU,CAC3B,yBAAyB,MAAM,EAAE,EACjC,EAAE,MAAM,EAAE,KAAK,EAAE,CAClB,CAAC;QACF,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;YACjC,OAAO;QACT,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,MAAM,YAAY,CAAC,CAAC;QAC1C,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;YACrB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,KAAK,UAAU,CAAC,CAAC,IAAI,YAAY,CAAC,CAAC,SAAS,QAAQ,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACjF,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,GAAG,GAAG,GAAG,YAAY,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAChE,OAAO,CAAC,KAAK,CAAC,UAAU,GAAG,EAAE,CAAC,CAAC;QAC/B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"workspace.member.list.js","sourceRoot":"","sources":["../../src/commands/workspace.member.list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAS5D,MAAM,CAAC,MAAM,0BAA0B,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC;KAC1D,WAAW,CAAC,6BAA6B,CAAC;KAC1C,MAAM,CAAC,sBAAsB,EAAE,8CAA8C,CAAC;KAC9E,MAAM,CAAC,KAAK,EAAE,OAA+B,EAAE,EAAE;IAChD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,iBAAiB,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7E,MAAM,IAAI,GAAG,MAAM,UAAU,CAC3B,yBAAyB,MAAM,EAAE,EACjC,EAAE,MAAM,EAAE,KAAK,EAAE,CAClB,CAAC;QACF,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;YACjC,OAAO;QACT,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,MAAM,YAAY,CAAC,CAAC;QAC1C,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;YACrB,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;YAC7D,OAAO,CAAC,GAAG,CAAC,KAAK,SAAS,QAAQ,CAAC,CAAC,IAAI,YAAY,CAAC,CAAC,SAAS,QAAQ,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACjF,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,GAAG,GAAG,GAAG,YAAY,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAChE,OAAO,CAAC,KAAK,CAAC,UAAU,GAAG,EAAE,CAAC,CAAC;QAC/B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC"}
@@ -103,6 +103,14 @@ import { pluginOrgInstallBulkCommand } from "./commands/plugin.org.install_bulk.
103
103
  import { pluginOrgListCommand } from "./commands/plugin.org.list.js";
104
104
  import { pluginOrgSetEnabledCommand } from "./commands/plugin.org.set_enabled.js";
105
105
  import { pluginRegistryRemoveCommand } from "./commands/plugin.registry.remove.js";
106
+ import { pluginRegistrySyncCommand } from "./commands/plugin.registry.sync.js";
107
+ import { pluginSettingsSetAuthAlertsCommand } from "./commands/plugin.settings.set_auth_alerts.js";
108
+ import { pluginWorkspaceSetEnabledCommand } from "./commands/plugin.workspace.set_enabled.js";
109
+ import { systemInstallInstructionsCommand } from "./commands/system.install.instructions.js";
110
+ import { userPreferencesReadCommand } from "./commands/user.preferences.read.js";
111
+ import { userPreferencesWriteCommand } from "./commands/user.preferences.write.js";
112
+ import { workflowCancelCommand } from "./commands/workflow.cancel.js";
113
+ import { workflowStatusCommand } from "./commands/workflow.status.js";
106
114
  import * as apiClient from "./lib/api-client.js";
107
115
  import * as config from "./lib/config.js";
108
116
  const mockApiRequest = vi.mocked(apiClient.apiRequest);
@@ -110,6 +118,11 @@ const mockRequireAuth = vi.mocked(apiClient.requireAuth);
110
118
  const mockWriteConfig = vi.mocked(config.writeConfig);
111
119
  const mockClearConfig = vi.mocked(config.clearConfig);
112
120
  const mockGetToken = vi.mocked(config.getToken);
121
+ // Helper: throw an ApiError through apiRequest mock (covers instanceof branch in catch blocks)
122
+ function mockApiError(status, message) {
123
+ const ApiErrorClass = apiClient.ApiError;
124
+ mockApiRequest.mockRejectedValueOnce(new ApiErrorClass(status, message));
125
+ }
113
126
  beforeEach(() => {
114
127
  vi.clearAllMocks();
115
128
  mockRequireAuth.mockImplementation(() => { });
@@ -1746,4 +1759,463 @@ describe("plugin registry remove", () => {
1746
1759
  exitSpy.mockRestore();
1747
1760
  });
1748
1761
  });
1762
+ // ---------------------------------------------------------------------------
1763
+ // plugin registry sync
1764
+ // ---------------------------------------------------------------------------
1765
+ describe("plugin registry sync", () => {
1766
+ it("triggers a registry sync", async () => {
1767
+ const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
1768
+ mockApiRequest.mockResolvedValueOnce({ accepted: true });
1769
+ await pluginRegistrySyncCommand.parseAsync(["node", "cli", "-r", "reg1"]);
1770
+ expect(mockApiRequest).toHaveBeenCalledWith("/plugin/registry/sync", expect.objectContaining({ method: "POST" }));
1771
+ expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("Sync accepted"));
1772
+ consoleSpy.mockRestore();
1773
+ });
1774
+ it("reports sync not accepted", async () => {
1775
+ const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
1776
+ mockApiRequest.mockResolvedValueOnce({ accepted: false });
1777
+ await pluginRegistrySyncCommand.parseAsync(["node", "cli", "-r", "reg1"]);
1778
+ expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("not accepted"));
1779
+ consoleSpy.mockRestore();
1780
+ });
1781
+ it("handles sync failure", async () => {
1782
+ const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
1783
+ const exitSpy = vi.spyOn(process, "exit").mockImplementation((_code) => { throw new Error("process.exit"); });
1784
+ mockApiRequest.mockRejectedValueOnce(new Error("Registry not found"));
1785
+ await expect(pluginRegistrySyncCommand.parseAsync(["node", "cli", "-r", "reg1"])).rejects.toThrow();
1786
+ expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("Error:"));
1787
+ consoleSpy.mockRestore();
1788
+ exitSpy.mockRestore();
1789
+ });
1790
+ });
1791
+ // ---------------------------------------------------------------------------
1792
+ // plugin settings set_auth_alerts
1793
+ // ---------------------------------------------------------------------------
1794
+ describe("plugin settings set_auth_alerts", () => {
1795
+ it("updates auth alert settings", async () => {
1796
+ const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
1797
+ mockApiRequest.mockResolvedValueOnce({ ok: true });
1798
+ await pluginSettingsSetAuthAlertsCommand.parseAsync(["node", "cli", "--roles", "Owner,Admin"]);
1799
+ expect(mockApiRequest).toHaveBeenCalledWith("/plugin/settings/set_auth_alerts", expect.objectContaining({ method: "POST" }));
1800
+ expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("updated"));
1801
+ consoleSpy.mockRestore();
1802
+ });
1803
+ it("reports update failed when ok=false", async () => {
1804
+ const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
1805
+ mockApiRequest.mockResolvedValueOnce({ ok: false });
1806
+ await pluginSettingsSetAuthAlertsCommand.parseAsync(["node", "cli", "--roles", "Owner"]);
1807
+ expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("Update failed"));
1808
+ consoleSpy.mockRestore();
1809
+ });
1810
+ it("handles failure", async () => {
1811
+ const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
1812
+ const exitSpy = vi.spyOn(process, "exit").mockImplementation((_code) => { throw new Error("process.exit"); });
1813
+ mockApiRequest.mockRejectedValueOnce(new Error("Permission denied"));
1814
+ await expect(pluginSettingsSetAuthAlertsCommand.parseAsync(["node", "cli", "--roles", "Owner"])).rejects.toThrow();
1815
+ consoleSpy.mockRestore();
1816
+ exitSpy.mockRestore();
1817
+ });
1818
+ });
1819
+ // ---------------------------------------------------------------------------
1820
+ // plugin workspace set_enabled
1821
+ // ---------------------------------------------------------------------------
1822
+ describe("plugin workspace set_enabled", () => {
1823
+ it("enables a plugin for workspace", async () => {
1824
+ const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
1825
+ mockApiRequest.mockResolvedValueOnce({ workspaceServerId: "wsrv1" });
1826
+ await pluginWorkspaceSetEnabledCommand.parseAsync(["node", "cli", "-l", "listing1", "--enabled", "true"]);
1827
+ expect(mockApiRequest).toHaveBeenCalledWith("/plugin/workspace/set_enabled", expect.objectContaining({ method: "POST" }));
1828
+ expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("enabled"));
1829
+ consoleSpy.mockRestore();
1830
+ });
1831
+ it("disables a plugin for workspace (no server ID)", async () => {
1832
+ const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
1833
+ mockApiRequest.mockResolvedValueOnce({ workspaceServerId: null });
1834
+ await pluginWorkspaceSetEnabledCommand.parseAsync(["node", "cli", "-l", "listing1", "--enabled", "false"]);
1835
+ expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("disabled"));
1836
+ consoleSpy.mockRestore();
1837
+ });
1838
+ it("handles failure", async () => {
1839
+ const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
1840
+ const exitSpy = vi.spyOn(process, "exit").mockImplementation((_code) => { throw new Error("process.exit"); });
1841
+ mockApiRequest.mockRejectedValueOnce(new Error("Listing not found"));
1842
+ await expect(pluginWorkspaceSetEnabledCommand.parseAsync(["node", "cli", "-l", "l1", "--enabled", "true"])).rejects.toThrow();
1843
+ consoleSpy.mockRestore();
1844
+ exitSpy.mockRestore();
1845
+ });
1846
+ });
1847
+ // ---------------------------------------------------------------------------
1848
+ // system install instructions
1849
+ // ---------------------------------------------------------------------------
1850
+ describe("system install instructions", () => {
1851
+ it("shows installation steps", async () => {
1852
+ const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
1853
+ mockApiRequest.mockResolvedValueOnce({
1854
+ client: "claude-code",
1855
+ steps: [
1856
+ { label: "Install the CLI", command: "npm install -g @oxagen/cli" },
1857
+ { label: "Authenticate", command: "oxagen auth login" },
1858
+ ],
1859
+ });
1860
+ await systemInstallInstructionsCommand.parseAsync(["node", "cli", "-c", "claude-code"]);
1861
+ expect(mockApiRequest).toHaveBeenCalled();
1862
+ expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("claude-code"));
1863
+ consoleSpy.mockRestore();
1864
+ });
1865
+ it("handles fetch failure", async () => {
1866
+ const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
1867
+ const exitSpy = vi.spyOn(process, "exit").mockImplementation((_code) => { throw new Error("process.exit"); });
1868
+ mockApiRequest.mockRejectedValueOnce(new Error("Unknown client"));
1869
+ await expect(systemInstallInstructionsCommand.parseAsync(["node", "cli", "-c", "unknown"])).rejects.toThrow();
1870
+ consoleSpy.mockRestore();
1871
+ exitSpy.mockRestore();
1872
+ });
1873
+ });
1874
+ // ---------------------------------------------------------------------------
1875
+ // user preferences read/write
1876
+ // ---------------------------------------------------------------------------
1877
+ describe("user preferences read", () => {
1878
+ it("reads user preferences", async () => {
1879
+ const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
1880
+ mockApiRequest.mockResolvedValueOnce({
1881
+ fontSize: "medium",
1882
+ density: "comfortable",
1883
+ enterToSubmit: true,
1884
+ pendingPromptBehavior: "queue",
1885
+ defaultTextTier: "balanced",
1886
+ defaultTextModel: "claude-haiku-4-5",
1887
+ defaultImageModel: null,
1888
+ defaultVideoModel: null,
1889
+ });
1890
+ await userPreferencesReadCommand.parseAsync(["node", "cli"]);
1891
+ expect(mockApiRequest).toHaveBeenCalledWith("/user/preferences/read", expect.objectContaining({ method: "GET" }));
1892
+ expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("preferences"));
1893
+ consoleSpy.mockRestore();
1894
+ });
1895
+ it("shows optional fields when set", async () => {
1896
+ const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
1897
+ mockApiRequest.mockResolvedValueOnce({
1898
+ fontSize: "large",
1899
+ density: "spacious",
1900
+ enterToSubmit: false,
1901
+ pendingPromptBehavior: "interrupt",
1902
+ defaultTextTier: "precise",
1903
+ defaultTextModel: "claude-sonnet-4-6",
1904
+ defaultImageModel: "gpt-image-1",
1905
+ defaultVideoModel: "veo-3.0",
1906
+ });
1907
+ await userPreferencesReadCommand.parseAsync(["node", "cli"]);
1908
+ expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("gpt-image-1"));
1909
+ consoleSpy.mockRestore();
1910
+ });
1911
+ it("handles read failure", async () => {
1912
+ const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
1913
+ const exitSpy = vi.spyOn(process, "exit").mockImplementation((_code) => { throw new Error("process.exit"); });
1914
+ mockApiRequest.mockRejectedValueOnce(new Error("Unauthorized"));
1915
+ await expect(userPreferencesReadCommand.parseAsync(["node", "cli"])).rejects.toThrow();
1916
+ consoleSpy.mockRestore();
1917
+ exitSpy.mockRestore();
1918
+ });
1919
+ });
1920
+ describe("user preferences write", () => {
1921
+ it("updates user preferences", async () => {
1922
+ const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
1923
+ mockApiRequest.mockResolvedValueOnce({
1924
+ fontSize: "large",
1925
+ density: "comfortable",
1926
+ enterToSubmit: true,
1927
+ pendingPromptBehavior: "queue",
1928
+ defaultTextTier: null,
1929
+ defaultTextModel: null,
1930
+ defaultImageModel: null,
1931
+ defaultVideoModel: null,
1932
+ });
1933
+ await userPreferencesWriteCommand.parseAsync(["node", "cli", "--font-size", "large"]);
1934
+ expect(mockApiRequest).toHaveBeenCalledWith("/user/preferences/write", expect.objectContaining({ method: "POST" }));
1935
+ expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("updated"));
1936
+ consoleSpy.mockRestore();
1937
+ });
1938
+ it("handles write failure", async () => {
1939
+ const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
1940
+ const exitSpy = vi.spyOn(process, "exit").mockImplementation((_code) => { throw new Error("process.exit"); });
1941
+ mockApiRequest.mockRejectedValueOnce(new Error("Validation failed"));
1942
+ await expect(userPreferencesWriteCommand.parseAsync(["node", "cli", "--density", "bad"])).rejects.toThrow();
1943
+ consoleSpy.mockRestore();
1944
+ exitSpy.mockRestore();
1945
+ });
1946
+ });
1947
+ // ---------------------------------------------------------------------------
1948
+ // workflow cancel / status
1949
+ // ---------------------------------------------------------------------------
1950
+ describe("workflow cancel", () => {
1951
+ it("cancels a workflow", async () => {
1952
+ const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
1953
+ mockApiRequest.mockResolvedValueOnce({ cancelled: true });
1954
+ await workflowCancelCommand.parseAsync(["node", "cli", "-w", "wfr_abc"]);
1955
+ expect(mockApiRequest).toHaveBeenCalledWith("/workflow/cancel", expect.objectContaining({ method: "POST" }));
1956
+ expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("cancelled"));
1957
+ consoleSpy.mockRestore();
1958
+ });
1959
+ it("reports workflow could not be cancelled", async () => {
1960
+ const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
1961
+ mockApiRequest.mockResolvedValueOnce({ cancelled: false });
1962
+ await workflowCancelCommand.parseAsync(["node", "cli", "-w", "wfr_abc"]);
1963
+ expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("could not be cancelled"));
1964
+ consoleSpy.mockRestore();
1965
+ });
1966
+ it("handles cancel failure", async () => {
1967
+ const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
1968
+ const exitSpy = vi.spyOn(process, "exit").mockImplementation((_code) => { throw new Error("process.exit"); });
1969
+ mockApiRequest.mockRejectedValueOnce(new Error("Not found"));
1970
+ await expect(workflowCancelCommand.parseAsync(["node", "cli", "-w", "wfr_abc"])).rejects.toThrow();
1971
+ consoleSpy.mockRestore();
1972
+ exitSpy.mockRestore();
1973
+ });
1974
+ });
1975
+ describe("workflow status", () => {
1976
+ it("shows workflow status and tasks", async () => {
1977
+ const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
1978
+ mockApiRequest.mockResolvedValueOnce({
1979
+ workflow: { id: "wf1", publicId: "wfr_abc", title: "Research task", status: "running", totalTasks: 5, completedTasks: 3, failedTasks: 0 },
1980
+ tasks: [
1981
+ { id: "t1", title: "Gather data", status: "completed" },
1982
+ { id: "t2", title: "Analyze data", status: "running" },
1983
+ ],
1984
+ });
1985
+ await workflowStatusCommand.parseAsync(["node", "cli", "-w", "wfr_abc"]);
1986
+ expect(mockApiRequest).toHaveBeenCalled();
1987
+ expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("running"));
1988
+ consoleSpy.mockRestore();
1989
+ });
1990
+ it("handles status fetch failure", async () => {
1991
+ const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
1992
+ const exitSpy = vi.spyOn(process, "exit").mockImplementation((_code) => { throw new Error("process.exit"); });
1993
+ mockApiRequest.mockRejectedValueOnce(new Error("Workflow not found"));
1994
+ await expect(workflowStatusCommand.parseAsync(["node", "cli", "-w", "wfr_xyz"])).rejects.toThrow();
1995
+ consoleSpy.mockRestore();
1996
+ exitSpy.mockRestore();
1997
+ });
1998
+ });
1999
+ // ---------------------------------------------------------------------------
2000
+ // Branch coverage: ApiError paths and edge cases
2001
+ // These tests exercise the `err instanceof ApiError ? ... : String(err)` branch
2002
+ // in catch blocks (currently always false), plus empty/optional data branches.
2003
+ // ---------------------------------------------------------------------------
2004
+ describe("branch coverage: ApiError error paths", () => {
2005
+ it("automation list returns ApiError message", async () => {
2006
+ const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
2007
+ const exitSpy = vi.spyOn(process, "exit").mockImplementation((_code) => { throw new Error("exit"); });
2008
+ mockApiError(403, "Forbidden");
2009
+ await expect(automationListCommand.parseAsync(["node", "cli"])).rejects.toThrow();
2010
+ expect(consoleSpy).toHaveBeenCalledWith("Error: Forbidden");
2011
+ consoleSpy.mockRestore();
2012
+ exitSpy.mockRestore();
2013
+ });
2014
+ it("automation create returns ApiError message", async () => {
2015
+ const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
2016
+ const exitSpy = vi.spyOn(process, "exit").mockImplementation((_code) => { throw new Error("exit"); });
2017
+ mockApiError(400, "Name required");
2018
+ await expect(automationCreateCommand.parseAsync(["node", "cli", "-n", "A"])).rejects.toThrow();
2019
+ expect(consoleSpy).toHaveBeenCalledWith("Error: Name required");
2020
+ consoleSpy.mockRestore();
2021
+ exitSpy.mockRestore();
2022
+ });
2023
+ it("automation trigger returns ApiError message", async () => {
2024
+ const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
2025
+ const exitSpy = vi.spyOn(process, "exit").mockImplementation((_code) => { throw new Error("exit"); });
2026
+ mockApiError(404, "Automation not found");
2027
+ await expect(automationTriggerCommand.parseAsync(["node", "cli", "-a", "a1"])).rejects.toThrow();
2028
+ expect(consoleSpy).toHaveBeenCalledWith("Error: Automation not found");
2029
+ consoleSpy.mockRestore();
2030
+ exitSpy.mockRestore();
2031
+ });
2032
+ it("billing credits purchase returns ApiError message", async () => {
2033
+ const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
2034
+ const exitSpy = vi.spyOn(process, "exit").mockImplementation((_code) => { throw new Error("exit"); });
2035
+ mockApiError(402, "Payment failed");
2036
+ await expect(billingCreditsPurchaseCommand.parseAsync(["node", "cli", "-a", "10"])).rejects.toThrow();
2037
+ expect(consoleSpy).toHaveBeenCalledWith("Error: Payment failed");
2038
+ consoleSpy.mockRestore();
2039
+ exitSpy.mockRestore();
2040
+ });
2041
+ it("billing subscription read returns ApiError message", async () => {
2042
+ const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
2043
+ const exitSpy = vi.spyOn(process, "exit").mockImplementation((_code) => { throw new Error("exit"); });
2044
+ mockApiError(404, "Subscription not found");
2045
+ await expect(billingSubscriptionReadCommand.parseAsync(["node", "cli"])).rejects.toThrow();
2046
+ expect(consoleSpy).toHaveBeenCalledWith("Error: Subscription not found");
2047
+ consoleSpy.mockRestore();
2048
+ exitSpy.mockRestore();
2049
+ });
2050
+ it("document list returns ApiError message", async () => {
2051
+ const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
2052
+ const exitSpy = vi.spyOn(process, "exit").mockImplementation((_code) => { throw new Error("exit"); });
2053
+ mockApiError(403, "Access denied");
2054
+ await expect(documentListCommand.parseAsync(["node", "cli"])).rejects.toThrow();
2055
+ expect(consoleSpy).toHaveBeenCalledWith("Error: Access denied");
2056
+ consoleSpy.mockRestore();
2057
+ exitSpy.mockRestore();
2058
+ });
2059
+ it("workspace member list returns ApiError message", async () => {
2060
+ const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
2061
+ const exitSpy = vi.spyOn(process, "exit").mockImplementation((_code) => { throw new Error("exit"); });
2062
+ mockApiError(403, "Not a member");
2063
+ await expect(workspaceMemberListCommand.parseAsync(["node", "cli"])).rejects.toThrow();
2064
+ expect(consoleSpy).toHaveBeenCalledWith("Error: Not a member");
2065
+ consoleSpy.mockRestore();
2066
+ exitSpy.mockRestore();
2067
+ });
2068
+ it("workflow cancel returns ApiError message", async () => {
2069
+ const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
2070
+ const exitSpy = vi.spyOn(process, "exit").mockImplementation((_code) => { throw new Error("exit"); });
2071
+ mockApiError(404, "Workflow not found");
2072
+ await expect(workflowCancelCommand.parseAsync(["node", "cli", "-w", "wfr_abc"])).rejects.toThrow();
2073
+ expect(consoleSpy).toHaveBeenCalledWith("Error: Workflow not found");
2074
+ consoleSpy.mockRestore();
2075
+ exitSpy.mockRestore();
2076
+ });
2077
+ it("workflow status returns ApiError message", async () => {
2078
+ const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
2079
+ const exitSpy = vi.spyOn(process, "exit").mockImplementation((_code) => { throw new Error("exit"); });
2080
+ mockApiError(404, "Run expired");
2081
+ await expect(workflowStatusCommand.parseAsync(["node", "cli", "-w", "wfr_abc"])).rejects.toThrow();
2082
+ expect(consoleSpy).toHaveBeenCalledWith("Error: Run expired");
2083
+ consoleSpy.mockRestore();
2084
+ exitSpy.mockRestore();
2085
+ });
2086
+ it("user preferences read returns ApiError message", async () => {
2087
+ const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
2088
+ const exitSpy = vi.spyOn(process, "exit").mockImplementation((_code) => { throw new Error("exit"); });
2089
+ mockApiError(401, "Unauthorized");
2090
+ await expect(userPreferencesReadCommand.parseAsync(["node", "cli"])).rejects.toThrow();
2091
+ expect(consoleSpy).toHaveBeenCalledWith("Error: Unauthorized");
2092
+ consoleSpy.mockRestore();
2093
+ exitSpy.mockRestore();
2094
+ });
2095
+ it("user preferences write returns ApiError message", async () => {
2096
+ const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
2097
+ const exitSpy = vi.spyOn(process, "exit").mockImplementation((_code) => { throw new Error("exit"); });
2098
+ mockApiError(400, "Invalid font size");
2099
+ await expect(userPreferencesWriteCommand.parseAsync(["node", "cli", "--font-size", "xxx"])).rejects.toThrow();
2100
+ expect(consoleSpy).toHaveBeenCalledWith("Error: Invalid font size");
2101
+ consoleSpy.mockRestore();
2102
+ exitSpy.mockRestore();
2103
+ });
2104
+ });
2105
+ describe("branch coverage: empty/optional data branches", () => {
2106
+ it("automation list shows empty message when no automations found", async () => {
2107
+ const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
2108
+ mockApiRequest.mockResolvedValueOnce([]);
2109
+ await automationListCommand.parseAsync(["node", "cli"]);
2110
+ expect(consoleSpy).toHaveBeenCalledWith("No automations found.");
2111
+ consoleSpy.mockRestore();
2112
+ });
2113
+ it("automation list with workspace option", async () => {
2114
+ const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
2115
+ mockApiRequest.mockResolvedValueOnce([{ id: "a1", name: "Test", status: "active", triggers: [] }]);
2116
+ await automationListCommand.parseAsync(["node", "cli", "-w", "ws1"]);
2117
+ expect(mockApiRequest).toHaveBeenCalledWith(expect.stringContaining("workspace_id=ws1"), expect.anything());
2118
+ consoleSpy.mockRestore();
2119
+ });
2120
+ it("automation list shows 'none' when triggers are empty", async () => {
2121
+ const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
2122
+ mockApiRequest.mockResolvedValueOnce([{ id: "a1", name: "Untriggered", status: "active", triggers: [] }]);
2123
+ await automationListCommand.parseAsync(["node", "cli"]);
2124
+ expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("triggers=none"));
2125
+ consoleSpy.mockRestore();
2126
+ });
2127
+ it("image create with save-to option", async () => {
2128
+ const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
2129
+ mockApiRequest.mockResolvedValueOnce({ id: "img1", url: "https://cdn.example.com/img.png", created_at: "2026-06-08", workspace_id: "ws1" });
2130
+ await imageCreateCommand.parseAsync(["node", "cli", "-p", "A cat"]);
2131
+ consoleSpy.mockRestore();
2132
+ });
2133
+ it("conversation chat ApiError path", async () => {
2134
+ const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
2135
+ const exitSpy = vi.spyOn(process, "exit").mockImplementation((_code) => { throw new Error("exit"); });
2136
+ mockApiError(401, "Not authenticated");
2137
+ await expect(conversationChatCommand.parseAsync(["node", "cli", "-m", "Hello"])).rejects.toThrow();
2138
+ expect(consoleSpy).toHaveBeenCalledWith("Error: Not authenticated");
2139
+ consoleSpy.mockRestore();
2140
+ exitSpy.mockRestore();
2141
+ });
2142
+ it("workspace list ApiError path", async () => {
2143
+ const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
2144
+ const exitSpy = vi.spyOn(process, "exit").mockImplementation((_code) => { throw new Error("exit"); });
2145
+ mockApiError(403, "Org not found");
2146
+ await expect(workspaceListCommand.parseAsync(["node", "cli"])).rejects.toThrow();
2147
+ expect(consoleSpy).toHaveBeenCalledWith("Error: Org not found");
2148
+ consoleSpy.mockRestore();
2149
+ exitSpy.mockRestore();
2150
+ });
2151
+ it("org list ApiError path", async () => {
2152
+ const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
2153
+ const exitSpy = vi.spyOn(process, "exit").mockImplementation((_code) => { throw new Error("exit"); });
2154
+ mockApiError(401, "Token expired");
2155
+ await expect(orgListCommand.parseAsync(["node", "cli"])).rejects.toThrow();
2156
+ expect(consoleSpy).toHaveBeenCalledWith("Error: Token expired");
2157
+ consoleSpy.mockRestore();
2158
+ exitSpy.mockRestore();
2159
+ });
2160
+ it("api-key create ApiError path", async () => {
2161
+ const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
2162
+ const exitSpy = vi.spyOn(process, "exit").mockImplementation((_code) => { throw new Error("exit"); });
2163
+ mockApiError(429, "Rate limit exceeded");
2164
+ await expect(apiKeyCreateCommand.parseAsync(["node", "cli", "mykey"])).rejects.toThrow();
2165
+ expect(consoleSpy).toHaveBeenCalledWith("Error: Rate limit exceeded");
2166
+ consoleSpy.mockRestore();
2167
+ exitSpy.mockRestore();
2168
+ });
2169
+ it("plugin list ApiError path", async () => {
2170
+ const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
2171
+ const exitSpy = vi.spyOn(process, "exit").mockImplementation((_code) => { throw new Error("exit"); });
2172
+ mockApiError(403, "Permission denied");
2173
+ await expect(pluginListCommand.parseAsync(["node", "cli"])).rejects.toThrow();
2174
+ expect(consoleSpy).toHaveBeenCalledWith("Error: Permission denied");
2175
+ consoleSpy.mockRestore();
2176
+ exitSpy.mockRestore();
2177
+ });
2178
+ it("billing status ApiError path", async () => {
2179
+ const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
2180
+ const exitSpy = vi.spyOn(process, "exit").mockImplementation((_code) => { throw new Error("exit"); });
2181
+ mockApiError(402, "Billing error");
2182
+ await expect(billingStatusCommand.parseAsync(["node", "cli"])).rejects.toThrow();
2183
+ expect(consoleSpy).toHaveBeenCalledWith("Error: Billing error");
2184
+ consoleSpy.mockRestore();
2185
+ exitSpy.mockRestore();
2186
+ });
2187
+ it("chat send ApiError path", async () => {
2188
+ const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
2189
+ const exitSpy = vi.spyOn(process, "exit").mockImplementation((_code) => { throw new Error("exit"); });
2190
+ mockApiError(503, "Service unavailable");
2191
+ await expect(chatSendCommand.parseAsync(["node", "cli", "test"])).rejects.toThrow();
2192
+ expect(consoleSpy).toHaveBeenCalledWith("Error: Service unavailable");
2193
+ consoleSpy.mockRestore();
2194
+ exitSpy.mockRestore();
2195
+ });
2196
+ it("document read ApiError path", async () => {
2197
+ const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
2198
+ const exitSpy = vi.spyOn(process, "exit").mockImplementation((_code) => { throw new Error("exit"); });
2199
+ mockApiError(404, "Document not found");
2200
+ await expect(documentReadCommand.parseAsync(["node", "cli", "-d", "doc1"])).rejects.toThrow();
2201
+ expect(consoleSpy).toHaveBeenCalledWith("Error: Document not found");
2202
+ consoleSpy.mockRestore();
2203
+ exitSpy.mockRestore();
2204
+ });
2205
+ it("notification list with empty results", async () => {
2206
+ const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
2207
+ mockApiRequest.mockResolvedValueOnce({ notifications: [] });
2208
+ await notificationsListCommand.parseAsync(["node", "cli"]);
2209
+ consoleSpy.mockRestore();
2210
+ });
2211
+ it("workflow run ApiError path", async () => {
2212
+ const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
2213
+ const exitSpy = vi.spyOn(process, "exit").mockImplementation((_code) => { throw new Error("exit"); });
2214
+ mockApiError(400, "Invalid workflow spec");
2215
+ await expect(workflowRunCommand.parseAsync(["node", "cli", "-w", "wf1"])).rejects.toThrow();
2216
+ expect(consoleSpy).toHaveBeenCalledWith("Error: Invalid workflow spec");
2217
+ consoleSpy.mockRestore();
2218
+ exitSpy.mockRestore();
2219
+ });
2220
+ });
1749
2221
  //# sourceMappingURL=commands.test.js.map