@oxagen/cli 0.5.0 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +66 -3
- package/dist/agent/__tests__/code-graph.test.d.ts +2 -0
- package/dist/agent/__tests__/code-graph.test.d.ts.map +1 -0
- package/dist/agent/__tests__/code-graph.test.js +83 -0
- package/dist/agent/__tests__/code-graph.test.js.map +1 -0
- package/dist/agent/__tests__/evaluator.test.d.ts +2 -0
- package/dist/agent/__tests__/evaluator.test.d.ts.map +1 -0
- package/dist/agent/__tests__/evaluator.test.js +96 -0
- package/dist/agent/__tests__/evaluator.test.js.map +1 -0
- package/dist/agent/__tests__/fleet-memory.test.d.ts +2 -0
- package/dist/agent/__tests__/fleet-memory.test.d.ts.map +1 -0
- package/dist/agent/__tests__/fleet-memory.test.js +107 -0
- package/dist/agent/__tests__/fleet-memory.test.js.map +1 -0
- package/dist/agent/__tests__/fleet-store.test.d.ts +2 -0
- package/dist/agent/__tests__/fleet-store.test.d.ts.map +1 -0
- package/dist/agent/__tests__/fleet-store.test.js +93 -0
- package/dist/agent/__tests__/fleet-store.test.js.map +1 -0
- package/dist/agent/__tests__/git-isolation.test.d.ts +2 -0
- package/dist/agent/__tests__/git-isolation.test.d.ts.map +1 -0
- package/dist/agent/__tests__/git-isolation.test.js +119 -0
- package/dist/agent/__tests__/git-isolation.test.js.map +1 -0
- package/dist/agent/__tests__/judge.test.d.ts +2 -0
- package/dist/agent/__tests__/judge.test.d.ts.map +1 -0
- package/dist/agent/__tests__/judge.test.js +140 -0
- package/dist/agent/__tests__/judge.test.js.map +1 -0
- package/dist/agent/__tests__/loop-errors.test.d.ts +2 -0
- package/dist/agent/__tests__/loop-errors.test.d.ts.map +1 -0
- package/dist/agent/__tests__/loop-errors.test.js +75 -0
- package/dist/agent/__tests__/loop-errors.test.js.map +1 -0
- package/dist/agent/__tests__/loop-gating.test.d.ts +2 -0
- package/dist/agent/__tests__/loop-gating.test.d.ts.map +1 -0
- package/dist/agent/__tests__/loop-gating.test.js +94 -0
- package/dist/agent/__tests__/loop-gating.test.js.map +1 -0
- package/dist/agent/__tests__/model-router.test.d.ts +2 -0
- package/dist/agent/__tests__/model-router.test.d.ts.map +1 -0
- package/dist/agent/__tests__/model-router.test.js +138 -0
- package/dist/agent/__tests__/model-router.test.js.map +1 -0
- package/dist/agent/__tests__/orchestrator-isolation.test.d.ts +2 -0
- package/dist/agent/__tests__/orchestrator-isolation.test.d.ts.map +1 -0
- package/dist/agent/__tests__/orchestrator-isolation.test.js +134 -0
- package/dist/agent/__tests__/orchestrator-isolation.test.js.map +1 -0
- package/dist/agent/__tests__/orchestrator.test.d.ts +2 -0
- package/dist/agent/__tests__/orchestrator.test.d.ts.map +1 -0
- package/dist/agent/__tests__/orchestrator.test.js +201 -0
- package/dist/agent/__tests__/orchestrator.test.js.map +1 -0
- package/dist/agent/__tests__/permissions.test.d.ts +2 -0
- package/dist/agent/__tests__/permissions.test.d.ts.map +1 -0
- package/dist/agent/__tests__/permissions.test.js +206 -0
- package/dist/agent/__tests__/permissions.test.js.map +1 -0
- package/dist/agent/__tests__/pipeline-telemetry.test.d.ts +2 -0
- package/dist/agent/__tests__/pipeline-telemetry.test.d.ts.map +1 -0
- package/dist/agent/__tests__/pipeline-telemetry.test.js +158 -0
- package/dist/agent/__tests__/pipeline-telemetry.test.js.map +1 -0
- package/dist/agent/__tests__/pipeline.test.d.ts +2 -0
- package/dist/agent/__tests__/pipeline.test.d.ts.map +1 -0
- package/dist/agent/__tests__/pipeline.test.js +235 -0
- package/dist/agent/__tests__/pipeline.test.js.map +1 -0
- package/dist/agent/__tests__/planner.test.d.ts +2 -0
- package/dist/agent/__tests__/planner.test.d.ts.map +1 -0
- package/dist/agent/__tests__/planner.test.js +98 -0
- package/dist/agent/__tests__/planner.test.js.map +1 -0
- package/dist/agent/__tests__/prompt-enhancer.test.d.ts +2 -0
- package/dist/agent/__tests__/prompt-enhancer.test.d.ts.map +1 -0
- package/dist/agent/__tests__/prompt-enhancer.test.js +107 -0
- package/dist/agent/__tests__/prompt-enhancer.test.js.map +1 -0
- package/dist/agent/__tests__/rate-card.test.d.ts +2 -0
- package/dist/agent/__tests__/rate-card.test.d.ts.map +1 -0
- package/dist/agent/__tests__/rate-card.test.js +69 -0
- package/dist/agent/__tests__/rate-card.test.js.map +1 -0
- package/dist/agent/__tests__/system-prompt.test.d.ts +2 -0
- package/dist/agent/__tests__/system-prompt.test.d.ts.map +1 -0
- package/dist/agent/__tests__/system-prompt.test.js +29 -0
- package/dist/agent/__tests__/system-prompt.test.js.map +1 -0
- package/dist/agent/__tests__/trace-format-verbose.test.d.ts +2 -0
- package/dist/agent/__tests__/trace-format-verbose.test.d.ts.map +1 -0
- package/dist/agent/__tests__/trace-format-verbose.test.js +93 -0
- package/dist/agent/__tests__/trace-format-verbose.test.js.map +1 -0
- package/dist/agent/__tests__/trace-format.test.d.ts +2 -0
- package/dist/agent/__tests__/trace-format.test.d.ts.map +1 -0
- package/dist/agent/__tests__/trace-format.test.js +104 -0
- package/dist/agent/__tests__/trace-format.test.js.map +1 -0
- package/dist/agent/__tests__/trace-store.test.d.ts +2 -0
- package/dist/agent/__tests__/trace-store.test.d.ts.map +1 -0
- package/dist/agent/__tests__/trace-store.test.js +113 -0
- package/dist/agent/__tests__/trace-store.test.js.map +1 -0
- package/dist/agent/__tests__/verbose-log.test.d.ts +2 -0
- package/dist/agent/__tests__/verbose-log.test.d.ts.map +1 -0
- package/dist/agent/__tests__/verbose-log.test.js +69 -0
- package/dist/agent/__tests__/verbose-log.test.js.map +1 -0
- package/dist/agent/code-graph.d.ts +18 -0
- package/dist/agent/code-graph.d.ts.map +1 -0
- package/dist/agent/code-graph.js +119 -0
- package/dist/agent/code-graph.js.map +1 -0
- package/dist/agent/env.d.ts +11 -0
- package/dist/agent/env.d.ts.map +1 -0
- package/dist/agent/env.js +82 -0
- package/dist/agent/env.js.map +1 -0
- package/dist/agent/evaluator.d.ts +13 -0
- package/dist/agent/evaluator.d.ts.map +1 -0
- package/dist/agent/evaluator.js +150 -0
- package/dist/agent/evaluator.js.map +1 -0
- package/dist/agent/fleet/git-isolation.d.ts +142 -0
- package/dist/agent/fleet/git-isolation.d.ts.map +1 -0
- package/dist/agent/fleet/git-isolation.js +290 -0
- package/dist/agent/fleet/git-isolation.js.map +1 -0
- package/dist/agent/fleet/memory.d.ts +21 -0
- package/dist/agent/fleet/memory.d.ts.map +1 -0
- package/dist/agent/fleet/memory.js +129 -0
- package/dist/agent/fleet/memory.js.map +1 -0
- package/dist/agent/fleet/orchestrator.d.ts +108 -0
- package/dist/agent/fleet/orchestrator.d.ts.map +1 -0
- package/dist/agent/fleet/orchestrator.js +358 -0
- package/dist/agent/fleet/orchestrator.js.map +1 -0
- package/dist/agent/fleet/store.d.ts +13 -0
- package/dist/agent/fleet/store.d.ts.map +1 -0
- package/dist/agent/fleet/store.js +79 -0
- package/dist/agent/fleet/store.js.map +1 -0
- package/dist/agent/fleet/types.d.ts +107 -0
- package/dist/agent/fleet/types.d.ts.map +1 -0
- package/dist/agent/fleet/types.js +17 -0
- package/dist/agent/fleet/types.js.map +1 -0
- package/dist/agent/judge.d.ts +46 -0
- package/dist/agent/judge.d.ts.map +1 -0
- package/dist/agent/judge.js +182 -0
- package/dist/agent/judge.js.map +1 -0
- package/dist/agent/loop.d.ts +96 -0
- package/dist/agent/loop.d.ts.map +1 -0
- package/dist/agent/loop.js +233 -0
- package/dist/agent/loop.js.map +1 -0
- package/dist/agent/memory.d.ts +14 -0
- package/dist/agent/memory.d.ts.map +1 -0
- package/dist/agent/memory.js +118 -0
- package/dist/agent/memory.js.map +1 -0
- package/dist/agent/model-router.d.ts +65 -0
- package/dist/agent/model-router.d.ts.map +1 -0
- package/dist/agent/model-router.js +118 -0
- package/dist/agent/model-router.js.map +1 -0
- package/dist/agent/model.d.ts +9 -0
- package/dist/agent/model.d.ts.map +1 -0
- package/dist/agent/model.js +24 -0
- package/dist/agent/model.js.map +1 -0
- package/dist/agent/permissions.d.ts +103 -0
- package/dist/agent/permissions.d.ts.map +1 -0
- package/dist/agent/permissions.js +245 -0
- package/dist/agent/permissions.js.map +1 -0
- package/dist/agent/pipeline.d.ts +92 -0
- package/dist/agent/pipeline.d.ts.map +1 -0
- package/dist/agent/pipeline.js +371 -0
- package/dist/agent/pipeline.js.map +1 -0
- package/dist/agent/planner.d.ts +19 -0
- package/dist/agent/planner.d.ts.map +1 -0
- package/dist/agent/planner.js +139 -0
- package/dist/agent/planner.js.map +1 -0
- package/dist/agent/project-context.d.ts +13 -0
- package/dist/agent/project-context.d.ts.map +1 -0
- package/dist/agent/project-context.js +66 -0
- package/dist/agent/project-context.js.map +1 -0
- package/dist/agent/prompt-enhancer.d.ts +46 -0
- package/dist/agent/prompt-enhancer.d.ts.map +1 -0
- package/dist/agent/prompt-enhancer.js +137 -0
- package/dist/agent/prompt-enhancer.js.map +1 -0
- package/dist/agent/rate-card.d.ts +77 -0
- package/dist/agent/rate-card.d.ts.map +1 -0
- package/dist/agent/rate-card.js +99 -0
- package/dist/agent/rate-card.js.map +1 -0
- package/dist/agent/system-prompt.d.ts +14 -0
- package/dist/agent/system-prompt.d.ts.map +1 -0
- package/dist/agent/system-prompt.js +47 -0
- package/dist/agent/system-prompt.js.map +1 -0
- package/dist/agent/tools.d.ts +23 -0
- package/dist/agent/tools.d.ts.map +1 -0
- package/dist/agent/tools.js +354 -0
- package/dist/agent/tools.js.map +1 -0
- package/dist/agent/trace-format.d.ts +13 -0
- package/dist/agent/trace-format.d.ts.map +1 -0
- package/dist/agent/trace-format.js +188 -0
- package/dist/agent/trace-format.js.map +1 -0
- package/dist/agent/trace-store.d.ts +19 -0
- package/dist/agent/trace-store.d.ts.map +1 -0
- package/dist/agent/trace-store.js +82 -0
- package/dist/agent/trace-store.js.map +1 -0
- package/dist/agent/trace.d.ts +180 -0
- package/dist/agent/trace.d.ts.map +1 -0
- package/dist/agent/trace.js +2 -0
- package/dist/agent/trace.js.map +1 -0
- package/dist/agent/verbose-log.d.ts +8 -0
- package/dist/agent/verbose-log.d.ts.map +1 -0
- package/dist/agent/verbose-log.js +53 -0
- package/dist/agent/verbose-log.js.map +1 -0
- package/dist/agents/__tests__/loader.test.d.ts +2 -0
- package/dist/agents/__tests__/loader.test.d.ts.map +1 -0
- package/dist/agents/__tests__/loader.test.js +88 -0
- package/dist/agents/__tests__/loader.test.js.map +1 -0
- package/dist/agents/__tests__/tools.test.d.ts +2 -0
- package/dist/agents/__tests__/tools.test.d.ts.map +1 -0
- package/dist/agents/__tests__/tools.test.js +40 -0
- package/dist/agents/__tests__/tools.test.js.map +1 -0
- package/dist/agents/index.d.ts +12 -0
- package/dist/agents/index.d.ts.map +1 -0
- package/dist/agents/index.js +4 -0
- package/dist/agents/index.js.map +1 -0
- package/dist/agents/loader.d.ts +25 -0
- package/dist/agents/loader.d.ts.map +1 -0
- package/dist/agents/loader.js +133 -0
- package/dist/agents/loader.js.map +1 -0
- package/dist/agents/tools.d.ts +14 -0
- package/dist/agents/tools.d.ts.map +1 -0
- package/dist/agents/tools.js +21 -0
- package/dist/agents/tools.js.map +1 -0
- package/dist/agents/types.d.ts +27 -0
- package/dist/agents/types.d.ts.map +1 -0
- package/dist/agents/types.js +11 -0
- package/dist/agents/types.js.map +1 -0
- package/dist/agents/write.d.ts +10 -0
- package/dist/agents/write.d.ts.map +1 -0
- package/dist/agents/write.js +28 -0
- package/dist/agents/write.js.map +1 -0
- package/dist/commands/__tests__/agent.test.d.ts +2 -0
- package/dist/commands/__tests__/agent.test.d.ts.map +1 -0
- package/dist/commands/__tests__/agent.test.js +82 -0
- package/dist/commands/__tests__/agent.test.js.map +1 -0
- package/dist/commands/__tests__/command.test.d.ts +2 -0
- package/dist/commands/__tests__/command.test.d.ts.map +1 -0
- package/dist/commands/__tests__/command.test.js +73 -0
- package/dist/commands/__tests__/command.test.js.map +1 -0
- package/dist/commands/__tests__/cost.test.d.ts +2 -0
- package/dist/commands/__tests__/cost.test.d.ts.map +1 -0
- package/dist/commands/__tests__/cost.test.js +139 -0
- package/dist/commands/__tests__/cost.test.js.map +1 -0
- package/dist/commands/__tests__/graph.pull.test.d.ts +2 -0
- package/dist/commands/__tests__/graph.pull.test.d.ts.map +1 -0
- package/dist/commands/__tests__/graph.pull.test.js +259 -0
- package/dist/commands/__tests__/graph.pull.test.js.map +1 -0
- package/dist/commands/__tests__/mcp.test.d.ts +2 -0
- package/dist/commands/__tests__/mcp.test.d.ts.map +1 -0
- package/dist/commands/__tests__/mcp.test.js +88 -0
- package/dist/commands/__tests__/mcp.test.js.map +1 -0
- package/dist/commands/__tests__/replay.test.d.ts +2 -0
- package/dist/commands/__tests__/replay.test.d.ts.map +1 -0
- package/dist/commands/__tests__/replay.test.js +76 -0
- package/dist/commands/__tests__/replay.test.js.map +1 -0
- package/dist/commands/__tests__/rules.test.d.ts +2 -0
- package/dist/commands/__tests__/rules.test.d.ts.map +1 -0
- package/dist/commands/__tests__/rules.test.js +95 -0
- package/dist/commands/__tests__/rules.test.js.map +1 -0
- package/dist/commands/__tests__/settings.test.d.ts +2 -0
- package/dist/commands/__tests__/settings.test.d.ts.map +1 -0
- package/dist/commands/__tests__/settings.test.js +83 -0
- package/dist/commands/__tests__/settings.test.js.map +1 -0
- package/dist/commands/agent.d.ts +15 -0
- package/dist/commands/agent.d.ts.map +1 -0
- package/dist/commands/agent.js +58 -0
- package/dist/commands/agent.js.map +1 -0
- package/dist/commands/agent.skill.load.d.ts +3 -0
- package/dist/commands/agent.skill.load.d.ts.map +1 -0
- package/dist/commands/agent.skill.load.js +57 -0
- package/dist/commands/agent.skill.load.js.map +1 -0
- package/dist/commands/code.d.ts +14 -0
- package/dist/commands/code.d.ts.map +1 -0
- package/dist/commands/code.js +100 -0
- package/dist/commands/code.js.map +1 -0
- package/dist/commands/command.d.ts +17 -0
- package/dist/commands/command.d.ts.map +1 -0
- package/dist/commands/command.js +74 -0
- package/dist/commands/command.js.map +1 -0
- package/dist/commands/config.d.ts +2 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +66 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/cost.d.ts +10 -0
- package/dist/commands/cost.d.ts.map +1 -0
- package/dist/commands/cost.js +140 -0
- package/dist/commands/cost.js.map +1 -0
- package/dist/commands/env.d.ts +19 -0
- package/dist/commands/env.d.ts.map +1 -0
- package/dist/commands/env.js +64 -0
- package/dist/commands/env.js.map +1 -0
- package/dist/commands/graph.pull.d.ts +15 -0
- package/dist/commands/graph.pull.d.ts.map +1 -0
- package/dist/commands/graph.pull.js +137 -0
- package/dist/commands/graph.pull.js.map +1 -0
- package/dist/commands/graph.search.d.ts +10 -0
- package/dist/commands/graph.search.d.ts.map +1 -0
- package/dist/commands/graph.search.js +25 -0
- package/dist/commands/graph.search.js.map +1 -0
- package/dist/commands/graph.status.d.ts +10 -0
- package/dist/commands/graph.status.d.ts.map +1 -0
- package/dist/commands/graph.status.js +75 -0
- package/dist/commands/graph.status.js.map +1 -0
- package/dist/commands/mcp.add.d.ts +13 -0
- package/dist/commands/mcp.add.d.ts.map +1 -0
- package/dist/commands/mcp.add.js +110 -0
- package/dist/commands/mcp.add.js.map +1 -0
- package/dist/commands/mcp.auth.d.ts +10 -0
- package/dist/commands/mcp.auth.d.ts.map +1 -0
- package/dist/commands/mcp.auth.js +132 -0
- package/dist/commands/mcp.auth.js.map +1 -0
- package/dist/commands/mcp.check.d.ts +10 -0
- package/dist/commands/mcp.check.d.ts.map +1 -0
- package/dist/commands/mcp.check.js +114 -0
- package/dist/commands/mcp.check.js.map +1 -0
- package/dist/commands/mcp.d.ts +18 -0
- package/dist/commands/mcp.d.ts.map +1 -0
- package/dist/commands/mcp.js +183 -0
- package/dist/commands/mcp.js.map +1 -0
- package/dist/commands/mcp.list.d.ts +9 -0
- package/dist/commands/mcp.list.d.ts.map +1 -0
- package/dist/commands/mcp.list.js +93 -0
- package/dist/commands/mcp.list.js.map +1 -0
- package/dist/commands/mcp.permit.d.ts +12 -0
- package/dist/commands/mcp.permit.d.ts.map +1 -0
- package/dist/commands/mcp.permit.js +117 -0
- package/dist/commands/mcp.permit.js.map +1 -0
- package/dist/commands/mcp.remove.d.ts +9 -0
- package/dist/commands/mcp.remove.d.ts.map +1 -0
- package/dist/commands/mcp.remove.js +65 -0
- package/dist/commands/mcp.remove.js.map +1 -0
- package/dist/commands/plugin.org.install_bulk.js +1 -1
- package/dist/commands/plugin.org.install_bulk.js.map +1 -1
- package/dist/commands/privacy.erase.test.js +7 -0
- package/dist/commands/privacy.erase.test.js.map +1 -1
- package/dist/commands/replay.d.ts +5 -0
- package/dist/commands/replay.d.ts.map +1 -0
- package/dist/commands/replay.js +28 -0
- package/dist/commands/replay.js.map +1 -0
- package/dist/commands/rules.d.ts +19 -0
- package/dist/commands/rules.d.ts.map +1 -0
- package/dist/commands/rules.js +96 -0
- package/dist/commands/rules.js.map +1 -0
- package/dist/commands/schema/schema.config.d.ts +3 -0
- package/dist/commands/schema/schema.config.d.ts.map +1 -0
- package/dist/commands/schema/schema.config.js +34 -0
- package/dist/commands/schema/schema.config.js.map +1 -0
- package/dist/commands/schema/schema.disable.d.ts +3 -0
- package/dist/commands/schema/schema.disable.d.ts.map +1 -0
- package/dist/commands/schema/schema.disable.js +22 -0
- package/dist/commands/schema/schema.disable.js.map +1 -0
- package/dist/commands/schema/schema.enable.d.ts +3 -0
- package/dist/commands/schema/schema.enable.d.ts.map +1 -0
- package/dist/commands/schema/schema.enable.js +22 -0
- package/dist/commands/schema/schema.enable.js.map +1 -0
- package/dist/commands/schema/schema.export.d.ts +3 -0
- package/dist/commands/schema/schema.export.d.ts.map +1 -0
- package/dist/commands/schema/schema.export.js +31 -0
- package/dist/commands/schema/schema.export.js.map +1 -0
- package/dist/commands/schema/schema.get.d.ts +3 -0
- package/dist/commands/schema/schema.get.d.ts.map +1 -0
- package/dist/commands/schema/schema.get.js +23 -0
- package/dist/commands/schema/schema.get.js.map +1 -0
- package/dist/commands/schema/schema.label.d.ts +5 -0
- package/dist/commands/schema/schema.label.d.ts.map +1 -0
- package/dist/commands/schema/schema.label.js +60 -0
- package/dist/commands/schema/schema.label.js.map +1 -0
- package/dist/commands/schema/schema.list.d.ts +3 -0
- package/dist/commands/schema/schema.list.d.ts.map +1 -0
- package/dist/commands/schema/schema.list.js +30 -0
- package/dist/commands/schema/schema.list.js.map +1 -0
- package/dist/commands/schema/schema.prop.d.ts +5 -0
- package/dist/commands/schema/schema.prop.d.ts.map +1 -0
- package/dist/commands/schema/schema.prop.js +72 -0
- package/dist/commands/schema/schema.prop.js.map +1 -0
- package/dist/commands/schema/schema.reconcile.d.ts +10 -0
- package/dist/commands/schema/schema.reconcile.d.ts.map +1 -0
- package/dist/commands/schema/schema.reconcile.js +65 -0
- package/dist/commands/schema/schema.reconcile.js.map +1 -0
- package/dist/commands/schema/schema.rel.d.ts +5 -0
- package/dist/commands/schema/schema.rel.d.ts.map +1 -0
- package/dist/commands/schema/schema.rel.js +65 -0
- package/dist/commands/schema/schema.rel.js.map +1 -0
- package/dist/commands/schema/schema.version.d.ts +7 -0
- package/dist/commands/schema/schema.version.d.ts.map +1 -0
- package/dist/commands/schema/schema.version.js +96 -0
- package/dist/commands/schema/schema.version.js.map +1 -0
- package/dist/commands/secret.d.ts +23 -0
- package/dist/commands/secret.d.ts.map +1 -0
- package/dist/commands/secret.js +90 -0
- package/dist/commands/secret.js.map +1 -0
- package/dist/commands/settings.d.ts +10 -0
- package/dist/commands/settings.d.ts.map +1 -0
- package/dist/commands/settings.js +117 -0
- package/dist/commands/settings.js.map +1 -0
- package/dist/commands/skill.create.d.ts +3 -0
- package/dist/commands/skill.create.d.ts.map +1 -0
- package/dist/commands/skill.create.js +52 -0
- package/dist/commands/skill.create.js.map +1 -0
- package/dist/commands/skill.enable.d.ts +3 -0
- package/dist/commands/skill.enable.d.ts.map +1 -0
- package/dist/commands/skill.enable.js +31 -0
- package/dist/commands/skill.enable.js.map +1 -0
- package/dist/commands.test.js +1291 -281
- package/dist/commands.test.js.map +1 -1
- package/dist/components/DevStatus.d.ts.map +1 -1
- package/dist/components/DevStatus.js +3 -2
- package/dist/components/DevStatus.js.map +1 -1
- package/dist/daemon/client.d.ts +30 -0
- package/dist/daemon/client.d.ts.map +1 -0
- package/dist/daemon/client.js +97 -0
- package/dist/daemon/client.js.map +1 -0
- package/dist/daemon/code-graph/builder.d.ts +6 -0
- package/dist/daemon/code-graph/builder.d.ts.map +1 -0
- package/dist/daemon/code-graph/builder.js +215 -0
- package/dist/daemon/code-graph/builder.js.map +1 -0
- package/dist/daemon/code-graph/query.d.ts +29 -0
- package/dist/daemon/code-graph/query.d.ts.map +1 -0
- package/dist/daemon/code-graph/query.js +98 -0
- package/dist/daemon/code-graph/query.js.map +1 -0
- package/dist/daemon/code-graph/types.d.ts +37 -0
- package/dist/daemon/code-graph/types.d.ts.map +1 -0
- package/dist/daemon/code-graph/types.js +5 -0
- package/dist/daemon/code-graph/types.js.map +1 -0
- package/dist/daemon/code-graph/watcher.d.ts +37 -0
- package/dist/daemon/code-graph/watcher.d.ts.map +1 -0
- package/dist/daemon/code-graph/watcher.js +79 -0
- package/dist/daemon/code-graph/watcher.js.map +1 -0
- package/dist/daemon/lifecycle.d.ts +6 -0
- package/dist/daemon/lifecycle.d.ts.map +1 -0
- package/dist/daemon/lifecycle.js +132 -0
- package/dist/daemon/lifecycle.js.map +1 -0
- package/dist/daemon/protocol.d.ts +113 -0
- package/dist/daemon/protocol.d.ts.map +1 -0
- package/dist/daemon/protocol.js +16 -0
- package/dist/daemon/protocol.js.map +1 -0
- package/dist/daemon/server.d.ts +26 -0
- package/dist/daemon/server.d.ts.map +1 -0
- package/dist/daemon/server.js +168 -0
- package/dist/daemon/server.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +559 -357
- package/dist/index.js.map +1 -1
- package/dist/lib/api.d.ts +5 -0
- package/dist/lib/api.d.ts.map +1 -0
- package/dist/lib/api.js +52 -0
- package/dist/lib/api.js.map +1 -0
- package/dist/lib/config.d.ts +5 -0
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +8 -2
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/differential-context.d.ts +46 -0
- package/dist/lib/differential-context.d.ts.map +1 -0
- package/dist/lib/differential-context.js +89 -0
- package/dist/lib/differential-context.js.map +1 -0
- package/dist/lib/resolve.d.ts +3 -0
- package/dist/lib/resolve.d.ts.map +1 -0
- package/dist/lib/resolve.js +29 -0
- package/dist/lib/resolve.js.map +1 -0
- package/dist/lib/structured-tool-io.d.ts +31 -0
- package/dist/lib/structured-tool-io.d.ts.map +1 -0
- package/dist/lib/structured-tool-io.js +56 -0
- package/dist/lib/structured-tool-io.js.map +1 -0
- package/dist/mcp/__tests__/client.test.d.ts +2 -0
- package/dist/mcp/__tests__/client.test.d.ts.map +1 -0
- package/dist/mcp/__tests__/client.test.js +101 -0
- package/dist/mcp/__tests__/client.test.js.map +1 -0
- package/dist/mcp/client.d.ts +89 -0
- package/dist/mcp/client.d.ts.map +1 -0
- package/dist/mcp/client.js +201 -0
- package/dist/mcp/client.js.map +1 -0
- package/dist/repl/__tests__/_queue_demo.test.d.ts +2 -0
- package/dist/repl/__tests__/_queue_demo.test.d.ts.map +1 -0
- package/dist/repl/__tests__/_queue_demo.test.js +40 -0
- package/dist/repl/__tests__/_queue_demo.test.js.map +1 -0
- package/dist/repl/__tests__/components.test.d.ts +2 -0
- package/dist/repl/__tests__/components.test.d.ts.map +1 -0
- package/dist/repl/__tests__/components.test.js +87 -0
- package/dist/repl/__tests__/components.test.js.map +1 -0
- package/dist/repl/__tests__/interactive.queue.test.d.ts +2 -0
- package/dist/repl/__tests__/interactive.queue.test.d.ts.map +1 -0
- package/dist/repl/__tests__/interactive.queue.test.js +124 -0
- package/dist/repl/__tests__/interactive.queue.test.js.map +1 -0
- package/dist/repl/components.d.ts +76 -0
- package/dist/repl/components.d.ts.map +1 -0
- package/dist/repl/components.js +182 -0
- package/dist/repl/components.js.map +1 -0
- package/dist/repl/interactive.d.ts +17 -0
- package/dist/repl/interactive.d.ts.map +1 -0
- package/dist/repl/interactive.js +439 -0
- package/dist/repl/interactive.js.map +1 -0
- package/dist/repl/one-shot.d.ts +25 -0
- package/dist/repl/one-shot.d.ts.map +1 -0
- package/dist/repl/one-shot.js +153 -0
- package/dist/repl/one-shot.js.map +1 -0
- package/dist/rules/__tests__/enforce.test.d.ts +2 -0
- package/dist/rules/__tests__/enforce.test.d.ts.map +1 -0
- package/dist/rules/__tests__/enforce.test.js +58 -0
- package/dist/rules/__tests__/enforce.test.js.map +1 -0
- package/dist/rules/__tests__/loader.test.d.ts +2 -0
- package/dist/rules/__tests__/loader.test.d.ts.map +1 -0
- package/dist/rules/__tests__/loader.test.js +54 -0
- package/dist/rules/__tests__/loader.test.js.map +1 -0
- package/dist/rules/enforce.d.ts +23 -0
- package/dist/rules/enforce.d.ts.map +1 -0
- package/dist/rules/enforce.js +36 -0
- package/dist/rules/enforce.js.map +1 -0
- package/dist/rules/index.d.ts +10 -0
- package/dist/rules/index.d.ts.map +1 -0
- package/dist/rules/index.js +4 -0
- package/dist/rules/index.js.map +1 -0
- package/dist/rules/loader.d.ts +10 -0
- package/dist/rules/loader.d.ts.map +1 -0
- package/dist/rules/loader.js +77 -0
- package/dist/rules/loader.js.map +1 -0
- package/dist/rules/types.d.ts +39 -0
- package/dist/rules/types.d.ts.map +1 -0
- package/dist/rules/types.js +16 -0
- package/dist/rules/types.js.map +1 -0
- package/dist/rules/write.d.ts +10 -0
- package/dist/rules/write.d.ts.map +1 -0
- package/dist/rules/write.js +28 -0
- package/dist/rules/write.js.map +1 -0
- package/dist/settings/__tests__/gate.test.d.ts +2 -0
- package/dist/settings/__tests__/gate.test.d.ts.map +1 -0
- package/dist/settings/__tests__/gate.test.js +137 -0
- package/dist/settings/__tests__/gate.test.js.map +1 -0
- package/dist/settings/__tests__/hooks.test.d.ts +2 -0
- package/dist/settings/__tests__/hooks.test.d.ts.map +1 -0
- package/dist/settings/__tests__/hooks.test.js +103 -0
- package/dist/settings/__tests__/hooks.test.js.map +1 -0
- package/dist/settings/__tests__/mcp-write.test.d.ts +2 -0
- package/dist/settings/__tests__/mcp-write.test.d.ts.map +1 -0
- package/dist/settings/__tests__/mcp-write.test.js +77 -0
- package/dist/settings/__tests__/mcp-write.test.js.map +1 -0
- package/dist/settings/__tests__/permissions-gate.test.d.ts +2 -0
- package/dist/settings/__tests__/permissions-gate.test.d.ts.map +1 -0
- package/dist/settings/__tests__/permissions-gate.test.js +75 -0
- package/dist/settings/__tests__/permissions-gate.test.js.map +1 -0
- package/dist/settings/__tests__/resolve.test.d.ts +2 -0
- package/dist/settings/__tests__/resolve.test.d.ts.map +1 -0
- package/dist/settings/__tests__/resolve.test.js +109 -0
- package/dist/settings/__tests__/resolve.test.js.map +1 -0
- package/dist/settings/__tests__/runtime.test.d.ts +2 -0
- package/dist/settings/__tests__/runtime.test.d.ts.map +1 -0
- package/dist/settings/__tests__/runtime.test.js +72 -0
- package/dist/settings/__tests__/runtime.test.js.map +1 -0
- package/dist/settings/__tests__/schema.test.d.ts +2 -0
- package/dist/settings/__tests__/schema.test.d.ts.map +1 -0
- package/dist/settings/__tests__/schema.test.js +55 -0
- package/dist/settings/__tests__/schema.test.js.map +1 -0
- package/dist/settings/__tests__/write.test.d.ts +2 -0
- package/dist/settings/__tests__/write.test.d.ts.map +1 -0
- package/dist/settings/__tests__/write.test.js +61 -0
- package/dist/settings/__tests__/write.test.js.map +1 -0
- package/dist/settings/gate.d.ts +34 -0
- package/dist/settings/gate.d.ts.map +1 -0
- package/dist/settings/gate.js +50 -0
- package/dist/settings/gate.js.map +1 -0
- package/dist/settings/hooks.d.ts +26 -0
- package/dist/settings/hooks.d.ts.map +1 -0
- package/dist/settings/hooks.js +115 -0
- package/dist/settings/hooks.js.map +1 -0
- package/dist/settings/index.d.ts +23 -0
- package/dist/settings/index.d.ts.map +1 -0
- package/dist/settings/index.js +23 -0
- package/dist/settings/index.js.map +1 -0
- package/dist/settings/mcp-write.d.ts +41 -0
- package/dist/settings/mcp-write.d.ts.map +1 -0
- package/dist/settings/mcp-write.js +61 -0
- package/dist/settings/mcp-write.js.map +1 -0
- package/dist/settings/permissions-gate.d.ts +19 -0
- package/dist/settings/permissions-gate.d.ts.map +1 -0
- package/dist/settings/permissions-gate.js +103 -0
- package/dist/settings/permissions-gate.js.map +1 -0
- package/dist/settings/resolve.d.ts +37 -0
- package/dist/settings/resolve.d.ts.map +1 -0
- package/dist/settings/resolve.js +169 -0
- package/dist/settings/resolve.js.map +1 -0
- package/dist/settings/runtime.d.ts +28 -0
- package/dist/settings/runtime.d.ts.map +1 -0
- package/dist/settings/runtime.js +45 -0
- package/dist/settings/runtime.js.map +1 -0
- package/dist/settings/schema.d.ts +1387 -0
- package/dist/settings/schema.d.ts.map +1 -0
- package/dist/settings/schema.js +146 -0
- package/dist/settings/schema.js.map +1 -0
- package/dist/settings/write.d.ts +37 -0
- package/dist/settings/write.d.ts.map +1 -0
- package/dist/settings/write.js +85 -0
- package/dist/settings/write.js.map +1 -0
- package/dist/slash/__tests__/expand.test.d.ts +2 -0
- package/dist/slash/__tests__/expand.test.d.ts.map +1 -0
- package/dist/slash/__tests__/expand.test.js +44 -0
- package/dist/slash/__tests__/expand.test.js.map +1 -0
- package/dist/slash/__tests__/loader.test.d.ts +2 -0
- package/dist/slash/__tests__/loader.test.d.ts.map +1 -0
- package/dist/slash/__tests__/loader.test.js +48 -0
- package/dist/slash/__tests__/loader.test.js.map +1 -0
- package/dist/slash/expand.d.ts +32 -0
- package/dist/slash/expand.d.ts.map +1 -0
- package/dist/slash/expand.js +48 -0
- package/dist/slash/expand.js.map +1 -0
- package/dist/slash/index.d.ts +11 -0
- package/dist/slash/index.d.ts.map +1 -0
- package/dist/slash/index.js +4 -0
- package/dist/slash/index.js.map +1 -0
- package/dist/slash/loader.d.ts +10 -0
- package/dist/slash/loader.d.ts.map +1 -0
- package/dist/slash/loader.js +64 -0
- package/dist/slash/loader.js.map +1 -0
- package/dist/slash/types.d.ts +24 -0
- package/dist/slash/types.d.ts.map +1 -0
- package/dist/slash/types.js +11 -0
- package/dist/slash/types.js.map +1 -0
- package/dist/slash/write.d.ts +10 -0
- package/dist/slash/write.d.ts.map +1 -0
- package/dist/slash/write.js +26 -0
- package/dist/slash/write.js.map +1 -0
- package/dist/tui/__tests__/app.test.d.ts +2 -0
- package/dist/tui/__tests__/app.test.d.ts.map +1 -0
- package/dist/tui/__tests__/app.test.js +136 -0
- package/dist/tui/__tests__/app.test.js.map +1 -0
- package/dist/tui/__tests__/banner.test.d.ts +2 -0
- package/dist/tui/__tests__/banner.test.d.ts.map +1 -0
- package/dist/tui/__tests__/banner.test.js +15 -0
- package/dist/tui/__tests__/banner.test.js.map +1 -0
- package/dist/tui/__tests__/command-form.test.d.ts +2 -0
- package/dist/tui/__tests__/command-form.test.d.ts.map +1 -0
- package/dist/tui/__tests__/command-form.test.js +96 -0
- package/dist/tui/__tests__/command-form.test.js.map +1 -0
- package/dist/tui/__tests__/command-tree.test.d.ts +2 -0
- package/dist/tui/__tests__/command-tree.test.d.ts.map +1 -0
- package/dist/tui/__tests__/command-tree.test.js +55 -0
- package/dist/tui/__tests__/command-tree.test.js.map +1 -0
- package/dist/tui/__tests__/runner.test.d.ts +2 -0
- package/dist/tui/__tests__/runner.test.d.ts.map +1 -0
- package/dist/tui/__tests__/runner.test.js +38 -0
- package/dist/tui/__tests__/runner.test.js.map +1 -0
- package/dist/tui/__tests__/theme.test.d.ts +2 -0
- package/dist/tui/__tests__/theme.test.d.ts.map +1 -0
- package/dist/tui/__tests__/theme.test.js +11 -0
- package/dist/tui/__tests__/theme.test.js.map +1 -0
- package/dist/tui/agent-view/activity-feed.d.ts +3 -0
- package/dist/tui/agent-view/activity-feed.d.ts.map +1 -0
- package/dist/tui/agent-view/activity-feed.js +34 -0
- package/dist/tui/agent-view/activity-feed.js.map +1 -0
- package/dist/tui/agent-view/budget-bar.d.ts +3 -0
- package/dist/tui/agent-view/budget-bar.d.ts.map +1 -0
- package/dist/tui/agent-view/budget-bar.js +53 -0
- package/dist/tui/agent-view/budget-bar.js.map +1 -0
- package/dist/tui/agent-view/compile-panel.d.ts +3 -0
- package/dist/tui/agent-view/compile-panel.d.ts.map +1 -0
- package/dist/tui/agent-view/compile-panel.js +34 -0
- package/dist/tui/agent-view/compile-panel.js.map +1 -0
- package/dist/tui/agent-view/index.d.ts +4 -0
- package/dist/tui/agent-view/index.d.ts.map +1 -0
- package/dist/tui/agent-view/index.js +31 -0
- package/dist/tui/agent-view/index.js.map +1 -0
- package/dist/tui/agent-view/memory-panel.d.ts +3 -0
- package/dist/tui/agent-view/memory-panel.d.ts.map +1 -0
- package/dist/tui/agent-view/memory-panel.js +80 -0
- package/dist/tui/agent-view/memory-panel.js.map +1 -0
- package/dist/tui/agent-view/session-panel.d.ts +3 -0
- package/dist/tui/agent-view/session-panel.d.ts.map +1 -0
- package/dist/tui/agent-view/session-panel.js +44 -0
- package/dist/tui/agent-view/session-panel.js.map +1 -0
- package/dist/tui/agent-view/status-bar.d.ts +7 -0
- package/dist/tui/agent-view/status-bar.d.ts.map +1 -0
- package/dist/tui/agent-view/status-bar.js +22 -0
- package/dist/tui/agent-view/status-bar.js.map +1 -0
- package/dist/tui/app.d.ts +9 -0
- package/dist/tui/app.d.ts.map +1 -0
- package/dist/tui/app.js +115 -0
- package/dist/tui/app.js.map +1 -0
- package/dist/tui/banner.d.ts +5 -0
- package/dist/tui/banner.d.ts.map +1 -0
- package/dist/tui/banner.js +17 -0
- package/dist/tui/banner.js.map +1 -0
- package/dist/tui/command-form.d.ts +9 -0
- package/dist/tui/command-form.d.ts.map +1 -0
- package/dist/tui/command-form.js +76 -0
- package/dist/tui/command-form.js.map +1 -0
- package/dist/tui/command-tree.d.ts +30 -0
- package/dist/tui/command-tree.d.ts.map +1 -0
- package/dist/tui/command-tree.js +43 -0
- package/dist/tui/command-tree.js.map +1 -0
- package/dist/tui/fleet-view/agent-row.d.ts +10 -0
- package/dist/tui/fleet-view/agent-row.d.ts.map +1 -0
- package/dist/tui/fleet-view/agent-row.js +80 -0
- package/dist/tui/fleet-view/agent-row.js.map +1 -0
- package/dist/tui/fleet-view/dispatch-input.d.ts +5 -0
- package/dist/tui/fleet-view/dispatch-input.d.ts.map +1 -0
- package/dist/tui/fleet-view/dispatch-input.js +36 -0
- package/dist/tui/fleet-view/dispatch-input.js.map +1 -0
- package/dist/tui/fleet-view/fleet-app.d.ts +11 -0
- package/dist/tui/fleet-view/fleet-app.d.ts.map +1 -0
- package/dist/tui/fleet-view/fleet-app.js +95 -0
- package/dist/tui/fleet-view/fleet-app.js.map +1 -0
- package/dist/tui/fleet-view/fleet-summary.d.ts +6 -0
- package/dist/tui/fleet-view/fleet-summary.d.ts.map +1 -0
- package/dist/tui/fleet-view/fleet-summary.js +19 -0
- package/dist/tui/fleet-view/fleet-summary.js.map +1 -0
- package/dist/tui/fleet-view/index.d.ts +16 -0
- package/dist/tui/fleet-view/index.d.ts.map +1 -0
- package/dist/tui/fleet-view/index.js +65 -0
- package/dist/tui/fleet-view/index.js.map +1 -0
- package/dist/tui/runner.d.ts +7 -0
- package/dist/tui/runner.d.ts.map +1 -0
- package/dist/tui/runner.js +36 -0
- package/dist/tui/runner.js.map +1 -0
- package/dist/tui/theme.d.ts +8 -0
- package/dist/tui/theme.d.ts.map +1 -0
- package/dist/tui/theme.js +10 -0
- package/dist/tui/theme.js.map +1 -0
- package/package.json +16 -7
package/dist/commands.test.js
CHANGED
|
@@ -3,7 +3,11 @@ import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
|
3
3
|
vi.mock("./lib/config.js", () => ({
|
|
4
4
|
getToken: vi.fn(() => "test-token"),
|
|
5
5
|
getApiUrl: vi.fn(() => "http://localhost:4000"),
|
|
6
|
-
readConfig: vi.fn(() => ({
|
|
6
|
+
readConfig: vi.fn(() => ({
|
|
7
|
+
token: "test-token",
|
|
8
|
+
orgSlug: "my-org",
|
|
9
|
+
workspaceSlug: "default",
|
|
10
|
+
})),
|
|
7
11
|
writeConfig: vi.fn(),
|
|
8
12
|
clearConfig: vi.fn(),
|
|
9
13
|
getOrgId: vi.fn(() => "my-org"),
|
|
@@ -67,8 +71,6 @@ import { imageListCommand } from "./commands/image.list.js";
|
|
|
67
71
|
import { imageAnalyzeCommand } from "./commands/image.analyze.js";
|
|
68
72
|
import { documentListCommand } from "./commands/document.list.js";
|
|
69
73
|
import { documentReadCommand } from "./commands/document.read.js";
|
|
70
|
-
import { formCreateCommand } from "./commands/form.create.js";
|
|
71
|
-
import { formSubmitCommand } from "./commands/form.submit.js";
|
|
72
74
|
import { automationCreateCommand } from "./commands/automation.create.js";
|
|
73
75
|
import { automationEnableCommand } from "./commands/automation.enable.js";
|
|
74
76
|
import { automationDisableCommand } from "./commands/automation.disable.js";
|
|
@@ -94,7 +96,6 @@ import { agentTaskBackgroundReadCommand } from "./commands/agent.task.background
|
|
|
94
96
|
import { agentTaskBackgroundCancelCommand } from "./commands/agent.task.background.cancel.js";
|
|
95
97
|
import { assetUploadCommand } from "./commands/asset.upload.js";
|
|
96
98
|
import { billingSubscriptionUpgradeStartCommand } from "./commands/billing.subscription.upgrade.start.js";
|
|
97
|
-
import { brandkitApplyCommand } from "./commands/brandkit.apply.js";
|
|
98
99
|
import { conversationPurgeCommand } from "./commands/conversation.purge.js";
|
|
99
100
|
import { documentsPdfCreateCommand } from "./commands/documents.pdf.create.js";
|
|
100
101
|
import { formFillCommand } from "./commands/form.fill.js";
|
|
@@ -139,7 +140,9 @@ afterEach(() => {
|
|
|
139
140
|
describe("auth login", () => {
|
|
140
141
|
it("exits 1 if email or password is missing", async () => {
|
|
141
142
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
142
|
-
const exitSpy = vi.spyOn(process, "exit").mockImplementation(() => {
|
|
143
|
+
const exitSpy = vi.spyOn(process, "exit").mockImplementation(() => {
|
|
144
|
+
throw new Error("exit");
|
|
145
|
+
});
|
|
143
146
|
await expect(() => authLoginCommand.parseAsync(["node", "cli"])).rejects.toThrow("exit");
|
|
144
147
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("email and password are required"));
|
|
145
148
|
consoleSpy.mockRestore();
|
|
@@ -147,8 +150,18 @@ describe("auth login", () => {
|
|
|
147
150
|
});
|
|
148
151
|
it("calls API with credentials and stores token", async () => {
|
|
149
152
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
150
|
-
mockApiRequest.mockResolvedValueOnce({
|
|
151
|
-
|
|
153
|
+
mockApiRequest.mockResolvedValueOnce({
|
|
154
|
+
token: "new-token",
|
|
155
|
+
user: { email: "user@example.com" },
|
|
156
|
+
});
|
|
157
|
+
await authLoginCommand.parseAsync([
|
|
158
|
+
"node",
|
|
159
|
+
"cli",
|
|
160
|
+
"--email",
|
|
161
|
+
"user@example.com",
|
|
162
|
+
"--password",
|
|
163
|
+
"secret",
|
|
164
|
+
]);
|
|
152
165
|
expect(mockApiRequest).toHaveBeenCalledWith("/auth/sign-in/email", expect.objectContaining({ method: "POST" }));
|
|
153
166
|
expect(mockWriteConfig).toHaveBeenCalledWith(expect.objectContaining({ token: "new-token" }));
|
|
154
167
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("Authenticated"));
|
|
@@ -156,9 +169,18 @@ describe("auth login", () => {
|
|
|
156
169
|
});
|
|
157
170
|
it("exits 1 on API error during login", async () => {
|
|
158
171
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
159
|
-
const exitSpy = vi.spyOn(process, "exit").mockImplementation(() => {
|
|
172
|
+
const exitSpy = vi.spyOn(process, "exit").mockImplementation(() => {
|
|
173
|
+
throw new Error("exit");
|
|
174
|
+
});
|
|
160
175
|
mockApiRequest.mockRejectedValueOnce(new Error("Unauthorized"));
|
|
161
|
-
await expect(() => authLoginCommand.parseAsync([
|
|
176
|
+
await expect(() => authLoginCommand.parseAsync([
|
|
177
|
+
"node",
|
|
178
|
+
"cli",
|
|
179
|
+
"--email",
|
|
180
|
+
"a@b.com",
|
|
181
|
+
"--password",
|
|
182
|
+
"pw",
|
|
183
|
+
])).rejects.toThrow("exit");
|
|
162
184
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("Error:"));
|
|
163
185
|
consoleSpy.mockRestore();
|
|
164
186
|
exitSpy.mockRestore();
|
|
@@ -166,7 +188,14 @@ describe("auth login", () => {
|
|
|
166
188
|
it("handles response with session.token shape", async () => {
|
|
167
189
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
168
190
|
mockApiRequest.mockResolvedValueOnce({ session: { token: "session-tok" } });
|
|
169
|
-
await authLoginCommand.parseAsync([
|
|
191
|
+
await authLoginCommand.parseAsync([
|
|
192
|
+
"node",
|
|
193
|
+
"cli",
|
|
194
|
+
"-e",
|
|
195
|
+
"a@b.com",
|
|
196
|
+
"-p",
|
|
197
|
+
"pw",
|
|
198
|
+
]);
|
|
170
199
|
expect(mockWriteConfig).toHaveBeenCalledWith(expect.objectContaining({ token: "session-tok" }));
|
|
171
200
|
consoleSpy.mockRestore();
|
|
172
201
|
});
|
|
@@ -221,15 +250,22 @@ describe("auth whoami", () => {
|
|
|
221
250
|
});
|
|
222
251
|
it("falls back to config values for org/workspace", async () => {
|
|
223
252
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
224
|
-
mockApiRequest.mockResolvedValueOnce({
|
|
225
|
-
|
|
253
|
+
mockApiRequest.mockResolvedValueOnce({
|
|
254
|
+
user: { email: "mac@example.com" },
|
|
255
|
+
});
|
|
256
|
+
vi.mocked(config.readConfig).mockReturnValue({
|
|
257
|
+
orgSlug: "cfg-org",
|
|
258
|
+
workspaceSlug: "cfg-ws",
|
|
259
|
+
});
|
|
226
260
|
await authWhoamiCommand.parseAsync(["node", "cli"]);
|
|
227
261
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("cfg-org"));
|
|
228
262
|
consoleSpy.mockRestore();
|
|
229
263
|
});
|
|
230
264
|
it("exits 1 on API error", async () => {
|
|
231
265
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
232
|
-
const exitSpy = vi.spyOn(process, "exit").mockImplementation(() => {
|
|
266
|
+
const exitSpy = vi.spyOn(process, "exit").mockImplementation(() => {
|
|
267
|
+
throw new Error("exit");
|
|
268
|
+
});
|
|
233
269
|
mockApiRequest.mockRejectedValueOnce(new Error("Forbidden"));
|
|
234
270
|
await expect(() => authWhoamiCommand.parseAsync(["node", "cli"])).rejects.toThrow("exit");
|
|
235
271
|
consoleSpy.mockRestore();
|
|
@@ -259,7 +295,9 @@ describe("org list", () => {
|
|
|
259
295
|
});
|
|
260
296
|
it("handles data array shape from API", async () => {
|
|
261
297
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
262
|
-
mockApiRequest.mockResolvedValueOnce({
|
|
298
|
+
mockApiRequest.mockResolvedValueOnce({
|
|
299
|
+
data: [{ id: "id1", slug: "org-1", name: "Org 1" }],
|
|
300
|
+
});
|
|
263
301
|
await orgListCommand.parseAsync(["node", "cli"]);
|
|
264
302
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("org-1"));
|
|
265
303
|
consoleSpy.mockRestore();
|
|
@@ -271,7 +309,9 @@ describe("org list", () => {
|
|
|
271
309
|
describe("org create", () => {
|
|
272
310
|
it("creates org and prints slug", async () => {
|
|
273
311
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
274
|
-
mockApiRequest.mockResolvedValueOnce({
|
|
312
|
+
mockApiRequest.mockResolvedValueOnce({
|
|
313
|
+
organization: { slug: "new-org", name: "New Org" },
|
|
314
|
+
});
|
|
275
315
|
await orgCreateCommand.parseAsync(["node", "cli", "New Org"]);
|
|
276
316
|
expect(mockApiRequest).toHaveBeenCalledWith("/organizations", expect.objectContaining({ method: "POST" }));
|
|
277
317
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("new-org"));
|
|
@@ -279,7 +319,9 @@ describe("org create", () => {
|
|
|
279
319
|
});
|
|
280
320
|
it("exits 1 on API error", async () => {
|
|
281
321
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
282
|
-
const exitSpy = vi.spyOn(process, "exit").mockImplementation(() => {
|
|
322
|
+
const exitSpy = vi.spyOn(process, "exit").mockImplementation(() => {
|
|
323
|
+
throw new Error("exit");
|
|
324
|
+
});
|
|
283
325
|
mockApiRequest.mockRejectedValueOnce(new Error("Conflict"));
|
|
284
326
|
await expect(() => orgCreateCommand.parseAsync(["node", "cli", "Dup"])).rejects.toThrow("exit");
|
|
285
327
|
consoleSpy.mockRestore();
|
|
@@ -293,7 +335,13 @@ describe("org member add", () => {
|
|
|
293
335
|
it("adds member and confirms", async () => {
|
|
294
336
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
295
337
|
mockApiRequest.mockResolvedValueOnce({});
|
|
296
|
-
await orgMemberAddCommand.parseAsync([
|
|
338
|
+
await orgMemberAddCommand.parseAsync([
|
|
339
|
+
"node",
|
|
340
|
+
"cli",
|
|
341
|
+
"new@example.com",
|
|
342
|
+
"--role",
|
|
343
|
+
"admin",
|
|
344
|
+
]);
|
|
297
345
|
expect(mockApiRequest).toHaveBeenCalledWith("/org/members", expect.objectContaining({ method: "POST" }));
|
|
298
346
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("new@example.com"));
|
|
299
347
|
consoleSpy.mockRestore();
|
|
@@ -301,7 +349,13 @@ describe("org member add", () => {
|
|
|
301
349
|
it("defaults role to member when no --role flag given", async () => {
|
|
302
350
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
303
351
|
mockApiRequest.mockResolvedValueOnce({});
|
|
304
|
-
await orgMemberAddCommand.parseAsync([
|
|
352
|
+
await orgMemberAddCommand.parseAsync([
|
|
353
|
+
"node",
|
|
354
|
+
"cli",
|
|
355
|
+
"x@example.com",
|
|
356
|
+
"--role",
|
|
357
|
+
"member",
|
|
358
|
+
]);
|
|
305
359
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("member"));
|
|
306
360
|
consoleSpy.mockRestore();
|
|
307
361
|
});
|
|
@@ -348,7 +402,9 @@ describe("workspace list", () => {
|
|
|
348
402
|
describe("workspace create", () => {
|
|
349
403
|
it("creates workspace and prints slug", async () => {
|
|
350
404
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
351
|
-
mockApiRequest.mockResolvedValueOnce({
|
|
405
|
+
mockApiRequest.mockResolvedValueOnce({
|
|
406
|
+
workspace: { slug: "my-ws", name: "My WS" },
|
|
407
|
+
});
|
|
352
408
|
await workspaceCreateCommand.parseAsync(["node", "cli", "My WS"]);
|
|
353
409
|
expect(mockApiRequest).toHaveBeenCalledWith("/workspaces", expect.objectContaining({ method: "POST" }));
|
|
354
410
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("my-ws"));
|
|
@@ -364,7 +420,10 @@ function makeSseResponse(text) {
|
|
|
364
420
|
const line = `data: ${JSON.stringify({ type: "text", text })}\n\nevent: done\ndata: [DONE]\n\n`;
|
|
365
421
|
const encoder = new TextEncoder();
|
|
366
422
|
const stream = new ReadableStream({
|
|
367
|
-
start(c) {
|
|
423
|
+
start(c) {
|
|
424
|
+
c.enqueue(encoder.encode(line));
|
|
425
|
+
c.close();
|
|
426
|
+
},
|
|
368
427
|
});
|
|
369
428
|
return new Response(stream, {
|
|
370
429
|
status: 200,
|
|
@@ -378,9 +437,13 @@ function makeErrorResponse(status, message) {
|
|
|
378
437
|
});
|
|
379
438
|
}
|
|
380
439
|
describe("chat send", () => {
|
|
381
|
-
afterEach(() => {
|
|
440
|
+
afterEach(() => {
|
|
441
|
+
vi.restoreAllMocks();
|
|
442
|
+
});
|
|
382
443
|
it("sends message and streams response to stdout", async () => {
|
|
383
|
-
const stdoutSpy = vi
|
|
444
|
+
const stdoutSpy = vi
|
|
445
|
+
.spyOn(process.stdout, "write")
|
|
446
|
+
.mockImplementation(() => true);
|
|
384
447
|
vi.spyOn(global, "fetch").mockResolvedValueOnce(makeSseResponse("Hello back!"));
|
|
385
448
|
await chatSendCommand.parseAsync(["node", "cli", "hello"]);
|
|
386
449
|
const written = stdoutSpy.mock.calls.map((c) => String(c[0])).join("");
|
|
@@ -388,19 +451,29 @@ describe("chat send", () => {
|
|
|
388
451
|
stdoutSpy.mockRestore();
|
|
389
452
|
});
|
|
390
453
|
it("passes conversationId when --conversation is provided", async () => {
|
|
391
|
-
const stdoutSpy = vi
|
|
454
|
+
const stdoutSpy = vi
|
|
455
|
+
.spyOn(process.stdout, "write")
|
|
456
|
+
.mockImplementation(() => true);
|
|
392
457
|
let capturedBody = null;
|
|
393
458
|
vi.spyOn(global, "fetch").mockImplementationOnce(async (_url, init) => {
|
|
394
459
|
capturedBody = JSON.parse(init.body);
|
|
395
460
|
return makeSseResponse("ok");
|
|
396
461
|
});
|
|
397
|
-
await chatSendCommand.parseAsync([
|
|
462
|
+
await chatSendCommand.parseAsync([
|
|
463
|
+
"node",
|
|
464
|
+
"cli",
|
|
465
|
+
"hi",
|
|
466
|
+
"--conversation",
|
|
467
|
+
"cnv_abc",
|
|
468
|
+
]);
|
|
398
469
|
expect(capturedBody["conversationId"]).toBe("cnv_abc");
|
|
399
470
|
stdoutSpy.mockRestore();
|
|
400
471
|
});
|
|
401
472
|
it("exits 1 when fetch throws a network error", async () => {
|
|
402
473
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
403
|
-
const exitSpy = vi.spyOn(process, "exit").mockImplementation(() => {
|
|
474
|
+
const exitSpy = vi.spyOn(process, "exit").mockImplementation(() => {
|
|
475
|
+
throw new Error("exit");
|
|
476
|
+
});
|
|
404
477
|
vi.spyOn(global, "fetch").mockRejectedValueOnce(new Error("ECONNREFUSED"));
|
|
405
478
|
await expect(() => chatSendCommand.parseAsync(["node", "cli", "msg"])).rejects.toThrow("exit");
|
|
406
479
|
consoleSpy.mockRestore();
|
|
@@ -408,7 +481,9 @@ describe("chat send", () => {
|
|
|
408
481
|
});
|
|
409
482
|
it("exits 1 on non-ok HTTP response", async () => {
|
|
410
483
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
411
|
-
const exitSpy = vi.spyOn(process, "exit").mockImplementation(() => {
|
|
484
|
+
const exitSpy = vi.spyOn(process, "exit").mockImplementation(() => {
|
|
485
|
+
throw new Error("exit");
|
|
486
|
+
});
|
|
412
487
|
vi.spyOn(global, "fetch").mockResolvedValueOnce(makeErrorResponse(503, "Service unavailable"));
|
|
413
488
|
await expect(() => chatSendCommand.parseAsync(["node", "cli", "test"])).rejects.toThrow();
|
|
414
489
|
consoleSpy.mockRestore();
|
|
@@ -439,7 +514,14 @@ describe("conversation list", () => {
|
|
|
439
514
|
it("passes filter and limit params", async () => {
|
|
440
515
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
441
516
|
mockApiRequest.mockResolvedValueOnce({ conversations: [] });
|
|
442
|
-
await conversationListCommand.parseAsync([
|
|
517
|
+
await conversationListCommand.parseAsync([
|
|
518
|
+
"node",
|
|
519
|
+
"cli",
|
|
520
|
+
"--filter",
|
|
521
|
+
"archived",
|
|
522
|
+
"--limit",
|
|
523
|
+
"5",
|
|
524
|
+
]);
|
|
443
525
|
expect(mockApiRequest).toHaveBeenCalledWith(expect.stringContaining("archived"));
|
|
444
526
|
consoleSpy.mockRestore();
|
|
445
527
|
});
|
|
@@ -455,7 +537,9 @@ describe("conversation delete", () => {
|
|
|
455
537
|
});
|
|
456
538
|
it("exits 1 on not found", async () => {
|
|
457
539
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
458
|
-
const exitSpy = vi.spyOn(process, "exit").mockImplementation(() => {
|
|
540
|
+
const exitSpy = vi.spyOn(process, "exit").mockImplementation(() => {
|
|
541
|
+
throw new Error("exit");
|
|
542
|
+
});
|
|
459
543
|
mockApiRequest.mockRejectedValueOnce(new Error("Not found"));
|
|
460
544
|
await expect(() => conversationDeleteCommand.parseAsync(["node", "cli", "bad"])).rejects.toThrow("exit");
|
|
461
545
|
consoleSpy.mockRestore();
|
|
@@ -474,7 +558,12 @@ describe("conversation archive", () => {
|
|
|
474
558
|
it("unarchives when --unarchive flag is set", async () => {
|
|
475
559
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
476
560
|
mockApiRequest.mockResolvedValueOnce({});
|
|
477
|
-
await conversationArchiveCommand.parseAsync([
|
|
561
|
+
await conversationArchiveCommand.parseAsync([
|
|
562
|
+
"node",
|
|
563
|
+
"cli",
|
|
564
|
+
"cnv_abc",
|
|
565
|
+
"--unarchive",
|
|
566
|
+
]);
|
|
478
567
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("unarchived"));
|
|
479
568
|
consoleSpy.mockRestore();
|
|
480
569
|
});
|
|
@@ -483,7 +572,12 @@ describe("conversation rename", () => {
|
|
|
483
572
|
it("renames conversation", async () => {
|
|
484
573
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
485
574
|
mockApiRequest.mockResolvedValueOnce({});
|
|
486
|
-
await conversationRenameCommand.parseAsync([
|
|
575
|
+
await conversationRenameCommand.parseAsync([
|
|
576
|
+
"node",
|
|
577
|
+
"cli",
|
|
578
|
+
"cnv_abc",
|
|
579
|
+
"New Title",
|
|
580
|
+
]);
|
|
487
581
|
expect(mockApiRequest).toHaveBeenCalledWith("/conversations/cnv_abc/rename", expect.objectContaining({ method: "POST" }));
|
|
488
582
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("New Title"));
|
|
489
583
|
consoleSpy.mockRestore();
|
|
@@ -495,7 +589,10 @@ describe("conversation rename", () => {
|
|
|
495
589
|
describe("api-key create", () => {
|
|
496
590
|
it("creates API key and displays secret", async () => {
|
|
497
591
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
498
|
-
mockApiRequest.mockResolvedValueOnce({
|
|
592
|
+
mockApiRequest.mockResolvedValueOnce({
|
|
593
|
+
id: "key_123",
|
|
594
|
+
key: "oxk_abc123secret",
|
|
595
|
+
});
|
|
499
596
|
const origIsTTY = process.stdout.isTTY;
|
|
500
597
|
process.stdout.isTTY = true; // Simulate interactive TTY to show full secret
|
|
501
598
|
await apiKeyCreateCommand.parseAsync(["node", "cli", "my-key"]);
|
|
@@ -507,7 +604,9 @@ describe("api-key create", () => {
|
|
|
507
604
|
});
|
|
508
605
|
it("exits 1 on API error", async () => {
|
|
509
606
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
510
|
-
const exitSpy = vi.spyOn(process, "exit").mockImplementation(() => {
|
|
607
|
+
const exitSpy = vi.spyOn(process, "exit").mockImplementation(() => {
|
|
608
|
+
throw new Error("exit");
|
|
609
|
+
});
|
|
511
610
|
mockApiRequest.mockRejectedValueOnce(new Error("Quota exceeded"));
|
|
512
611
|
await expect(() => apiKeyCreateCommand.parseAsync(["node", "cli", "key"])).rejects.toThrow("exit");
|
|
513
612
|
consoleSpy.mockRestore();
|
|
@@ -533,7 +632,11 @@ describe("notifications list", () => {
|
|
|
533
632
|
mockApiRequest.mockResolvedValueOnce({
|
|
534
633
|
notifications: [
|
|
535
634
|
{ publicId: "ntf_1", title: "New member joined", readAt: null },
|
|
536
|
-
{
|
|
635
|
+
{
|
|
636
|
+
publicId: "ntf_2",
|
|
637
|
+
title: "Subscription renewed",
|
|
638
|
+
readAt: "2026-06-01",
|
|
639
|
+
},
|
|
537
640
|
],
|
|
538
641
|
});
|
|
539
642
|
await notificationsListCommand.parseAsync(["node", "cli"]);
|
|
@@ -568,7 +671,12 @@ describe("notifications mark", () => {
|
|
|
568
671
|
it("marks notification as unread with --unread flag", async () => {
|
|
569
672
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
570
673
|
mockApiRequest.mockResolvedValueOnce({});
|
|
571
|
-
await notificationsMarkCommand.parseAsync([
|
|
674
|
+
await notificationsMarkCommand.parseAsync([
|
|
675
|
+
"node",
|
|
676
|
+
"cli",
|
|
677
|
+
"ntf_1",
|
|
678
|
+
"--unread",
|
|
679
|
+
]);
|
|
572
680
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("unread"));
|
|
573
681
|
consoleSpy.mockRestore();
|
|
574
682
|
});
|
|
@@ -580,7 +688,10 @@ describe("plugin list", () => {
|
|
|
580
688
|
it("lists installed plugins", async () => {
|
|
581
689
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
582
690
|
mockApiRequest.mockResolvedValueOnce({
|
|
583
|
-
plugins: [
|
|
691
|
+
plugins: [
|
|
692
|
+
{ pluginId: "github", enabled: true },
|
|
693
|
+
{ pluginId: "slack", enabled: false },
|
|
694
|
+
],
|
|
584
695
|
});
|
|
585
696
|
await pluginListCommand.parseAsync(["node", "cli"]);
|
|
586
697
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("github"));
|
|
@@ -606,7 +717,9 @@ describe("plugin install", () => {
|
|
|
606
717
|
});
|
|
607
718
|
it("exits 1 on install failure", async () => {
|
|
608
719
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
609
|
-
const exitSpy = vi.spyOn(process, "exit").mockImplementation(() => {
|
|
720
|
+
const exitSpy = vi.spyOn(process, "exit").mockImplementation(() => {
|
|
721
|
+
throw new Error("exit");
|
|
722
|
+
});
|
|
610
723
|
mockApiRequest.mockRejectedValueOnce(new Error("Not found in catalog"));
|
|
611
724
|
await expect(() => pluginInstallCommand.parseAsync(["node", "cli", "bad-plugin"])).rejects.toThrow("exit");
|
|
612
725
|
consoleSpy.mockRestore();
|
|
@@ -652,7 +765,9 @@ describe("billing status", () => {
|
|
|
652
765
|
});
|
|
653
766
|
it("exits 1 on API error", async () => {
|
|
654
767
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
655
|
-
const exitSpy = vi.spyOn(process, "exit").mockImplementation(() => {
|
|
768
|
+
const exitSpy = vi.spyOn(process, "exit").mockImplementation(() => {
|
|
769
|
+
throw new Error("exit");
|
|
770
|
+
});
|
|
656
771
|
mockApiRequest.mockRejectedValueOnce(new Error("Forbidden"));
|
|
657
772
|
await expect(() => billingStatusCommand.parseAsync(["node", "cli"])).rejects.toThrow("exit");
|
|
658
773
|
consoleSpy.mockRestore();
|
|
@@ -681,7 +796,9 @@ describe("agent skill list", () => {
|
|
|
681
796
|
it("lists agent skills successfully", async () => {
|
|
682
797
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
683
798
|
mockApiRequest.mockResolvedValueOnce({
|
|
684
|
-
skills: [
|
|
799
|
+
skills: [
|
|
800
|
+
{ id: "skill1", name: "memory", description: "Memory management" },
|
|
801
|
+
],
|
|
685
802
|
});
|
|
686
803
|
await agentSkillListCommand.parseAsync(["node", "cli"]);
|
|
687
804
|
expect(mockApiRequest).toHaveBeenCalledWith(expect.stringContaining("/agent/skill/list"), expect.objectContaining({ method: "GET" }));
|
|
@@ -696,7 +813,9 @@ describe("agent tool list", () => {
|
|
|
696
813
|
it("lists agent tools successfully", async () => {
|
|
697
814
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
698
815
|
mockApiRequest.mockResolvedValueOnce({
|
|
699
|
-
tools: [
|
|
816
|
+
tools: [
|
|
817
|
+
{ id: "tool1", name: "search", description: "Search capability" },
|
|
818
|
+
],
|
|
700
819
|
});
|
|
701
820
|
await agentToolListCommand.parseAsync(["node", "cli"]);
|
|
702
821
|
expect(mockApiRequest).toHaveBeenCalledWith(expect.stringContaining("/agent/tool/list"), expect.objectContaining({ method: "GET" }));
|
|
@@ -714,7 +833,12 @@ describe("billing credits purchase", () => {
|
|
|
714
833
|
credits: 100,
|
|
715
834
|
totalCost: 10,
|
|
716
835
|
});
|
|
717
|
-
await billingCreditsPurchaseCommand.parseAsync([
|
|
836
|
+
await billingCreditsPurchaseCommand.parseAsync([
|
|
837
|
+
"node",
|
|
838
|
+
"cli",
|
|
839
|
+
"-a",
|
|
840
|
+
"100",
|
|
841
|
+
]);
|
|
718
842
|
expect(mockApiRequest).toHaveBeenCalledWith("/billing/credits/purchase", expect.objectContaining({ method: "POST" }));
|
|
719
843
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("Purchase initiated"));
|
|
720
844
|
consoleSpy.mockRestore();
|
|
@@ -762,7 +886,12 @@ describe("plugin org uninstall", () => {
|
|
|
762
886
|
id: "plugin1",
|
|
763
887
|
status: "uninstalled",
|
|
764
888
|
});
|
|
765
|
-
await pluginOrgUninstallCommand.parseAsync([
|
|
889
|
+
await pluginOrgUninstallCommand.parseAsync([
|
|
890
|
+
"node",
|
|
891
|
+
"cli",
|
|
892
|
+
"-p",
|
|
893
|
+
"plugin1",
|
|
894
|
+
]);
|
|
766
895
|
expect(mockApiRequest).toHaveBeenCalledWith("/plugin/org/uninstall", expect.objectContaining({ method: "POST" }));
|
|
767
896
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("Plugin uninstalled"));
|
|
768
897
|
consoleSpy.mockRestore();
|
|
@@ -775,7 +904,14 @@ describe("plugin catalog get", () => {
|
|
|
775
904
|
it("browses plugin catalog", async () => {
|
|
776
905
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
777
906
|
mockApiRequest.mockResolvedValueOnce({
|
|
778
|
-
plugins: [
|
|
907
|
+
plugins: [
|
|
908
|
+
{
|
|
909
|
+
id: "p1",
|
|
910
|
+
name: "github",
|
|
911
|
+
description: "GitHub integration",
|
|
912
|
+
category: "vcs",
|
|
913
|
+
},
|
|
914
|
+
],
|
|
779
915
|
});
|
|
780
916
|
await pluginCatalogGetCommand.parseAsync(["node", "cli"]);
|
|
781
917
|
expect(mockApiRequest).toHaveBeenCalledWith("/plugin/catalog/get?", expect.objectContaining({ method: "GET" }));
|
|
@@ -794,7 +930,14 @@ describe("org member role change", () => {
|
|
|
794
930
|
role: "admin",
|
|
795
931
|
updated: true,
|
|
796
932
|
});
|
|
797
|
-
await orgMemberRoleChangeCommand.parseAsync([
|
|
933
|
+
await orgMemberRoleChangeCommand.parseAsync([
|
|
934
|
+
"node",
|
|
935
|
+
"cli",
|
|
936
|
+
"-u",
|
|
937
|
+
"user1",
|
|
938
|
+
"-r",
|
|
939
|
+
"admin",
|
|
940
|
+
]);
|
|
798
941
|
expect(mockApiRequest).toHaveBeenCalledWith("/org/member/role-change", expect.objectContaining({ method: "POST" }));
|
|
799
942
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("Role updated"));
|
|
800
943
|
consoleSpy.mockRestore();
|
|
@@ -807,14 +950,30 @@ describe("agent approval resolve", () => {
|
|
|
807
950
|
it("resolves approval with approve decision", async () => {
|
|
808
951
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
809
952
|
mockApiRequest.mockResolvedValueOnce({ id: "apr1", status: "approved" });
|
|
810
|
-
await agentApprovalResolveCommand.parseAsync([
|
|
953
|
+
await agentApprovalResolveCommand.parseAsync([
|
|
954
|
+
"node",
|
|
955
|
+
"cli",
|
|
956
|
+
"-a",
|
|
957
|
+
"apr1",
|
|
958
|
+
"-d",
|
|
959
|
+
"approve",
|
|
960
|
+
]);
|
|
811
961
|
expect(mockApiRequest).toHaveBeenCalledWith("/agent/approval/resolve", expect.objectContaining({ method: "POST" }));
|
|
812
962
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("approved"));
|
|
813
963
|
consoleSpy.mockRestore();
|
|
814
964
|
});
|
|
815
965
|
it("rejects invalid decision", async () => {
|
|
816
|
-
const exitSpy = vi.spyOn(process, "exit").mockImplementation(() => {
|
|
817
|
-
|
|
966
|
+
const exitSpy = vi.spyOn(process, "exit").mockImplementation(() => {
|
|
967
|
+
throw new Error("exit");
|
|
968
|
+
});
|
|
969
|
+
await expect(() => agentApprovalResolveCommand.parseAsync([
|
|
970
|
+
"node",
|
|
971
|
+
"cli",
|
|
972
|
+
"-a",
|
|
973
|
+
"apr1",
|
|
974
|
+
"-d",
|
|
975
|
+
"invalid",
|
|
976
|
+
])).rejects.toThrow();
|
|
818
977
|
exitSpy.mockRestore();
|
|
819
978
|
});
|
|
820
979
|
});
|
|
@@ -824,8 +983,19 @@ describe("agent approval resolve", () => {
|
|
|
824
983
|
describe("archive create", () => {
|
|
825
984
|
it("creates archive from conversation", async () => {
|
|
826
985
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
827
|
-
mockApiRequest.mockResolvedValueOnce({
|
|
828
|
-
|
|
986
|
+
mockApiRequest.mockResolvedValueOnce({
|
|
987
|
+
id: "arc1",
|
|
988
|
+
name: "Archive 1",
|
|
989
|
+
status: "created",
|
|
990
|
+
});
|
|
991
|
+
await archiveCreateCommand.parseAsync([
|
|
992
|
+
"node",
|
|
993
|
+
"cli",
|
|
994
|
+
"-c",
|
|
995
|
+
"conv1",
|
|
996
|
+
"-n",
|
|
997
|
+
"My Archive",
|
|
998
|
+
]);
|
|
829
999
|
expect(mockApiRequest).toHaveBeenCalledWith("/archive/create", expect.objectContaining({ method: "POST" }));
|
|
830
1000
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("Archive created"));
|
|
831
1001
|
consoleSpy.mockRestore();
|
|
@@ -838,7 +1008,14 @@ describe("workflow run", () => {
|
|
|
838
1008
|
it("runs workflow with input", async () => {
|
|
839
1009
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
840
1010
|
mockApiRequest.mockResolvedValueOnce({ id: "run1", status: "started" });
|
|
841
|
-
await workflowRunCommand.parseAsync([
|
|
1011
|
+
await workflowRunCommand.parseAsync([
|
|
1012
|
+
"node",
|
|
1013
|
+
"cli",
|
|
1014
|
+
"-w",
|
|
1015
|
+
"wf1",
|
|
1016
|
+
"--input",
|
|
1017
|
+
'{"key":"value"}',
|
|
1018
|
+
]);
|
|
842
1019
|
expect(mockApiRequest).toHaveBeenCalledWith("/workflow/run", expect.objectContaining({ method: "POST" }));
|
|
843
1020
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("started"));
|
|
844
1021
|
consoleSpy.mockRestore();
|
|
@@ -861,7 +1038,12 @@ describe("user preferences update", () => {
|
|
|
861
1038
|
it("updates user preferences", async () => {
|
|
862
1039
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
863
1040
|
mockApiRequest.mockResolvedValueOnce({ theme: "light" });
|
|
864
|
-
await userPreferencesUpdateCommand.parseAsync([
|
|
1041
|
+
await userPreferencesUpdateCommand.parseAsync([
|
|
1042
|
+
"node",
|
|
1043
|
+
"cli",
|
|
1044
|
+
"-t",
|
|
1045
|
+
"light",
|
|
1046
|
+
]);
|
|
865
1047
|
expect(mockApiRequest).toHaveBeenCalledWith("/user/preferences/update", expect.objectContaining({ method: "POST" }));
|
|
866
1048
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("light"));
|
|
867
1049
|
consoleSpy.mockRestore();
|
|
@@ -873,7 +1055,14 @@ describe("user preferences update", () => {
|
|
|
873
1055
|
describe("workspace member list", () => {
|
|
874
1056
|
it("lists workspace members", async () => {
|
|
875
1057
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
876
|
-
mockApiRequest.mockResolvedValueOnce([
|
|
1058
|
+
mockApiRequest.mockResolvedValueOnce([
|
|
1059
|
+
{
|
|
1060
|
+
id: "m1",
|
|
1061
|
+
email: "user@example.com",
|
|
1062
|
+
role: "member",
|
|
1063
|
+
joined_at: "2026-06-08",
|
|
1064
|
+
},
|
|
1065
|
+
]);
|
|
877
1066
|
await workspaceMemberListCommand.parseAsync(["node", "cli"]);
|
|
878
1067
|
expect(mockApiRequest).toHaveBeenCalled();
|
|
879
1068
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("member(s)"));
|
|
@@ -884,7 +1073,12 @@ describe("workspace invite send", () => {
|
|
|
884
1073
|
it("sends workspace invitation", async () => {
|
|
885
1074
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
886
1075
|
mockApiRequest.mockResolvedValueOnce({ id: "inv1", status: "sent" });
|
|
887
|
-
await workspaceInviteSendCommand.parseAsync([
|
|
1076
|
+
await workspaceInviteSendCommand.parseAsync([
|
|
1077
|
+
"node",
|
|
1078
|
+
"cli",
|
|
1079
|
+
"-e",
|
|
1080
|
+
"user@example.com",
|
|
1081
|
+
]);
|
|
888
1082
|
expect(mockApiRequest).toHaveBeenCalledWith("/workspace/invite/send", expect.objectContaining({ method: "POST" }));
|
|
889
1083
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("Invitation sent"));
|
|
890
1084
|
consoleSpy.mockRestore();
|
|
@@ -896,8 +1090,18 @@ describe("workspace invite send", () => {
|
|
|
896
1090
|
describe("conversation chat", () => {
|
|
897
1091
|
it("sends chat message", async () => {
|
|
898
1092
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
899
|
-
mockApiRequest.mockResolvedValueOnce({
|
|
900
|
-
|
|
1093
|
+
mockApiRequest.mockResolvedValueOnce({
|
|
1094
|
+
id: "msg1",
|
|
1095
|
+
created_at: "2026-06-08T00:00:00Z",
|
|
1096
|
+
});
|
|
1097
|
+
await conversationChatCommand.parseAsync([
|
|
1098
|
+
"node",
|
|
1099
|
+
"cli",
|
|
1100
|
+
"-c",
|
|
1101
|
+
"conv1",
|
|
1102
|
+
"-m",
|
|
1103
|
+
"Hello",
|
|
1104
|
+
]);
|
|
901
1105
|
expect(mockApiRequest).toHaveBeenCalledWith("/conversation/chat", expect.objectContaining({ method: "POST" }));
|
|
902
1106
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("Message sent"));
|
|
903
1107
|
consoleSpy.mockRestore();
|
|
@@ -909,7 +1113,10 @@ describe("conversation chat", () => {
|
|
|
909
1113
|
describe("image create", () => {
|
|
910
1114
|
it("creates image from prompt", async () => {
|
|
911
1115
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
912
|
-
mockApiRequest.mockResolvedValueOnce({
|
|
1116
|
+
mockApiRequest.mockResolvedValueOnce({
|
|
1117
|
+
id: "img1",
|
|
1118
|
+
url: "https://example.com/img1.jpg",
|
|
1119
|
+
});
|
|
913
1120
|
await imageCreateCommand.parseAsync(["node", "cli", "-p", "A blue sky"]);
|
|
914
1121
|
expect(mockApiRequest).toHaveBeenCalledWith("/image/create", expect.objectContaining({ method: "POST" }));
|
|
915
1122
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("Image created"));
|
|
@@ -919,7 +1126,16 @@ describe("image create", () => {
|
|
|
919
1126
|
describe("image list", () => {
|
|
920
1127
|
it("lists images", async () => {
|
|
921
1128
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
922
|
-
mockApiRequest.mockResolvedValueOnce({
|
|
1129
|
+
mockApiRequest.mockResolvedValueOnce({
|
|
1130
|
+
images: [
|
|
1131
|
+
{
|
|
1132
|
+
id: "img1",
|
|
1133
|
+
url: "https://example.com/img1.jpg",
|
|
1134
|
+
prompt: "Blue sky",
|
|
1135
|
+
created_at: "2026-06-08",
|
|
1136
|
+
},
|
|
1137
|
+
],
|
|
1138
|
+
});
|
|
923
1139
|
await imageListCommand.parseAsync(["node", "cli"]);
|
|
924
1140
|
expect(mockApiRequest).toHaveBeenCalled();
|
|
925
1141
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("Images"));
|
|
@@ -929,7 +1145,10 @@ describe("image list", () => {
|
|
|
929
1145
|
describe("image analyze", () => {
|
|
930
1146
|
it("analyzes image", async () => {
|
|
931
1147
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
932
|
-
mockApiRequest.mockResolvedValueOnce({
|
|
1148
|
+
mockApiRequest.mockResolvedValueOnce({
|
|
1149
|
+
analysis: "sky",
|
|
1150
|
+
tags: ["nature", "outdoor"],
|
|
1151
|
+
});
|
|
933
1152
|
await imageAnalyzeCommand.parseAsync(["node", "cli", "-i", "img1"]);
|
|
934
1153
|
expect(mockApiRequest).toHaveBeenCalledWith("/image/analyze", expect.objectContaining({ method: "POST" }));
|
|
935
1154
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("Analysis"));
|
|
@@ -952,7 +1171,17 @@ describe("document create", () => {
|
|
|
952
1171
|
describe("document list", () => {
|
|
953
1172
|
it("lists documents", async () => {
|
|
954
1173
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
955
|
-
mockApiRequest.mockResolvedValueOnce({
|
|
1174
|
+
mockApiRequest.mockResolvedValueOnce({
|
|
1175
|
+
documents: [
|
|
1176
|
+
{
|
|
1177
|
+
id: "doc1",
|
|
1178
|
+
title: "Doc 1",
|
|
1179
|
+
created_at: "2026-06-08",
|
|
1180
|
+
updated_at: "2026-06-08",
|
|
1181
|
+
author: "user",
|
|
1182
|
+
},
|
|
1183
|
+
],
|
|
1184
|
+
});
|
|
956
1185
|
await documentListCommand.parseAsync(["node", "cli"]);
|
|
957
1186
|
expect(mockApiRequest).toHaveBeenCalled();
|
|
958
1187
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("Documents"));
|
|
@@ -962,7 +1191,12 @@ describe("document list", () => {
|
|
|
962
1191
|
describe("document read", () => {
|
|
963
1192
|
it("reads document", async () => {
|
|
964
1193
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
965
|
-
mockApiRequest.mockResolvedValueOnce({
|
|
1194
|
+
mockApiRequest.mockResolvedValueOnce({
|
|
1195
|
+
title: "Doc 1",
|
|
1196
|
+
content: "Content...",
|
|
1197
|
+
metadata: {},
|
|
1198
|
+
created_at: "2026-06-08",
|
|
1199
|
+
});
|
|
966
1200
|
await documentReadCommand.parseAsync(["node", "cli", "-d", "doc1"]);
|
|
967
1201
|
expect(mockApiRequest).toHaveBeenCalled();
|
|
968
1202
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("Title:"));
|
|
@@ -970,35 +1204,14 @@ describe("document read", () => {
|
|
|
970
1204
|
});
|
|
971
1205
|
});
|
|
972
1206
|
// ---------------------------------------------------------------------------
|
|
973
|
-
// form management
|
|
974
|
-
// ---------------------------------------------------------------------------
|
|
975
|
-
describe("form create", () => {
|
|
976
|
-
it("creates form", async () => {
|
|
977
|
-
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
978
|
-
mockApiRequest.mockResolvedValueOnce({ id: "form1", title: "Survey" });
|
|
979
|
-
await formCreateCommand.parseAsync(["node", "cli", "-t", "Survey"]);
|
|
980
|
-
expect(mockApiRequest).toHaveBeenCalledWith("/form/create", expect.objectContaining({ method: "POST" }));
|
|
981
|
-
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("Form created"));
|
|
982
|
-
consoleSpy.mockRestore();
|
|
983
|
-
});
|
|
984
|
-
});
|
|
985
|
-
describe("form submit", () => {
|
|
986
|
-
it("submits form", async () => {
|
|
987
|
-
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
988
|
-
mockApiRequest.mockResolvedValueOnce({ id: "sub1", status: "submitted" });
|
|
989
|
-
await formSubmitCommand.parseAsync(["node", "cli", "-f", "form1"]);
|
|
990
|
-
expect(mockApiRequest).toHaveBeenCalledWith("/form/submit", expect.objectContaining({ method: "POST" }));
|
|
991
|
-
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("submitted"));
|
|
992
|
-
consoleSpy.mockRestore();
|
|
993
|
-
});
|
|
994
|
-
});
|
|
995
|
-
// ---------------------------------------------------------------------------
|
|
996
1207
|
// automation management
|
|
997
1208
|
// ---------------------------------------------------------------------------
|
|
998
1209
|
describe("automation list", () => {
|
|
999
1210
|
it("lists automations", async () => {
|
|
1000
1211
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
1001
|
-
mockApiRequest.mockResolvedValueOnce([
|
|
1212
|
+
mockApiRequest.mockResolvedValueOnce([
|
|
1213
|
+
{ id: "auto1", name: "Auto 1", status: "active", triggers: ["event1"] },
|
|
1214
|
+
]);
|
|
1002
1215
|
await automationListCommand.parseAsync(["node", "cli"]);
|
|
1003
1216
|
expect(mockApiRequest).toHaveBeenCalled();
|
|
1004
1217
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("automation(s)"));
|
|
@@ -1016,7 +1229,12 @@ describe("automation create", () => {
|
|
|
1016
1229
|
triggerType: "api",
|
|
1017
1230
|
enabled: false,
|
|
1018
1231
|
});
|
|
1019
|
-
await automationCreateCommand.parseAsync([
|
|
1232
|
+
await automationCreateCommand.parseAsync([
|
|
1233
|
+
"node",
|
|
1234
|
+
"cli",
|
|
1235
|
+
"-n",
|
|
1236
|
+
"My Automation",
|
|
1237
|
+
]);
|
|
1020
1238
|
expect(mockApiRequest).toHaveBeenCalledWith("/automation/create", expect.objectContaining({ method: "POST" }));
|
|
1021
1239
|
const body = JSON.parse((mockApiRequest.mock.calls[0]?.[1]).body);
|
|
1022
1240
|
expect(body).toMatchObject({
|
|
@@ -1040,12 +1258,18 @@ describe("automation create", () => {
|
|
|
1040
1258
|
enabled: true,
|
|
1041
1259
|
});
|
|
1042
1260
|
await automationCreateCommand.parseAsync([
|
|
1043
|
-
"node",
|
|
1044
|
-
"
|
|
1045
|
-
"
|
|
1046
|
-
"
|
|
1047
|
-
"--
|
|
1048
|
-
"
|
|
1261
|
+
"node",
|
|
1262
|
+
"cli",
|
|
1263
|
+
"-n",
|
|
1264
|
+
"Watcher",
|
|
1265
|
+
"--trigger-type",
|
|
1266
|
+
"event",
|
|
1267
|
+
"--entity-type",
|
|
1268
|
+
"Contact",
|
|
1269
|
+
"--event-type",
|
|
1270
|
+
"node.updated",
|
|
1271
|
+
"--conditions",
|
|
1272
|
+
'[{"property":"status","toValue":"customer","operator":"eq"}]',
|
|
1049
1273
|
"--enabled",
|
|
1050
1274
|
]);
|
|
1051
1275
|
const body = JSON.parse((mockApiRequest.mock.calls[0]?.[1]).body);
|
|
@@ -1055,7 +1279,9 @@ describe("automation create", () => {
|
|
|
1055
1279
|
triggerConfig: {
|
|
1056
1280
|
entityType: "Contact",
|
|
1057
1281
|
eventType: "node.updated",
|
|
1058
|
-
propertyConditions: [
|
|
1282
|
+
propertyConditions: [
|
|
1283
|
+
{ property: "status", toValue: "customer", operator: "eq" },
|
|
1284
|
+
],
|
|
1059
1285
|
},
|
|
1060
1286
|
enabled: true,
|
|
1061
1287
|
});
|
|
@@ -1072,16 +1298,24 @@ describe("automation create", () => {
|
|
|
1072
1298
|
enabled: false,
|
|
1073
1299
|
});
|
|
1074
1300
|
await automationCreateCommand.parseAsync([
|
|
1075
|
-
"node",
|
|
1076
|
-
"
|
|
1077
|
-
"
|
|
1078
|
-
"
|
|
1079
|
-
"--
|
|
1301
|
+
"node",
|
|
1302
|
+
"cli",
|
|
1303
|
+
"-n",
|
|
1304
|
+
"Report",
|
|
1305
|
+
"--trigger-type",
|
|
1306
|
+
"schedule",
|
|
1307
|
+
"--cron",
|
|
1308
|
+
"0 9 * * 1",
|
|
1309
|
+
"--timezone",
|
|
1310
|
+
"America/New_York",
|
|
1080
1311
|
]);
|
|
1081
1312
|
const body = JSON.parse((mockApiRequest.mock.calls[0]?.[1]).body);
|
|
1082
1313
|
expect(body).toMatchObject({
|
|
1083
1314
|
triggerType: "schedule",
|
|
1084
|
-
triggerConfig: {
|
|
1315
|
+
triggerConfig: {
|
|
1316
|
+
cronExpression: "0 9 * * 1",
|
|
1317
|
+
timezone: "America/New_York",
|
|
1318
|
+
},
|
|
1085
1319
|
});
|
|
1086
1320
|
consoleSpy.mockRestore();
|
|
1087
1321
|
});
|
|
@@ -1089,7 +1323,11 @@ describe("automation create", () => {
|
|
|
1089
1323
|
describe("automation enable", () => {
|
|
1090
1324
|
it("enables automation", async () => {
|
|
1091
1325
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
1092
|
-
mockApiRequest.mockResolvedValueOnce({
|
|
1326
|
+
mockApiRequest.mockResolvedValueOnce({
|
|
1327
|
+
automation_id: "plt_1",
|
|
1328
|
+
enabled: true,
|
|
1329
|
+
status: "active",
|
|
1330
|
+
});
|
|
1093
1331
|
await automationEnableCommand.parseAsync(["node", "cli", "plt_1"]);
|
|
1094
1332
|
expect(mockApiRequest).toHaveBeenCalledWith("/automation/enable", expect.objectContaining({ method: "POST" }));
|
|
1095
1333
|
const body = JSON.parse((mockApiRequest.mock.calls[0]?.[1]).body);
|
|
@@ -1101,7 +1339,11 @@ describe("automation enable", () => {
|
|
|
1101
1339
|
describe("automation disable", () => {
|
|
1102
1340
|
it("disables automation", async () => {
|
|
1103
1341
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
1104
|
-
mockApiRequest.mockResolvedValueOnce({
|
|
1342
|
+
mockApiRequest.mockResolvedValueOnce({
|
|
1343
|
+
automation_id: "plt_1",
|
|
1344
|
+
enabled: false,
|
|
1345
|
+
status: "paused",
|
|
1346
|
+
});
|
|
1105
1347
|
await automationDisableCommand.parseAsync(["node", "cli", "plt_1"]);
|
|
1106
1348
|
expect(mockApiRequest).toHaveBeenCalledWith("/automation/disable", expect.objectContaining({ method: "POST" }));
|
|
1107
1349
|
const body = JSON.parse((mockApiRequest.mock.calls[0]?.[1]).body);
|
|
@@ -1126,7 +1368,16 @@ describe("automation trigger", () => {
|
|
|
1126
1368
|
describe("skill workspace list", () => {
|
|
1127
1369
|
it("lists workspace skills", async () => {
|
|
1128
1370
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
1129
|
-
mockApiRequest.mockResolvedValueOnce({
|
|
1371
|
+
mockApiRequest.mockResolvedValueOnce({
|
|
1372
|
+
skills: [
|
|
1373
|
+
{
|
|
1374
|
+
id: "skill1",
|
|
1375
|
+
name: "Research",
|
|
1376
|
+
enabled: true,
|
|
1377
|
+
description: "Research skill",
|
|
1378
|
+
},
|
|
1379
|
+
],
|
|
1380
|
+
});
|
|
1130
1381
|
await skillWorkspaceListCommand.parseAsync(["node", "cli"]);
|
|
1131
1382
|
expect(mockApiRequest).toHaveBeenCalled();
|
|
1132
1383
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("Workspace skills"));
|
|
@@ -1139,18 +1390,40 @@ describe("skill workspace list", () => {
|
|
|
1139
1390
|
describe("agent memory recall", () => {
|
|
1140
1391
|
it("recalls memory observations", async () => {
|
|
1141
1392
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
1142
|
-
const mockResult = {
|
|
1393
|
+
const mockResult = {
|
|
1394
|
+
observations: [
|
|
1395
|
+
{ id: "obs1", text: "User prefers dark mode", score: 0.9 },
|
|
1396
|
+
],
|
|
1397
|
+
};
|
|
1143
1398
|
mockApiRequest.mockResolvedValueOnce(mockResult);
|
|
1144
|
-
await agentMemoryRecallCommand.parseAsync([
|
|
1399
|
+
await agentMemoryRecallCommand.parseAsync([
|
|
1400
|
+
"node",
|
|
1401
|
+
"cli",
|
|
1402
|
+
"-a",
|
|
1403
|
+
"agent1",
|
|
1404
|
+
"-q",
|
|
1405
|
+
"user preferences",
|
|
1406
|
+
]);
|
|
1145
1407
|
expect(mockApiRequest).toHaveBeenCalledWith("/agent/memory/recall", expect.objectContaining({ method: "POST" }));
|
|
1146
1408
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("obs1"));
|
|
1147
1409
|
consoleSpy.mockRestore();
|
|
1148
1410
|
});
|
|
1149
1411
|
it("handles recall failure", async () => {
|
|
1150
1412
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
1151
|
-
const exitSpy = vi
|
|
1413
|
+
const exitSpy = vi
|
|
1414
|
+
.spyOn(process, "exit")
|
|
1415
|
+
.mockImplementation((_code) => {
|
|
1416
|
+
throw new Error("process.exit");
|
|
1417
|
+
});
|
|
1152
1418
|
mockApiRequest.mockRejectedValueOnce(new Error("Network error"));
|
|
1153
|
-
await expect(agentMemoryRecallCommand.parseAsync([
|
|
1419
|
+
await expect(agentMemoryRecallCommand.parseAsync([
|
|
1420
|
+
"node",
|
|
1421
|
+
"cli",
|
|
1422
|
+
"-a",
|
|
1423
|
+
"agent1",
|
|
1424
|
+
"-q",
|
|
1425
|
+
"query",
|
|
1426
|
+
])).rejects.toThrow();
|
|
1154
1427
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("Failed to recall"), expect.any(Error));
|
|
1155
1428
|
consoleSpy.mockRestore();
|
|
1156
1429
|
exitSpy.mockRestore();
|
|
@@ -1161,7 +1434,14 @@ describe("agent memory write", () => {
|
|
|
1161
1434
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
1162
1435
|
const mockResult = { id: "obs2", status: "stored" };
|
|
1163
1436
|
mockApiRequest.mockResolvedValueOnce(mockResult);
|
|
1164
|
-
await agentMemoryWriteCommand.parseAsync([
|
|
1437
|
+
await agentMemoryWriteCommand.parseAsync([
|
|
1438
|
+
"node",
|
|
1439
|
+
"cli",
|
|
1440
|
+
"-a",
|
|
1441
|
+
"agent1",
|
|
1442
|
+
"-t",
|
|
1443
|
+
"User prefers TypeScript",
|
|
1444
|
+
]);
|
|
1165
1445
|
expect(mockApiRequest).toHaveBeenCalledWith("/agent/memory/write", expect.objectContaining({ method: "POST" }));
|
|
1166
1446
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("obs2"));
|
|
1167
1447
|
consoleSpy.mockRestore();
|
|
@@ -1169,16 +1449,36 @@ describe("agent memory write", () => {
|
|
|
1169
1449
|
it("writes a memory observation with tags", async () => {
|
|
1170
1450
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
1171
1451
|
mockApiRequest.mockResolvedValueOnce({ id: "obs3", status: "stored" });
|
|
1172
|
-
await agentMemoryWriteCommand.parseAsync([
|
|
1452
|
+
await agentMemoryWriteCommand.parseAsync([
|
|
1453
|
+
"node",
|
|
1454
|
+
"cli",
|
|
1455
|
+
"-a",
|
|
1456
|
+
"agent1",
|
|
1457
|
+
"-t",
|
|
1458
|
+
"Uses dark mode",
|
|
1459
|
+
"--tags",
|
|
1460
|
+
"ui,preferences",
|
|
1461
|
+
]);
|
|
1173
1462
|
const callBody = JSON.parse(mockApiRequest.mock.calls[0][1].body);
|
|
1174
1463
|
expect(callBody.tags).toEqual(["ui", "preferences"]);
|
|
1175
1464
|
consoleSpy.mockRestore();
|
|
1176
1465
|
});
|
|
1177
1466
|
it("handles write failure", async () => {
|
|
1178
1467
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
1179
|
-
const exitSpy = vi
|
|
1468
|
+
const exitSpy = vi
|
|
1469
|
+
.spyOn(process, "exit")
|
|
1470
|
+
.mockImplementation((_code) => {
|
|
1471
|
+
throw new Error("process.exit");
|
|
1472
|
+
});
|
|
1180
1473
|
mockApiRequest.mockRejectedValueOnce(new Error("Network error"));
|
|
1181
|
-
await expect(agentMemoryWriteCommand.parseAsync([
|
|
1474
|
+
await expect(agentMemoryWriteCommand.parseAsync([
|
|
1475
|
+
"node",
|
|
1476
|
+
"cli",
|
|
1477
|
+
"-a",
|
|
1478
|
+
"agent1",
|
|
1479
|
+
"-t",
|
|
1480
|
+
"text",
|
|
1481
|
+
])).rejects.toThrow();
|
|
1182
1482
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("Failed to write"), expect.any(Error));
|
|
1183
1483
|
consoleSpy.mockRestore();
|
|
1184
1484
|
exitSpy.mockRestore();
|
|
@@ -1190,26 +1490,59 @@ describe("agent memory write", () => {
|
|
|
1190
1490
|
describe("documents generate", () => {
|
|
1191
1491
|
it("generates a document from template", async () => {
|
|
1192
1492
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
1193
|
-
const mockResult = {
|
|
1493
|
+
const mockResult = {
|
|
1494
|
+
id: "doc1",
|
|
1495
|
+
status: "complete",
|
|
1496
|
+
url: "https://example.com/doc.pdf",
|
|
1497
|
+
};
|
|
1194
1498
|
mockApiRequest.mockResolvedValueOnce(mockResult);
|
|
1195
|
-
await documentsGenerateCommand.parseAsync([
|
|
1499
|
+
await documentsGenerateCommand.parseAsync([
|
|
1500
|
+
"node",
|
|
1501
|
+
"cli",
|
|
1502
|
+
"-t",
|
|
1503
|
+
"report",
|
|
1504
|
+
"-c",
|
|
1505
|
+
'{"title":"Q1 Report"}',
|
|
1506
|
+
]);
|
|
1196
1507
|
expect(mockApiRequest).toHaveBeenCalledWith("/documents/generate", expect.objectContaining({ method: "POST" }));
|
|
1197
1508
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("doc1"));
|
|
1198
1509
|
consoleSpy.mockRestore();
|
|
1199
1510
|
});
|
|
1200
1511
|
it("fails on invalid JSON context", async () => {
|
|
1201
1512
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
1202
|
-
const exitSpy = vi
|
|
1203
|
-
|
|
1513
|
+
const exitSpy = vi
|
|
1514
|
+
.spyOn(process, "exit")
|
|
1515
|
+
.mockImplementation((_code) => {
|
|
1516
|
+
throw new Error("process.exit");
|
|
1517
|
+
});
|
|
1518
|
+
await expect(documentsGenerateCommand.parseAsync([
|
|
1519
|
+
"node",
|
|
1520
|
+
"cli",
|
|
1521
|
+
"-t",
|
|
1522
|
+
"report",
|
|
1523
|
+
"-c",
|
|
1524
|
+
"not-json",
|
|
1525
|
+
])).rejects.toThrow();
|
|
1204
1526
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("Invalid JSON"), expect.anything());
|
|
1205
1527
|
consoleSpy.mockRestore();
|
|
1206
1528
|
exitSpy.mockRestore();
|
|
1207
1529
|
});
|
|
1208
1530
|
it("handles generate failure", async () => {
|
|
1209
1531
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
1210
|
-
const exitSpy = vi
|
|
1532
|
+
const exitSpy = vi
|
|
1533
|
+
.spyOn(process, "exit")
|
|
1534
|
+
.mockImplementation((_code) => {
|
|
1535
|
+
throw new Error("process.exit");
|
|
1536
|
+
});
|
|
1211
1537
|
mockApiRequest.mockRejectedValueOnce(new Error("Template not found"));
|
|
1212
|
-
await expect(documentsGenerateCommand.parseAsync([
|
|
1538
|
+
await expect(documentsGenerateCommand.parseAsync([
|
|
1539
|
+
"node",
|
|
1540
|
+
"cli",
|
|
1541
|
+
"-t",
|
|
1542
|
+
"report",
|
|
1543
|
+
"-c",
|
|
1544
|
+
"{}",
|
|
1545
|
+
])).rejects.toThrow();
|
|
1213
1546
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("Failed to generate"), expect.any(Error));
|
|
1214
1547
|
consoleSpy.mockRestore();
|
|
1215
1548
|
exitSpy.mockRestore();
|
|
@@ -1223,14 +1556,23 @@ describe("image generate", () => {
|
|
|
1223
1556
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
1224
1557
|
const mockResult = { url: "https://example.com/img.png", id: "img1" };
|
|
1225
1558
|
mockApiRequest.mockResolvedValueOnce(mockResult);
|
|
1226
|
-
await imageGenerateCommand.parseAsync([
|
|
1559
|
+
await imageGenerateCommand.parseAsync([
|
|
1560
|
+
"node",
|
|
1561
|
+
"cli",
|
|
1562
|
+
"-p",
|
|
1563
|
+
"A sunset over the ocean",
|
|
1564
|
+
]);
|
|
1227
1565
|
expect(mockApiRequest).toHaveBeenCalledWith("/image/generate", expect.objectContaining({ method: "POST" }));
|
|
1228
1566
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("img1"));
|
|
1229
1567
|
consoleSpy.mockRestore();
|
|
1230
1568
|
});
|
|
1231
1569
|
it("handles generate failure", async () => {
|
|
1232
1570
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
1233
|
-
const exitSpy = vi
|
|
1571
|
+
const exitSpy = vi
|
|
1572
|
+
.spyOn(process, "exit")
|
|
1573
|
+
.mockImplementation((_code) => {
|
|
1574
|
+
throw new Error("process.exit");
|
|
1575
|
+
});
|
|
1234
1576
|
mockApiRequest.mockRejectedValueOnce(new Error("Model not found"));
|
|
1235
1577
|
await expect(imageGenerateCommand.parseAsync(["node", "cli", "-p", "a cat"])).rejects.toThrow();
|
|
1236
1578
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("Failed to generate"), expect.any(Error));
|
|
@@ -1244,15 +1586,27 @@ describe("image generate", () => {
|
|
|
1244
1586
|
describe("org member invite accept", () => {
|
|
1245
1587
|
it("accepts an invitation", async () => {
|
|
1246
1588
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
1247
|
-
mockApiRequest.mockResolvedValueOnce({
|
|
1248
|
-
|
|
1589
|
+
mockApiRequest.mockResolvedValueOnce({
|
|
1590
|
+
status: "accepted",
|
|
1591
|
+
orgSlug: "my-org",
|
|
1592
|
+
});
|
|
1593
|
+
await orgMemberInviteAcceptCommand.parseAsync([
|
|
1594
|
+
"node",
|
|
1595
|
+
"cli",
|
|
1596
|
+
"-i",
|
|
1597
|
+
"invite123",
|
|
1598
|
+
]);
|
|
1249
1599
|
expect(mockApiRequest).toHaveBeenCalledWith("/org/member/invite/accept", expect.objectContaining({ method: "POST" }));
|
|
1250
1600
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("accepted"));
|
|
1251
1601
|
consoleSpy.mockRestore();
|
|
1252
1602
|
});
|
|
1253
1603
|
it("handles accept failure", async () => {
|
|
1254
1604
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
1255
|
-
const exitSpy = vi
|
|
1605
|
+
const exitSpy = vi
|
|
1606
|
+
.spyOn(process, "exit")
|
|
1607
|
+
.mockImplementation((_code) => {
|
|
1608
|
+
throw new Error("process.exit");
|
|
1609
|
+
});
|
|
1256
1610
|
mockApiRequest.mockRejectedValueOnce(new Error("Invitation expired"));
|
|
1257
1611
|
await expect(orgMemberInviteAcceptCommand.parseAsync(["node", "cli", "-i", "inv1"])).rejects.toThrow();
|
|
1258
1612
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("Failed to accept"), expect.any(Error));
|
|
@@ -1266,7 +1620,10 @@ describe("org member invite accept", () => {
|
|
|
1266
1620
|
describe("plugin catalog browse", () => {
|
|
1267
1621
|
it("browses the plugin catalog", async () => {
|
|
1268
1622
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
1269
|
-
const mockResult = {
|
|
1623
|
+
const mockResult = {
|
|
1624
|
+
plugins: [{ id: "p1", name: "Slack", category: "messaging" }],
|
|
1625
|
+
total: 1,
|
|
1626
|
+
};
|
|
1270
1627
|
mockApiRequest.mockResolvedValueOnce(mockResult);
|
|
1271
1628
|
await pluginCatalogBrowseCommand.parseAsync(["node", "cli"]);
|
|
1272
1629
|
expect(mockApiRequest).toHaveBeenCalledWith("/plugin/catalog/browse", expect.objectContaining({ method: "GET" }));
|
|
@@ -1275,7 +1632,11 @@ describe("plugin catalog browse", () => {
|
|
|
1275
1632
|
});
|
|
1276
1633
|
it("handles browse failure", async () => {
|
|
1277
1634
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
1278
|
-
const exitSpy = vi
|
|
1635
|
+
const exitSpy = vi
|
|
1636
|
+
.spyOn(process, "exit")
|
|
1637
|
+
.mockImplementation((_code) => {
|
|
1638
|
+
throw new Error("process.exit");
|
|
1639
|
+
});
|
|
1279
1640
|
mockApiRequest.mockRejectedValueOnce(new Error("Service unavailable"));
|
|
1280
1641
|
await expect(pluginCatalogBrowseCommand.parseAsync(["node", "cli"])).rejects.toThrow();
|
|
1281
1642
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("Failed to browse"), expect.any(Error));
|
|
@@ -1289,15 +1650,27 @@ describe("plugin catalog browse", () => {
|
|
|
1289
1650
|
describe("plugin credential reauth", () => {
|
|
1290
1651
|
it("re-authenticates plugin credentials", async () => {
|
|
1291
1652
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
1292
|
-
mockApiRequest.mockResolvedValueOnce({
|
|
1293
|
-
|
|
1653
|
+
mockApiRequest.mockResolvedValueOnce({
|
|
1654
|
+
status: "reauthenticated",
|
|
1655
|
+
pluginId: "slack",
|
|
1656
|
+
});
|
|
1657
|
+
await pluginCredentialReauthCommand.parseAsync([
|
|
1658
|
+
"node",
|
|
1659
|
+
"cli",
|
|
1660
|
+
"-p",
|
|
1661
|
+
"slack",
|
|
1662
|
+
]);
|
|
1294
1663
|
expect(mockApiRequest).toHaveBeenCalledWith("/plugin/credential/reauth", expect.objectContaining({ method: "POST" }));
|
|
1295
1664
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("reauthenticated"));
|
|
1296
1665
|
consoleSpy.mockRestore();
|
|
1297
1666
|
});
|
|
1298
1667
|
it("handles reauth failure", async () => {
|
|
1299
1668
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
1300
|
-
const exitSpy = vi
|
|
1669
|
+
const exitSpy = vi
|
|
1670
|
+
.spyOn(process, "exit")
|
|
1671
|
+
.mockImplementation((_code) => {
|
|
1672
|
+
throw new Error("process.exit");
|
|
1673
|
+
});
|
|
1301
1674
|
mockApiRequest.mockRejectedValueOnce(new Error("OAuth error"));
|
|
1302
1675
|
await expect(pluginCredentialReauthCommand.parseAsync(["node", "cli", "-p", "slack"])).rejects.toThrow();
|
|
1303
1676
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("Failed to re-authenticate"), expect.any(Error));
|
|
@@ -1311,7 +1684,11 @@ describe("plugin credential reauth", () => {
|
|
|
1311
1684
|
describe("plugin registry list", () => {
|
|
1312
1685
|
it("lists plugin registries", async () => {
|
|
1313
1686
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
1314
|
-
mockApiRequest.mockResolvedValueOnce({
|
|
1687
|
+
mockApiRequest.mockResolvedValueOnce({
|
|
1688
|
+
registries: [
|
|
1689
|
+
{ id: "reg1", name: "Official", url: "https://registry.oxagen.ai" },
|
|
1690
|
+
],
|
|
1691
|
+
});
|
|
1315
1692
|
await pluginRegistryListCommand.parseAsync(["node", "cli"]);
|
|
1316
1693
|
expect(mockApiRequest).toHaveBeenCalledWith("/plugin/registry/list", expect.objectContaining({ method: "GET" }));
|
|
1317
1694
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("Official"));
|
|
@@ -1319,7 +1696,11 @@ describe("plugin registry list", () => {
|
|
|
1319
1696
|
});
|
|
1320
1697
|
it("handles list failure", async () => {
|
|
1321
1698
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
1322
|
-
const exitSpy = vi
|
|
1699
|
+
const exitSpy = vi
|
|
1700
|
+
.spyOn(process, "exit")
|
|
1701
|
+
.mockImplementation((_code) => {
|
|
1702
|
+
throw new Error("process.exit");
|
|
1703
|
+
});
|
|
1323
1704
|
mockApiRequest.mockRejectedValueOnce(new Error("Network error"));
|
|
1324
1705
|
await expect(pluginRegistryListCommand.parseAsync(["node", "cli"])).rejects.toThrow();
|
|
1325
1706
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("Failed to list"), expect.any(Error));
|
|
@@ -1330,17 +1711,39 @@ describe("plugin registry list", () => {
|
|
|
1330
1711
|
describe("plugin registry add", () => {
|
|
1331
1712
|
it("adds a plugin registry", async () => {
|
|
1332
1713
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
1333
|
-
mockApiRequest.mockResolvedValueOnce({
|
|
1334
|
-
|
|
1714
|
+
mockApiRequest.mockResolvedValueOnce({
|
|
1715
|
+
id: "reg2",
|
|
1716
|
+
name: "Private",
|
|
1717
|
+
url: "https://private.example.com",
|
|
1718
|
+
});
|
|
1719
|
+
await pluginRegistryAddCommand.parseAsync([
|
|
1720
|
+
"node",
|
|
1721
|
+
"cli",
|
|
1722
|
+
"-n",
|
|
1723
|
+
"Private",
|
|
1724
|
+
"-u",
|
|
1725
|
+
"https://private.example.com",
|
|
1726
|
+
]);
|
|
1335
1727
|
expect(mockApiRequest).toHaveBeenCalledWith("/plugin/registry/add", expect.objectContaining({ method: "POST" }));
|
|
1336
1728
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("reg2"));
|
|
1337
1729
|
consoleSpy.mockRestore();
|
|
1338
1730
|
});
|
|
1339
1731
|
it("handles add failure", async () => {
|
|
1340
1732
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
1341
|
-
const exitSpy = vi
|
|
1733
|
+
const exitSpy = vi
|
|
1734
|
+
.spyOn(process, "exit")
|
|
1735
|
+
.mockImplementation((_code) => {
|
|
1736
|
+
throw new Error("process.exit");
|
|
1737
|
+
});
|
|
1342
1738
|
mockApiRequest.mockRejectedValueOnce(new Error("Registry already exists"));
|
|
1343
|
-
await expect(pluginRegistryAddCommand.parseAsync([
|
|
1739
|
+
await expect(pluginRegistryAddCommand.parseAsync([
|
|
1740
|
+
"node",
|
|
1741
|
+
"cli",
|
|
1742
|
+
"-n",
|
|
1743
|
+
"Private",
|
|
1744
|
+
"-u",
|
|
1745
|
+
"https://x.com",
|
|
1746
|
+
])).rejects.toThrow();
|
|
1344
1747
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("Failed to add"), expect.any(Error));
|
|
1345
1748
|
consoleSpy.mockRestore();
|
|
1346
1749
|
exitSpy.mockRestore();
|
|
@@ -1360,7 +1763,11 @@ describe("svg generate", () => {
|
|
|
1360
1763
|
});
|
|
1361
1764
|
it("handles generate failure", async () => {
|
|
1362
1765
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
1363
|
-
const exitSpy = vi
|
|
1766
|
+
const exitSpy = vi
|
|
1767
|
+
.spyOn(process, "exit")
|
|
1768
|
+
.mockImplementation((_code) => {
|
|
1769
|
+
throw new Error("process.exit");
|
|
1770
|
+
});
|
|
1364
1771
|
mockApiRequest.mockRejectedValueOnce(new Error("Generation failed"));
|
|
1365
1772
|
await expect(svgGenerateCommand.parseAsync(["node", "cli", "-d", "circle"])).rejects.toThrow();
|
|
1366
1773
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("Failed to generate"), expect.any(Error));
|
|
@@ -1374,15 +1781,28 @@ describe("svg generate", () => {
|
|
|
1374
1781
|
describe("video generate", () => {
|
|
1375
1782
|
it("generates a video", async () => {
|
|
1376
1783
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
1377
|
-
mockApiRequest.mockResolvedValueOnce({
|
|
1378
|
-
|
|
1784
|
+
mockApiRequest.mockResolvedValueOnce({
|
|
1785
|
+
id: "vid1",
|
|
1786
|
+
status: "processing",
|
|
1787
|
+
url: null,
|
|
1788
|
+
});
|
|
1789
|
+
await videoGenerateCommand.parseAsync([
|
|
1790
|
+
"node",
|
|
1791
|
+
"cli",
|
|
1792
|
+
"-p",
|
|
1793
|
+
"A flying eagle",
|
|
1794
|
+
]);
|
|
1379
1795
|
expect(mockApiRequest).toHaveBeenCalledWith("/video/generate", expect.objectContaining({ method: "POST" }));
|
|
1380
1796
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("vid1"));
|
|
1381
1797
|
consoleSpy.mockRestore();
|
|
1382
1798
|
});
|
|
1383
1799
|
it("handles generate failure", async () => {
|
|
1384
1800
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
1385
|
-
const exitSpy = vi
|
|
1801
|
+
const exitSpy = vi
|
|
1802
|
+
.spyOn(process, "exit")
|
|
1803
|
+
.mockImplementation((_code) => {
|
|
1804
|
+
throw new Error("process.exit");
|
|
1805
|
+
});
|
|
1386
1806
|
mockApiRequest.mockRejectedValueOnce(new Error("Model not available"));
|
|
1387
1807
|
await expect(videoGenerateCommand.parseAsync(["node", "cli", "-p", "a cat"])).rejects.toThrow();
|
|
1388
1808
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("Failed to generate"), expect.any(Error));
|
|
@@ -1396,7 +1816,10 @@ describe("video generate", () => {
|
|
|
1396
1816
|
describe("workspace model settings read", () => {
|
|
1397
1817
|
it("reads workspace model settings", async () => {
|
|
1398
1818
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
1399
|
-
mockApiRequest.mockResolvedValueOnce({
|
|
1819
|
+
mockApiRequest.mockResolvedValueOnce({
|
|
1820
|
+
defaultModel: "claude-haiku-4-5-20251001",
|
|
1821
|
+
maxTokens: 4096,
|
|
1822
|
+
});
|
|
1400
1823
|
await workspaceModelSettingsReadCommand.parseAsync(["node", "cli"]);
|
|
1401
1824
|
expect(mockApiRequest).toHaveBeenCalledWith("/workspace/model-settings/read", expect.objectContaining({ method: "POST" }));
|
|
1402
1825
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("defaultModel"));
|
|
@@ -1404,7 +1827,11 @@ describe("workspace model settings read", () => {
|
|
|
1404
1827
|
});
|
|
1405
1828
|
it("handles read failure", async () => {
|
|
1406
1829
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
1407
|
-
const exitSpy = vi
|
|
1830
|
+
const exitSpy = vi
|
|
1831
|
+
.spyOn(process, "exit")
|
|
1832
|
+
.mockImplementation((_code) => {
|
|
1833
|
+
throw new Error("process.exit");
|
|
1834
|
+
});
|
|
1408
1835
|
mockApiRequest.mockRejectedValueOnce(new Error("Workspace not found"));
|
|
1409
1836
|
await expect(workspaceModelSettingsReadCommand.parseAsync(["node", "cli"])).rejects.toThrow();
|
|
1410
1837
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("Failed to read"), expect.any(Error));
|
|
@@ -1415,17 +1842,39 @@ describe("workspace model settings read", () => {
|
|
|
1415
1842
|
describe("workspace model settings write", () => {
|
|
1416
1843
|
it("writes workspace model settings", async () => {
|
|
1417
1844
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
1418
|
-
mockApiRequest.mockResolvedValueOnce({
|
|
1419
|
-
|
|
1845
|
+
mockApiRequest.mockResolvedValueOnce({
|
|
1846
|
+
success: true,
|
|
1847
|
+
key: "defaultModel",
|
|
1848
|
+
value: "claude-sonnet-4-6",
|
|
1849
|
+
});
|
|
1850
|
+
await workspaceModelSettingsWriteCommand.parseAsync([
|
|
1851
|
+
"node",
|
|
1852
|
+
"cli",
|
|
1853
|
+
"-k",
|
|
1854
|
+
"defaultModel",
|
|
1855
|
+
"-v",
|
|
1856
|
+
"claude-sonnet-4-6",
|
|
1857
|
+
]);
|
|
1420
1858
|
expect(mockApiRequest).toHaveBeenCalledWith("/workspace/model-settings/write", expect.objectContaining({ method: "POST" }));
|
|
1421
1859
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("defaultModel"));
|
|
1422
1860
|
consoleSpy.mockRestore();
|
|
1423
1861
|
});
|
|
1424
1862
|
it("handles write failure", async () => {
|
|
1425
1863
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
1426
|
-
const exitSpy = vi
|
|
1864
|
+
const exitSpy = vi
|
|
1865
|
+
.spyOn(process, "exit")
|
|
1866
|
+
.mockImplementation((_code) => {
|
|
1867
|
+
throw new Error("process.exit");
|
|
1868
|
+
});
|
|
1427
1869
|
mockApiRequest.mockRejectedValueOnce(new Error("Invalid setting key"));
|
|
1428
|
-
await expect(workspaceModelSettingsWriteCommand.parseAsync([
|
|
1870
|
+
await expect(workspaceModelSettingsWriteCommand.parseAsync([
|
|
1871
|
+
"node",
|
|
1872
|
+
"cli",
|
|
1873
|
+
"-k",
|
|
1874
|
+
"badKey",
|
|
1875
|
+
"-v",
|
|
1876
|
+
"value",
|
|
1877
|
+
])).rejects.toThrow();
|
|
1429
1878
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("Failed to write"), expect.any(Error));
|
|
1430
1879
|
consoleSpy.mockRestore();
|
|
1431
1880
|
exitSpy.mockRestore();
|
|
@@ -1437,17 +1886,43 @@ describe("workspace model settings write", () => {
|
|
|
1437
1886
|
describe("agent mcp register", () => {
|
|
1438
1887
|
it("registers an MCP server", async () => {
|
|
1439
1888
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
1440
|
-
mockApiRequest.mockResolvedValueOnce({
|
|
1441
|
-
|
|
1889
|
+
mockApiRequest.mockResolvedValueOnce({
|
|
1890
|
+
mcpServerId: "mcp1",
|
|
1891
|
+
healthStatus: "healthy",
|
|
1892
|
+
discoveredTools: ["tool1", "tool2"],
|
|
1893
|
+
});
|
|
1894
|
+
await agentMcpRegisterCommand.parseAsync([
|
|
1895
|
+
"node",
|
|
1896
|
+
"cli",
|
|
1897
|
+
"-n",
|
|
1898
|
+
"My MCP",
|
|
1899
|
+
"-u",
|
|
1900
|
+
"https://mcp.example.com",
|
|
1901
|
+
"-t",
|
|
1902
|
+
"streamable-http",
|
|
1903
|
+
]);
|
|
1442
1904
|
expect(mockApiRequest).toHaveBeenCalledWith("/agent/mcp/register", expect.objectContaining({ method: "POST" }));
|
|
1443
1905
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("mcp1"));
|
|
1444
1906
|
consoleSpy.mockRestore();
|
|
1445
1907
|
});
|
|
1446
1908
|
it("handles registration failure", async () => {
|
|
1447
1909
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
1448
|
-
const exitSpy = vi
|
|
1910
|
+
const exitSpy = vi
|
|
1911
|
+
.spyOn(process, "exit")
|
|
1912
|
+
.mockImplementation((_code) => {
|
|
1913
|
+
throw new Error("process.exit");
|
|
1914
|
+
});
|
|
1449
1915
|
mockApiRequest.mockRejectedValueOnce(new Error("Bad URL"));
|
|
1450
|
-
await expect(agentMcpRegisterCommand.parseAsync([
|
|
1916
|
+
await expect(agentMcpRegisterCommand.parseAsync([
|
|
1917
|
+
"node",
|
|
1918
|
+
"cli",
|
|
1919
|
+
"-n",
|
|
1920
|
+
"M",
|
|
1921
|
+
"-u",
|
|
1922
|
+
"http://x",
|
|
1923
|
+
"-t",
|
|
1924
|
+
"stdio",
|
|
1925
|
+
])).rejects.toThrow();
|
|
1451
1926
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("Error:"));
|
|
1452
1927
|
consoleSpy.mockRestore();
|
|
1453
1928
|
exitSpy.mockRestore();
|
|
@@ -1459,17 +1934,38 @@ describe("agent mcp register", () => {
|
|
|
1459
1934
|
describe("agent plan approve", () => {
|
|
1460
1935
|
it("approves a plan", async () => {
|
|
1461
1936
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
1462
|
-
mockApiRequest.mockResolvedValueOnce({
|
|
1463
|
-
|
|
1937
|
+
mockApiRequest.mockResolvedValueOnce({
|
|
1938
|
+
planId: "plan1",
|
|
1939
|
+
status: "approved",
|
|
1940
|
+
});
|
|
1941
|
+
await agentPlanApproveCommand.parseAsync([
|
|
1942
|
+
"node",
|
|
1943
|
+
"cli",
|
|
1944
|
+
"-p",
|
|
1945
|
+
"plan1",
|
|
1946
|
+
"-d",
|
|
1947
|
+
"approve",
|
|
1948
|
+
]);
|
|
1464
1949
|
expect(mockApiRequest).toHaveBeenCalledWith("/agent/plan/approve", expect.objectContaining({ method: "POST" }));
|
|
1465
1950
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("approved"));
|
|
1466
1951
|
consoleSpy.mockRestore();
|
|
1467
1952
|
});
|
|
1468
1953
|
it("handles approval failure", async () => {
|
|
1469
1954
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
1470
|
-
const exitSpy = vi
|
|
1955
|
+
const exitSpy = vi
|
|
1956
|
+
.spyOn(process, "exit")
|
|
1957
|
+
.mockImplementation((_code) => {
|
|
1958
|
+
throw new Error("process.exit");
|
|
1959
|
+
});
|
|
1471
1960
|
mockApiRequest.mockRejectedValueOnce(new Error("Plan not found"));
|
|
1472
|
-
await expect(agentPlanApproveCommand.parseAsync([
|
|
1961
|
+
await expect(agentPlanApproveCommand.parseAsync([
|
|
1962
|
+
"node",
|
|
1963
|
+
"cli",
|
|
1964
|
+
"-p",
|
|
1965
|
+
"p1",
|
|
1966
|
+
"-d",
|
|
1967
|
+
"deny",
|
|
1968
|
+
])).rejects.toThrow();
|
|
1473
1969
|
consoleSpy.mockRestore();
|
|
1474
1970
|
exitSpy.mockRestore();
|
|
1475
1971
|
});
|
|
@@ -1480,17 +1976,38 @@ describe("agent plan approve", () => {
|
|
|
1480
1976
|
describe("agent task background start", () => {
|
|
1481
1977
|
it("starts a background task", async () => {
|
|
1482
1978
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
1483
|
-
mockApiRequest.mockResolvedValueOnce({
|
|
1484
|
-
|
|
1979
|
+
mockApiRequest.mockResolvedValueOnce({
|
|
1980
|
+
taskId: "task1",
|
|
1981
|
+
inngestRunId: "run1",
|
|
1982
|
+
});
|
|
1983
|
+
await agentTaskBackgroundStartCommand.parseAsync([
|
|
1984
|
+
"node",
|
|
1985
|
+
"cli",
|
|
1986
|
+
"-k",
|
|
1987
|
+
"research",
|
|
1988
|
+
"--payload",
|
|
1989
|
+
'{"query":"test"}',
|
|
1990
|
+
]);
|
|
1485
1991
|
expect(mockApiRequest).toHaveBeenCalledWith("/agent/task/background/start", expect.objectContaining({ method: "POST" }));
|
|
1486
1992
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("task1"));
|
|
1487
1993
|
consoleSpy.mockRestore();
|
|
1488
1994
|
});
|
|
1489
1995
|
it("handles start failure", async () => {
|
|
1490
1996
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
1491
|
-
const exitSpy = vi
|
|
1997
|
+
const exitSpy = vi
|
|
1998
|
+
.spyOn(process, "exit")
|
|
1999
|
+
.mockImplementation((_code) => {
|
|
2000
|
+
throw new Error("process.exit");
|
|
2001
|
+
});
|
|
1492
2002
|
mockApiRequest.mockRejectedValueOnce(new Error("Queue full"));
|
|
1493
|
-
await expect(agentTaskBackgroundStartCommand.parseAsync([
|
|
2003
|
+
await expect(agentTaskBackgroundStartCommand.parseAsync([
|
|
2004
|
+
"node",
|
|
2005
|
+
"cli",
|
|
2006
|
+
"-k",
|
|
2007
|
+
"kind",
|
|
2008
|
+
"--payload",
|
|
2009
|
+
"{}",
|
|
2010
|
+
])).rejects.toThrow();
|
|
1494
2011
|
consoleSpy.mockRestore();
|
|
1495
2012
|
exitSpy.mockRestore();
|
|
1496
2013
|
});
|
|
@@ -1498,15 +2015,34 @@ describe("agent task background start", () => {
|
|
|
1498
2015
|
describe("agent task background read", () => {
|
|
1499
2016
|
it("reads task status", async () => {
|
|
1500
2017
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
1501
|
-
mockApiRequest.mockResolvedValueOnce({
|
|
1502
|
-
|
|
2018
|
+
mockApiRequest.mockResolvedValueOnce({
|
|
2019
|
+
taskId: "task1",
|
|
2020
|
+
kind: "research",
|
|
2021
|
+
status: "completed",
|
|
2022
|
+
label: "My task",
|
|
2023
|
+
resultPayload: { answer: "42" },
|
|
2024
|
+
failureReason: null,
|
|
2025
|
+
createdAt: "2026-06-08",
|
|
2026
|
+
startedAt: "2026-06-08",
|
|
2027
|
+
completedAt: "2026-06-08",
|
|
2028
|
+
});
|
|
2029
|
+
await agentTaskBackgroundReadCommand.parseAsync([
|
|
2030
|
+
"node",
|
|
2031
|
+
"cli",
|
|
2032
|
+
"-t",
|
|
2033
|
+
"task1",
|
|
2034
|
+
]);
|
|
1503
2035
|
expect(mockApiRequest).toHaveBeenCalled();
|
|
1504
2036
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("completed"));
|
|
1505
2037
|
consoleSpy.mockRestore();
|
|
1506
2038
|
});
|
|
1507
2039
|
it("handles read failure", async () => {
|
|
1508
2040
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
1509
|
-
const exitSpy = vi
|
|
2041
|
+
const exitSpy = vi
|
|
2042
|
+
.spyOn(process, "exit")
|
|
2043
|
+
.mockImplementation((_code) => {
|
|
2044
|
+
throw new Error("process.exit");
|
|
2045
|
+
});
|
|
1510
2046
|
mockApiRequest.mockRejectedValueOnce(new Error("Not found"));
|
|
1511
2047
|
await expect(agentTaskBackgroundReadCommand.parseAsync(["node", "cli", "-t", "t1"])).rejects.toThrow();
|
|
1512
2048
|
consoleSpy.mockRestore();
|
|
@@ -1517,7 +2053,12 @@ describe("agent task background cancel", () => {
|
|
|
1517
2053
|
it("cancels a background task", async () => {
|
|
1518
2054
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
1519
2055
|
mockApiRequest.mockResolvedValueOnce({ cancelled: true });
|
|
1520
|
-
await agentTaskBackgroundCancelCommand.parseAsync([
|
|
2056
|
+
await agentTaskBackgroundCancelCommand.parseAsync([
|
|
2057
|
+
"node",
|
|
2058
|
+
"cli",
|
|
2059
|
+
"-t",
|
|
2060
|
+
"task1",
|
|
2061
|
+
]);
|
|
1521
2062
|
expect(mockApiRequest).toHaveBeenCalledWith("/agent/task/background/cancel", expect.objectContaining({ method: "POST" }));
|
|
1522
2063
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("cancelled"));
|
|
1523
2064
|
consoleSpy.mockRestore();
|
|
@@ -1525,13 +2066,22 @@ describe("agent task background cancel", () => {
|
|
|
1525
2066
|
it("reports task could not be cancelled", async () => {
|
|
1526
2067
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
1527
2068
|
mockApiRequest.mockResolvedValueOnce({ cancelled: false });
|
|
1528
|
-
await agentTaskBackgroundCancelCommand.parseAsync([
|
|
2069
|
+
await agentTaskBackgroundCancelCommand.parseAsync([
|
|
2070
|
+
"node",
|
|
2071
|
+
"cli",
|
|
2072
|
+
"-t",
|
|
2073
|
+
"task1",
|
|
2074
|
+
]);
|
|
1529
2075
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("could not be cancelled"));
|
|
1530
2076
|
consoleSpy.mockRestore();
|
|
1531
2077
|
});
|
|
1532
2078
|
it("handles cancel failure", async () => {
|
|
1533
2079
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
1534
|
-
const exitSpy = vi
|
|
2080
|
+
const exitSpy = vi
|
|
2081
|
+
.spyOn(process, "exit")
|
|
2082
|
+
.mockImplementation((_code) => {
|
|
2083
|
+
throw new Error("process.exit");
|
|
2084
|
+
});
|
|
1535
2085
|
mockApiRequest.mockRejectedValueOnce(new Error("Not found"));
|
|
1536
2086
|
await expect(agentTaskBackgroundCancelCommand.parseAsync(["node", "cli", "-t", "t1"])).rejects.toThrow();
|
|
1537
2087
|
consoleSpy.mockRestore();
|
|
@@ -1544,17 +2094,40 @@ describe("agent task background cancel", () => {
|
|
|
1544
2094
|
describe("asset upload", () => {
|
|
1545
2095
|
it("uploads an asset", async () => {
|
|
1546
2096
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
1547
|
-
mockApiRequest.mockResolvedValueOnce({
|
|
1548
|
-
|
|
2097
|
+
mockApiRequest.mockResolvedValueOnce({
|
|
2098
|
+
url: "https://cdn.example.com/img.png",
|
|
2099
|
+
key: "img/abc.png",
|
|
2100
|
+
contentType: "image/png",
|
|
2101
|
+
bytes: 12345,
|
|
2102
|
+
});
|
|
2103
|
+
await assetUploadCommand.parseAsync([
|
|
2104
|
+
"node",
|
|
2105
|
+
"cli",
|
|
2106
|
+
"-s",
|
|
2107
|
+
"https://example.com/img.png",
|
|
2108
|
+
"-k",
|
|
2109
|
+
"image",
|
|
2110
|
+
]);
|
|
1549
2111
|
expect(mockApiRequest).toHaveBeenCalledWith("/asset/upload", expect.objectContaining({ method: "POST" }));
|
|
1550
2112
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("Asset uploaded"));
|
|
1551
2113
|
consoleSpy.mockRestore();
|
|
1552
2114
|
});
|
|
1553
2115
|
it("handles upload failure", async () => {
|
|
1554
2116
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
1555
|
-
const exitSpy = vi
|
|
2117
|
+
const exitSpy = vi
|
|
2118
|
+
.spyOn(process, "exit")
|
|
2119
|
+
.mockImplementation((_code) => {
|
|
2120
|
+
throw new Error("process.exit");
|
|
2121
|
+
});
|
|
1556
2122
|
mockApiRequest.mockRejectedValueOnce(new Error("Source URL unreachable"));
|
|
1557
|
-
await expect(assetUploadCommand.parseAsync([
|
|
2123
|
+
await expect(assetUploadCommand.parseAsync([
|
|
2124
|
+
"node",
|
|
2125
|
+
"cli",
|
|
2126
|
+
"-s",
|
|
2127
|
+
"https://bad.url",
|
|
2128
|
+
"-k",
|
|
2129
|
+
"image",
|
|
2130
|
+
])).rejects.toThrow();
|
|
1558
2131
|
consoleSpy.mockRestore();
|
|
1559
2132
|
exitSpy.mockRestore();
|
|
1560
2133
|
});
|
|
@@ -1565,38 +2138,47 @@ describe("asset upload", () => {
|
|
|
1565
2138
|
describe("billing subscription upgrade start", () => {
|
|
1566
2139
|
it("starts a checkout session", async () => {
|
|
1567
2140
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
1568
|
-
mockApiRequest.mockResolvedValueOnce({
|
|
1569
|
-
|
|
2141
|
+
mockApiRequest.mockResolvedValueOnce({
|
|
2142
|
+
checkoutUrl: "https://checkout.stripe.com/pay/cs_test_123",
|
|
2143
|
+
planSlug: "scale",
|
|
2144
|
+
interval: "month",
|
|
2145
|
+
});
|
|
2146
|
+
await billingSubscriptionUpgradeStartCommand.parseAsync([
|
|
2147
|
+
"node",
|
|
2148
|
+
"cli",
|
|
2149
|
+
"-p",
|
|
2150
|
+
"scale",
|
|
2151
|
+
"-i",
|
|
2152
|
+
"month",
|
|
2153
|
+
"--success-url",
|
|
2154
|
+
"https://app.oxagen.ai/success",
|
|
2155
|
+
"--cancel-url",
|
|
2156
|
+
"https://app.oxagen.ai/cancel",
|
|
2157
|
+
]);
|
|
1570
2158
|
expect(mockApiRequest).toHaveBeenCalledWith("/billing/subscription/upgrade/start", expect.objectContaining({ method: "POST" }));
|
|
1571
2159
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("Checkout session created"));
|
|
1572
2160
|
consoleSpy.mockRestore();
|
|
1573
2161
|
});
|
|
1574
2162
|
it("handles upgrade failure", async () => {
|
|
1575
2163
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
1576
|
-
const exitSpy = vi
|
|
2164
|
+
const exitSpy = vi
|
|
2165
|
+
.spyOn(process, "exit")
|
|
2166
|
+
.mockImplementation((_code) => {
|
|
2167
|
+
throw new Error("process.exit");
|
|
2168
|
+
});
|
|
1577
2169
|
mockApiRequest.mockRejectedValueOnce(new Error("Stripe error"));
|
|
1578
|
-
await expect(billingSubscriptionUpgradeStartCommand.parseAsync([
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
await brandkitApplyCommand.parseAsync(["node", "cli", "-b", "bk1", "-f", "file1", "-w", "ws1"]);
|
|
1591
|
-
expect(mockApiRequest).toHaveBeenCalledWith("/brandkit/apply", expect.objectContaining({ method: "POST" }));
|
|
1592
|
-
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("stub"));
|
|
1593
|
-
consoleSpy.mockRestore();
|
|
1594
|
-
});
|
|
1595
|
-
it("handles apply failure", async () => {
|
|
1596
|
-
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
1597
|
-
const exitSpy = vi.spyOn(process, "exit").mockImplementation((_code) => { throw new Error("process.exit"); });
|
|
1598
|
-
mockApiRequest.mockRejectedValueOnce(new Error("Brand kit not found"));
|
|
1599
|
-
await expect(brandkitApplyCommand.parseAsync(["node", "cli", "-b", "bk1", "-f", "f1", "-w", "ws1"])).rejects.toThrow();
|
|
2170
|
+
await expect(billingSubscriptionUpgradeStartCommand.parseAsync([
|
|
2171
|
+
"node",
|
|
2172
|
+
"cli",
|
|
2173
|
+
"-p",
|
|
2174
|
+
"scale",
|
|
2175
|
+
"-i",
|
|
2176
|
+
"month",
|
|
2177
|
+
"--success-url",
|
|
2178
|
+
"https://a.com/ok",
|
|
2179
|
+
"--cancel-url",
|
|
2180
|
+
"https://a.com/cancel",
|
|
2181
|
+
])).rejects.toThrow();
|
|
1600
2182
|
consoleSpy.mockRestore();
|
|
1601
2183
|
exitSpy.mockRestore();
|
|
1602
2184
|
});
|
|
@@ -1608,14 +2190,24 @@ describe("conversation purge", () => {
|
|
|
1608
2190
|
it("purges archived conversations with --yes", async () => {
|
|
1609
2191
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
1610
2192
|
mockApiRequest.mockResolvedValueOnce({ deleted: 5 });
|
|
1611
|
-
await conversationPurgeCommand.parseAsync([
|
|
2193
|
+
await conversationPurgeCommand.parseAsync([
|
|
2194
|
+
"node",
|
|
2195
|
+
"cli",
|
|
2196
|
+
"-w",
|
|
2197
|
+
"ws1",
|
|
2198
|
+
"--yes",
|
|
2199
|
+
]);
|
|
1612
2200
|
expect(mockApiRequest).toHaveBeenCalledWith("/conversation/purge", expect.objectContaining({ method: "POST" }));
|
|
1613
2201
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("Purged 5"));
|
|
1614
2202
|
consoleSpy.mockRestore();
|
|
1615
2203
|
});
|
|
1616
2204
|
it("exits without --yes", async () => {
|
|
1617
2205
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
1618
|
-
const exitSpy = vi
|
|
2206
|
+
const exitSpy = vi
|
|
2207
|
+
.spyOn(process, "exit")
|
|
2208
|
+
.mockImplementation((_code) => {
|
|
2209
|
+
throw new Error("process.exit");
|
|
2210
|
+
});
|
|
1619
2211
|
await expect(conversationPurgeCommand.parseAsync(["node", "cli", "-w", "ws1"])).rejects.toThrow();
|
|
1620
2212
|
expect(consoleSpy).toHaveBeenCalled();
|
|
1621
2213
|
consoleSpy.mockRestore();
|
|
@@ -1623,9 +2215,19 @@ describe("conversation purge", () => {
|
|
|
1623
2215
|
});
|
|
1624
2216
|
it("handles purge failure", async () => {
|
|
1625
2217
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
1626
|
-
const exitSpy = vi
|
|
2218
|
+
const exitSpy = vi
|
|
2219
|
+
.spyOn(process, "exit")
|
|
2220
|
+
.mockImplementation((_code) => {
|
|
2221
|
+
throw new Error("process.exit");
|
|
2222
|
+
});
|
|
1627
2223
|
mockApiRequest.mockRejectedValueOnce(new Error("Workspace not found"));
|
|
1628
|
-
await expect(conversationPurgeCommand.parseAsync([
|
|
2224
|
+
await expect(conversationPurgeCommand.parseAsync([
|
|
2225
|
+
"node",
|
|
2226
|
+
"cli",
|
|
2227
|
+
"-w",
|
|
2228
|
+
"ws1",
|
|
2229
|
+
"--yes",
|
|
2230
|
+
])).rejects.toThrow();
|
|
1629
2231
|
consoleSpy.mockRestore();
|
|
1630
2232
|
exitSpy.mockRestore();
|
|
1631
2233
|
});
|
|
@@ -1636,15 +2238,32 @@ describe("conversation purge", () => {
|
|
|
1636
2238
|
describe("documents pdf create", () => {
|
|
1637
2239
|
it("creates a PDF document", async () => {
|
|
1638
2240
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
1639
|
-
mockApiRequest.mockResolvedValueOnce({
|
|
1640
|
-
|
|
2241
|
+
mockApiRequest.mockResolvedValueOnce({
|
|
2242
|
+
assetId: "asset1",
|
|
2243
|
+
publicId: "pub1",
|
|
2244
|
+
kind: "pdf",
|
|
2245
|
+
mimeType: "application/pdf",
|
|
2246
|
+
sizeBytes: 50000,
|
|
2247
|
+
url: "https://blob.example.com/doc.pdf",
|
|
2248
|
+
serveUrl: "https://api.example.com/assets/asset1",
|
|
2249
|
+
});
|
|
2250
|
+
await documentsPdfCreateCommand.parseAsync([
|
|
2251
|
+
"node",
|
|
2252
|
+
"cli",
|
|
2253
|
+
"-t",
|
|
2254
|
+
"Q1 Report",
|
|
2255
|
+
]);
|
|
1641
2256
|
expect(mockApiRequest).toHaveBeenCalledWith("/documents/pdf/create", expect.objectContaining({ method: "POST" }));
|
|
1642
2257
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("PDF created"));
|
|
1643
2258
|
consoleSpy.mockRestore();
|
|
1644
2259
|
});
|
|
1645
2260
|
it("handles pdf create failure", async () => {
|
|
1646
2261
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
1647
|
-
const exitSpy = vi
|
|
2262
|
+
const exitSpy = vi
|
|
2263
|
+
.spyOn(process, "exit")
|
|
2264
|
+
.mockImplementation((_code) => {
|
|
2265
|
+
throw new Error("process.exit");
|
|
2266
|
+
});
|
|
1648
2267
|
mockApiRequest.mockRejectedValueOnce(new Error("Generation failed"));
|
|
1649
2268
|
await expect(documentsPdfCreateCommand.parseAsync(["node", "cli", "-t", "Report"])).rejects.toThrow();
|
|
1650
2269
|
consoleSpy.mockRestore();
|
|
@@ -1657,18 +2276,50 @@ describe("documents pdf create", () => {
|
|
|
1657
2276
|
describe("form fill", () => {
|
|
1658
2277
|
it("fills form fields", async () => {
|
|
1659
2278
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
1660
|
-
const fields = [
|
|
2279
|
+
const fields = [
|
|
2280
|
+
{
|
|
2281
|
+
name: "firstName",
|
|
2282
|
+
label: "First Name",
|
|
2283
|
+
type: "text",
|
|
2284
|
+
current: "",
|
|
2285
|
+
changed: false,
|
|
2286
|
+
proposed: "Alice",
|
|
2287
|
+
reason: "Inferred from instruction",
|
|
2288
|
+
},
|
|
2289
|
+
];
|
|
1661
2290
|
mockApiRequest.mockResolvedValueOnce({ fields });
|
|
1662
|
-
await formFillCommand.parseAsync([
|
|
2291
|
+
await formFillCommand.parseAsync([
|
|
2292
|
+
"node",
|
|
2293
|
+
"cli",
|
|
2294
|
+
"-r",
|
|
2295
|
+
"/profile",
|
|
2296
|
+
"-i",
|
|
2297
|
+
"Fill with Alice's info",
|
|
2298
|
+
"--fields",
|
|
2299
|
+
'[{"name":"firstName","label":"First Name","type":"text","current":""}]',
|
|
2300
|
+
]);
|
|
1663
2301
|
expect(mockApiRequest).toHaveBeenCalledWith("/form/fill", expect.objectContaining({ method: "POST" }));
|
|
1664
2302
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("Form fill suggestion"));
|
|
1665
2303
|
consoleSpy.mockRestore();
|
|
1666
2304
|
});
|
|
1667
2305
|
it("handles form fill failure", async () => {
|
|
1668
2306
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
1669
|
-
const exitSpy = vi
|
|
2307
|
+
const exitSpy = vi
|
|
2308
|
+
.spyOn(process, "exit")
|
|
2309
|
+
.mockImplementation((_code) => {
|
|
2310
|
+
throw new Error("process.exit");
|
|
2311
|
+
});
|
|
1670
2312
|
mockApiRequest.mockRejectedValueOnce(new Error("LLM error"));
|
|
1671
|
-
await expect(formFillCommand.parseAsync([
|
|
2313
|
+
await expect(formFillCommand.parseAsync([
|
|
2314
|
+
"node",
|
|
2315
|
+
"cli",
|
|
2316
|
+
"-r",
|
|
2317
|
+
"/p",
|
|
2318
|
+
"-i",
|
|
2319
|
+
"fill",
|
|
2320
|
+
"--fields",
|
|
2321
|
+
"[]",
|
|
2322
|
+
])).rejects.toThrow();
|
|
1672
2323
|
consoleSpy.mockRestore();
|
|
1673
2324
|
exitSpy.mockRestore();
|
|
1674
2325
|
});
|
|
@@ -1679,15 +2330,27 @@ describe("form fill", () => {
|
|
|
1679
2330
|
describe("org member invite decline", () => {
|
|
1680
2331
|
it("declines an invitation", async () => {
|
|
1681
2332
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
1682
|
-
mockApiRequest.mockResolvedValueOnce({
|
|
1683
|
-
|
|
2333
|
+
mockApiRequest.mockResolvedValueOnce({
|
|
2334
|
+
invitationPublicId: "inv1",
|
|
2335
|
+
status: "declined",
|
|
2336
|
+
});
|
|
2337
|
+
await orgMemberInviteDeclineCommand.parseAsync([
|
|
2338
|
+
"node",
|
|
2339
|
+
"cli",
|
|
2340
|
+
"-i",
|
|
2341
|
+
"inv1",
|
|
2342
|
+
]);
|
|
1684
2343
|
expect(mockApiRequest).toHaveBeenCalledWith("/org/member/invite/decline", expect.objectContaining({ method: "POST" }));
|
|
1685
2344
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("declined"));
|
|
1686
2345
|
consoleSpy.mockRestore();
|
|
1687
2346
|
});
|
|
1688
2347
|
it("handles decline failure", async () => {
|
|
1689
2348
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
1690
|
-
const exitSpy = vi
|
|
2349
|
+
const exitSpy = vi
|
|
2350
|
+
.spyOn(process, "exit")
|
|
2351
|
+
.mockImplementation((_code) => {
|
|
2352
|
+
throw new Error("process.exit");
|
|
2353
|
+
});
|
|
1691
2354
|
mockApiRequest.mockRejectedValueOnce(new Error("Invitation not found"));
|
|
1692
2355
|
await expect(orgMemberInviteDeclineCommand.parseAsync(["node", "cli", "-i", "inv1"])).rejects.toThrow();
|
|
1693
2356
|
consoleSpy.mockRestore();
|
|
@@ -1700,17 +2363,41 @@ describe("org member invite decline", () => {
|
|
|
1700
2363
|
describe("organization create", () => {
|
|
1701
2364
|
it("creates an organization", async () => {
|
|
1702
2365
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
1703
|
-
mockApiRequest.mockResolvedValueOnce({
|
|
1704
|
-
|
|
2366
|
+
mockApiRequest.mockResolvedValueOnce({
|
|
2367
|
+
publicId: "org1",
|
|
2368
|
+
name: "Acme Corp",
|
|
2369
|
+
slug: "acme-corp",
|
|
2370
|
+
type: "business",
|
|
2371
|
+
createdAt: "2026-06-08",
|
|
2372
|
+
});
|
|
2373
|
+
await organizationCreateCommand.parseAsync([
|
|
2374
|
+
"node",
|
|
2375
|
+
"cli",
|
|
2376
|
+
"-n",
|
|
2377
|
+
"Acme Corp",
|
|
2378
|
+
"-s",
|
|
2379
|
+
"acme-corp",
|
|
2380
|
+
]);
|
|
1705
2381
|
expect(mockApiRequest).toHaveBeenCalledWith("/organization/create", expect.objectContaining({ method: "POST" }));
|
|
1706
2382
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("Organization created"));
|
|
1707
2383
|
consoleSpy.mockRestore();
|
|
1708
2384
|
});
|
|
1709
2385
|
it("handles create failure", async () => {
|
|
1710
2386
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
1711
|
-
const exitSpy = vi
|
|
2387
|
+
const exitSpy = vi
|
|
2388
|
+
.spyOn(process, "exit")
|
|
2389
|
+
.mockImplementation((_code) => {
|
|
2390
|
+
throw new Error("process.exit");
|
|
2391
|
+
});
|
|
1712
2392
|
mockApiRequest.mockRejectedValueOnce(new Error("Slug already taken"));
|
|
1713
|
-
await expect(organizationCreateCommand.parseAsync([
|
|
2393
|
+
await expect(organizationCreateCommand.parseAsync([
|
|
2394
|
+
"node",
|
|
2395
|
+
"cli",
|
|
2396
|
+
"-n",
|
|
2397
|
+
"Acme",
|
|
2398
|
+
"-s",
|
|
2399
|
+
"acme",
|
|
2400
|
+
])).rejects.toThrow();
|
|
1714
2401
|
consoleSpy.mockRestore();
|
|
1715
2402
|
exitSpy.mockRestore();
|
|
1716
2403
|
});
|
|
@@ -1722,16 +2409,36 @@ describe("plugin credential set_secret", () => {
|
|
|
1722
2409
|
it("stores a credential", async () => {
|
|
1723
2410
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
1724
2411
|
mockApiRequest.mockResolvedValueOnce({ ok: true });
|
|
1725
|
-
await pluginCredentialSetSecretCommand.parseAsync([
|
|
2412
|
+
await pluginCredentialSetSecretCommand.parseAsync([
|
|
2413
|
+
"node",
|
|
2414
|
+
"cli",
|
|
2415
|
+
"-l",
|
|
2416
|
+
"listing1",
|
|
2417
|
+
"-a",
|
|
2418
|
+
"secret",
|
|
2419
|
+
"--secret",
|
|
2420
|
+
"my-secret",
|
|
2421
|
+
]);
|
|
1726
2422
|
expect(mockApiRequest).toHaveBeenCalledWith("/plugin/credential/set_secret", expect.objectContaining({ method: "POST" }));
|
|
1727
2423
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("Credential stored"));
|
|
1728
2424
|
consoleSpy.mockRestore();
|
|
1729
2425
|
});
|
|
1730
2426
|
it("handles credential failure", async () => {
|
|
1731
2427
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
1732
|
-
const exitSpy = vi
|
|
2428
|
+
const exitSpy = vi
|
|
2429
|
+
.spyOn(process, "exit")
|
|
2430
|
+
.mockImplementation((_code) => {
|
|
2431
|
+
throw new Error("process.exit");
|
|
2432
|
+
});
|
|
1733
2433
|
mockApiRequest.mockRejectedValueOnce(new Error("Listing not found"));
|
|
1734
|
-
await expect(pluginCredentialSetSecretCommand.parseAsync([
|
|
2434
|
+
await expect(pluginCredentialSetSecretCommand.parseAsync([
|
|
2435
|
+
"node",
|
|
2436
|
+
"cli",
|
|
2437
|
+
"-l",
|
|
2438
|
+
"l1",
|
|
2439
|
+
"-a",
|
|
2440
|
+
"secret",
|
|
2441
|
+
])).rejects.toThrow();
|
|
1735
2442
|
consoleSpy.mockRestore();
|
|
1736
2443
|
exitSpy.mockRestore();
|
|
1737
2444
|
});
|
|
@@ -1742,22 +2449,41 @@ describe("plugin credential set_secret", () => {
|
|
|
1742
2449
|
describe("plugin org install bulk", () => {
|
|
1743
2450
|
it("bulk installs plugins", async () => {
|
|
1744
2451
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
1745
|
-
mockApiRequest.mockResolvedValueOnce({
|
|
1746
|
-
|
|
2452
|
+
mockApiRequest.mockResolvedValueOnce({
|
|
2453
|
+
installed: [{ pluginId: "srv1", orgListingId: "listing1", error: null }],
|
|
2454
|
+
});
|
|
2455
|
+
await pluginOrgInstallBulkCommand.parseAsync([
|
|
2456
|
+
"node",
|
|
2457
|
+
"cli",
|
|
2458
|
+
"--items",
|
|
2459
|
+
'[{"catalogServerId":"srv1"}]',
|
|
2460
|
+
]);
|
|
1747
2461
|
expect(mockApiRequest).toHaveBeenCalledWith("/plugin/org/install_bulk", expect.objectContaining({ method: "POST" }));
|
|
1748
2462
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("1 succeeded"));
|
|
1749
2463
|
consoleSpy.mockRestore();
|
|
1750
2464
|
});
|
|
1751
2465
|
it("reports partial failures", async () => {
|
|
1752
2466
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
1753
|
-
mockApiRequest.mockResolvedValueOnce({
|
|
1754
|
-
|
|
2467
|
+
mockApiRequest.mockResolvedValueOnce({
|
|
2468
|
+
installed: [{ pluginId: "srv1", orgListingId: null, error: "Not found" }],
|
|
2469
|
+
});
|
|
2470
|
+
await pluginOrgInstallBulkCommand.parseAsync([
|
|
2471
|
+
"node",
|
|
2472
|
+
"cli",
|
|
2473
|
+
"--items",
|
|
2474
|
+
'[{"catalogServerId":"srv1"}]',
|
|
2475
|
+
]);
|
|
1755
2476
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("0 succeeded, 1 failed"));
|
|
2477
|
+
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("srv1: Not found"));
|
|
1756
2478
|
consoleSpy.mockRestore();
|
|
1757
2479
|
});
|
|
1758
2480
|
it("handles bulk install failure", async () => {
|
|
1759
2481
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
1760
|
-
const exitSpy = vi
|
|
2482
|
+
const exitSpy = vi
|
|
2483
|
+
.spyOn(process, "exit")
|
|
2484
|
+
.mockImplementation((_code) => {
|
|
2485
|
+
throw new Error("process.exit");
|
|
2486
|
+
});
|
|
1761
2487
|
mockApiRequest.mockRejectedValueOnce(new Error("Bad request"));
|
|
1762
2488
|
await expect(pluginOrgInstallBulkCommand.parseAsync(["node", "cli", "--items", "[]"])).rejects.toThrow();
|
|
1763
2489
|
consoleSpy.mockRestore();
|
|
@@ -1771,7 +2497,15 @@ describe("plugin org list", () => {
|
|
|
1771
2497
|
it("lists org plugins", async () => {
|
|
1772
2498
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
1773
2499
|
mockApiRequest.mockResolvedValueOnce({
|
|
1774
|
-
listings: [
|
|
2500
|
+
listings: [
|
|
2501
|
+
{
|
|
2502
|
+
id: "l1",
|
|
2503
|
+
publicId: "pub1",
|
|
2504
|
+
name: "Slack",
|
|
2505
|
+
pluginType: "mcp_server",
|
|
2506
|
+
enabled: true,
|
|
2507
|
+
},
|
|
2508
|
+
],
|
|
1775
2509
|
denylist: [],
|
|
1776
2510
|
});
|
|
1777
2511
|
await pluginOrgListCommand.parseAsync(["node", "cli"]);
|
|
@@ -1783,7 +2517,14 @@ describe("plugin org list", () => {
|
|
|
1783
2517
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
1784
2518
|
mockApiRequest.mockResolvedValueOnce({
|
|
1785
2519
|
listings: [],
|
|
1786
|
-
denylist: [
|
|
2520
|
+
denylist: [
|
|
2521
|
+
{
|
|
2522
|
+
id: "d1",
|
|
2523
|
+
serverName: "bad-server",
|
|
2524
|
+
pluginType: "mcp_server",
|
|
2525
|
+
reason: "Security risk",
|
|
2526
|
+
},
|
|
2527
|
+
],
|
|
1787
2528
|
});
|
|
1788
2529
|
await pluginOrgListCommand.parseAsync(["node", "cli"]);
|
|
1789
2530
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("Denylist"));
|
|
@@ -1791,7 +2532,11 @@ describe("plugin org list", () => {
|
|
|
1791
2532
|
});
|
|
1792
2533
|
it("handles list failure", async () => {
|
|
1793
2534
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
1794
|
-
const exitSpy = vi
|
|
2535
|
+
const exitSpy = vi
|
|
2536
|
+
.spyOn(process, "exit")
|
|
2537
|
+
.mockImplementation((_code) => {
|
|
2538
|
+
throw new Error("process.exit");
|
|
2539
|
+
});
|
|
1795
2540
|
mockApiRequest.mockRejectedValueOnce(new Error("Unauthorized"));
|
|
1796
2541
|
await expect(pluginOrgListCommand.parseAsync(["node", "cli"])).rejects.toThrow();
|
|
1797
2542
|
consoleSpy.mockRestore();
|
|
@@ -1805,7 +2550,14 @@ describe("plugin org set_enabled", () => {
|
|
|
1805
2550
|
it("enables a plugin listing", async () => {
|
|
1806
2551
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
1807
2552
|
mockApiRequest.mockResolvedValueOnce({ ok: true });
|
|
1808
|
-
await pluginOrgSetEnabledCommand.parseAsync([
|
|
2553
|
+
await pluginOrgSetEnabledCommand.parseAsync([
|
|
2554
|
+
"node",
|
|
2555
|
+
"cli",
|
|
2556
|
+
"-l",
|
|
2557
|
+
"listing1",
|
|
2558
|
+
"--enabled",
|
|
2559
|
+
"true",
|
|
2560
|
+
]);
|
|
1809
2561
|
expect(mockApiRequest).toHaveBeenCalledWith("/plugin/org/set_enabled", expect.objectContaining({ method: "POST" }));
|
|
1810
2562
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("enabled"));
|
|
1811
2563
|
consoleSpy.mockRestore();
|
|
@@ -1813,15 +2565,33 @@ describe("plugin org set_enabled", () => {
|
|
|
1813
2565
|
it("disables a plugin listing", async () => {
|
|
1814
2566
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
1815
2567
|
mockApiRequest.mockResolvedValueOnce({ ok: true });
|
|
1816
|
-
await pluginOrgSetEnabledCommand.parseAsync([
|
|
2568
|
+
await pluginOrgSetEnabledCommand.parseAsync([
|
|
2569
|
+
"node",
|
|
2570
|
+
"cli",
|
|
2571
|
+
"-l",
|
|
2572
|
+
"listing1",
|
|
2573
|
+
"--enabled",
|
|
2574
|
+
"false",
|
|
2575
|
+
]);
|
|
1817
2576
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("disabled"));
|
|
1818
2577
|
consoleSpy.mockRestore();
|
|
1819
2578
|
});
|
|
1820
2579
|
it("handles set_enabled failure", async () => {
|
|
1821
2580
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
1822
|
-
const exitSpy = vi
|
|
2581
|
+
const exitSpy = vi
|
|
2582
|
+
.spyOn(process, "exit")
|
|
2583
|
+
.mockImplementation((_code) => {
|
|
2584
|
+
throw new Error("process.exit");
|
|
2585
|
+
});
|
|
1823
2586
|
mockApiRequest.mockRejectedValueOnce(new Error("Listing not found"));
|
|
1824
|
-
await expect(pluginOrgSetEnabledCommand.parseAsync([
|
|
2587
|
+
await expect(pluginOrgSetEnabledCommand.parseAsync([
|
|
2588
|
+
"node",
|
|
2589
|
+
"cli",
|
|
2590
|
+
"-l",
|
|
2591
|
+
"l1",
|
|
2592
|
+
"--enabled",
|
|
2593
|
+
"true",
|
|
2594
|
+
])).rejects.toThrow();
|
|
1825
2595
|
consoleSpy.mockRestore();
|
|
1826
2596
|
exitSpy.mockRestore();
|
|
1827
2597
|
});
|
|
@@ -1840,7 +2610,11 @@ describe("plugin registry remove", () => {
|
|
|
1840
2610
|
});
|
|
1841
2611
|
it("handles remove failure", async () => {
|
|
1842
2612
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
1843
|
-
const exitSpy = vi
|
|
2613
|
+
const exitSpy = vi
|
|
2614
|
+
.spyOn(process, "exit")
|
|
2615
|
+
.mockImplementation((_code) => {
|
|
2616
|
+
throw new Error("process.exit");
|
|
2617
|
+
});
|
|
1844
2618
|
mockApiRequest.mockRejectedValueOnce(new Error("Registry is global default"));
|
|
1845
2619
|
await expect(pluginRegistryRemoveCommand.parseAsync(["node", "cli", "-r", "r1"])).rejects.toThrow();
|
|
1846
2620
|
consoleSpy.mockRestore();
|
|
@@ -1854,7 +2628,12 @@ describe("plugin settings set_auth_alerts", () => {
|
|
|
1854
2628
|
it("updates auth alert settings", async () => {
|
|
1855
2629
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
1856
2630
|
mockApiRequest.mockResolvedValueOnce({ ok: true });
|
|
1857
|
-
await pluginSettingsSetAuthAlertsCommand.parseAsync([
|
|
2631
|
+
await pluginSettingsSetAuthAlertsCommand.parseAsync([
|
|
2632
|
+
"node",
|
|
2633
|
+
"cli",
|
|
2634
|
+
"--roles",
|
|
2635
|
+
"Owner,Admin",
|
|
2636
|
+
]);
|
|
1858
2637
|
expect(mockApiRequest).toHaveBeenCalledWith("/plugin/settings/set_auth_alerts", expect.objectContaining({ method: "POST" }));
|
|
1859
2638
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("updated"));
|
|
1860
2639
|
consoleSpy.mockRestore();
|
|
@@ -1862,15 +2641,29 @@ describe("plugin settings set_auth_alerts", () => {
|
|
|
1862
2641
|
it("reports update failed when ok=false", async () => {
|
|
1863
2642
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
1864
2643
|
mockApiRequest.mockResolvedValueOnce({ ok: false });
|
|
1865
|
-
await pluginSettingsSetAuthAlertsCommand.parseAsync([
|
|
2644
|
+
await pluginSettingsSetAuthAlertsCommand.parseAsync([
|
|
2645
|
+
"node",
|
|
2646
|
+
"cli",
|
|
2647
|
+
"--roles",
|
|
2648
|
+
"Owner",
|
|
2649
|
+
]);
|
|
1866
2650
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("Update failed"));
|
|
1867
2651
|
consoleSpy.mockRestore();
|
|
1868
2652
|
});
|
|
1869
2653
|
it("handles failure", async () => {
|
|
1870
2654
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
1871
|
-
const exitSpy = vi
|
|
2655
|
+
const exitSpy = vi
|
|
2656
|
+
.spyOn(process, "exit")
|
|
2657
|
+
.mockImplementation((_code) => {
|
|
2658
|
+
throw new Error("process.exit");
|
|
2659
|
+
});
|
|
1872
2660
|
mockApiRequest.mockRejectedValueOnce(new Error("Permission denied"));
|
|
1873
|
-
await expect(pluginSettingsSetAuthAlertsCommand.parseAsync([
|
|
2661
|
+
await expect(pluginSettingsSetAuthAlertsCommand.parseAsync([
|
|
2662
|
+
"node",
|
|
2663
|
+
"cli",
|
|
2664
|
+
"--roles",
|
|
2665
|
+
"Owner",
|
|
2666
|
+
])).rejects.toThrow();
|
|
1874
2667
|
consoleSpy.mockRestore();
|
|
1875
2668
|
exitSpy.mockRestore();
|
|
1876
2669
|
});
|
|
@@ -1882,7 +2675,14 @@ describe("plugin workspace set_enabled", () => {
|
|
|
1882
2675
|
it("enables a plugin for workspace", async () => {
|
|
1883
2676
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
1884
2677
|
mockApiRequest.mockResolvedValueOnce({ workspaceServerId: "wsrv1" });
|
|
1885
|
-
await pluginWorkspaceSetEnabledCommand.parseAsync([
|
|
2678
|
+
await pluginWorkspaceSetEnabledCommand.parseAsync([
|
|
2679
|
+
"node",
|
|
2680
|
+
"cli",
|
|
2681
|
+
"-l",
|
|
2682
|
+
"listing1",
|
|
2683
|
+
"--enabled",
|
|
2684
|
+
"true",
|
|
2685
|
+
]);
|
|
1886
2686
|
expect(mockApiRequest).toHaveBeenCalledWith("/plugin/workspace/set_enabled", expect.objectContaining({ method: "POST" }));
|
|
1887
2687
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("enabled"));
|
|
1888
2688
|
consoleSpy.mockRestore();
|
|
@@ -1890,15 +2690,33 @@ describe("plugin workspace set_enabled", () => {
|
|
|
1890
2690
|
it("disables a plugin for workspace (no server ID)", async () => {
|
|
1891
2691
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
1892
2692
|
mockApiRequest.mockResolvedValueOnce({ workspaceServerId: null });
|
|
1893
|
-
await pluginWorkspaceSetEnabledCommand.parseAsync([
|
|
2693
|
+
await pluginWorkspaceSetEnabledCommand.parseAsync([
|
|
2694
|
+
"node",
|
|
2695
|
+
"cli",
|
|
2696
|
+
"-l",
|
|
2697
|
+
"listing1",
|
|
2698
|
+
"--enabled",
|
|
2699
|
+
"false",
|
|
2700
|
+
]);
|
|
1894
2701
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("disabled"));
|
|
1895
2702
|
consoleSpy.mockRestore();
|
|
1896
2703
|
});
|
|
1897
2704
|
it("handles failure", async () => {
|
|
1898
2705
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
1899
|
-
const exitSpy = vi
|
|
2706
|
+
const exitSpy = vi
|
|
2707
|
+
.spyOn(process, "exit")
|
|
2708
|
+
.mockImplementation((_code) => {
|
|
2709
|
+
throw new Error("process.exit");
|
|
2710
|
+
});
|
|
1900
2711
|
mockApiRequest.mockRejectedValueOnce(new Error("Listing not found"));
|
|
1901
|
-
await expect(pluginWorkspaceSetEnabledCommand.parseAsync([
|
|
2712
|
+
await expect(pluginWorkspaceSetEnabledCommand.parseAsync([
|
|
2713
|
+
"node",
|
|
2714
|
+
"cli",
|
|
2715
|
+
"-l",
|
|
2716
|
+
"l1",
|
|
2717
|
+
"--enabled",
|
|
2718
|
+
"true",
|
|
2719
|
+
])).rejects.toThrow();
|
|
1902
2720
|
consoleSpy.mockRestore();
|
|
1903
2721
|
exitSpy.mockRestore();
|
|
1904
2722
|
});
|
|
@@ -1916,16 +2734,30 @@ describe("system install instructions", () => {
|
|
|
1916
2734
|
{ label: "Authenticate", command: "oxagen auth login" },
|
|
1917
2735
|
],
|
|
1918
2736
|
});
|
|
1919
|
-
await systemInstallInstructionsCommand.parseAsync([
|
|
2737
|
+
await systemInstallInstructionsCommand.parseAsync([
|
|
2738
|
+
"node",
|
|
2739
|
+
"cli",
|
|
2740
|
+
"-c",
|
|
2741
|
+
"claude-code",
|
|
2742
|
+
]);
|
|
1920
2743
|
expect(mockApiRequest).toHaveBeenCalled();
|
|
1921
2744
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("claude-code"));
|
|
1922
2745
|
consoleSpy.mockRestore();
|
|
1923
2746
|
});
|
|
1924
2747
|
it("handles fetch failure", async () => {
|
|
1925
2748
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
1926
|
-
const exitSpy = vi
|
|
2749
|
+
const exitSpy = vi
|
|
2750
|
+
.spyOn(process, "exit")
|
|
2751
|
+
.mockImplementation((_code) => {
|
|
2752
|
+
throw new Error("process.exit");
|
|
2753
|
+
});
|
|
1927
2754
|
mockApiRequest.mockRejectedValueOnce(new Error("Unknown client"));
|
|
1928
|
-
await expect(systemInstallInstructionsCommand.parseAsync([
|
|
2755
|
+
await expect(systemInstallInstructionsCommand.parseAsync([
|
|
2756
|
+
"node",
|
|
2757
|
+
"cli",
|
|
2758
|
+
"-c",
|
|
2759
|
+
"unknown",
|
|
2760
|
+
])).rejects.toThrow();
|
|
1929
2761
|
consoleSpy.mockRestore();
|
|
1930
2762
|
exitSpy.mockRestore();
|
|
1931
2763
|
});
|
|
@@ -1969,7 +2801,11 @@ describe("user preferences read", () => {
|
|
|
1969
2801
|
});
|
|
1970
2802
|
it("handles read failure", async () => {
|
|
1971
2803
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
1972
|
-
const exitSpy = vi
|
|
2804
|
+
const exitSpy = vi
|
|
2805
|
+
.spyOn(process, "exit")
|
|
2806
|
+
.mockImplementation((_code) => {
|
|
2807
|
+
throw new Error("process.exit");
|
|
2808
|
+
});
|
|
1973
2809
|
mockApiRequest.mockRejectedValueOnce(new Error("Unauthorized"));
|
|
1974
2810
|
await expect(userPreferencesReadCommand.parseAsync(["node", "cli"])).rejects.toThrow();
|
|
1975
2811
|
consoleSpy.mockRestore();
|
|
@@ -1989,16 +2825,30 @@ describe("user preferences write", () => {
|
|
|
1989
2825
|
defaultImageModel: null,
|
|
1990
2826
|
defaultVideoModel: null,
|
|
1991
2827
|
});
|
|
1992
|
-
await userPreferencesWriteCommand.parseAsync([
|
|
2828
|
+
await userPreferencesWriteCommand.parseAsync([
|
|
2829
|
+
"node",
|
|
2830
|
+
"cli",
|
|
2831
|
+
"--font-size",
|
|
2832
|
+
"large",
|
|
2833
|
+
]);
|
|
1993
2834
|
expect(mockApiRequest).toHaveBeenCalledWith("/user/preferences/write", expect.objectContaining({ method: "POST" }));
|
|
1994
2835
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("updated"));
|
|
1995
2836
|
consoleSpy.mockRestore();
|
|
1996
2837
|
});
|
|
1997
2838
|
it("handles write failure", async () => {
|
|
1998
2839
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
1999
|
-
const exitSpy = vi
|
|
2840
|
+
const exitSpy = vi
|
|
2841
|
+
.spyOn(process, "exit")
|
|
2842
|
+
.mockImplementation((_code) => {
|
|
2843
|
+
throw new Error("process.exit");
|
|
2844
|
+
});
|
|
2000
2845
|
mockApiRequest.mockRejectedValueOnce(new Error("Validation failed"));
|
|
2001
|
-
await expect(userPreferencesWriteCommand.parseAsync([
|
|
2846
|
+
await expect(userPreferencesWriteCommand.parseAsync([
|
|
2847
|
+
"node",
|
|
2848
|
+
"cli",
|
|
2849
|
+
"--density",
|
|
2850
|
+
"bad",
|
|
2851
|
+
])).rejects.toThrow();
|
|
2002
2852
|
consoleSpy.mockRestore();
|
|
2003
2853
|
exitSpy.mockRestore();
|
|
2004
2854
|
});
|
|
@@ -2024,7 +2874,11 @@ describe("workflow cancel", () => {
|
|
|
2024
2874
|
});
|
|
2025
2875
|
it("handles cancel failure", async () => {
|
|
2026
2876
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
2027
|
-
const exitSpy = vi
|
|
2877
|
+
const exitSpy = vi
|
|
2878
|
+
.spyOn(process, "exit")
|
|
2879
|
+
.mockImplementation((_code) => {
|
|
2880
|
+
throw new Error("process.exit");
|
|
2881
|
+
});
|
|
2028
2882
|
mockApiRequest.mockRejectedValueOnce(new Error("Not found"));
|
|
2029
2883
|
await expect(workflowCancelCommand.parseAsync(["node", "cli", "-w", "wfr_abc"])).rejects.toThrow();
|
|
2030
2884
|
consoleSpy.mockRestore();
|
|
@@ -2035,7 +2889,15 @@ describe("workflow status", () => {
|
|
|
2035
2889
|
it("shows workflow status and tasks", async () => {
|
|
2036
2890
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
2037
2891
|
mockApiRequest.mockResolvedValueOnce({
|
|
2038
|
-
workflow: {
|
|
2892
|
+
workflow: {
|
|
2893
|
+
id: "wf1",
|
|
2894
|
+
publicId: "wfr_abc",
|
|
2895
|
+
title: "Research task",
|
|
2896
|
+
status: "running",
|
|
2897
|
+
totalTasks: 5,
|
|
2898
|
+
completedTasks: 3,
|
|
2899
|
+
failedTasks: 0,
|
|
2900
|
+
},
|
|
2039
2901
|
tasks: [
|
|
2040
2902
|
{ id: "t1", title: "Gather data", status: "completed" },
|
|
2041
2903
|
{ id: "t2", title: "Analyze data", status: "running" },
|
|
@@ -2048,7 +2910,11 @@ describe("workflow status", () => {
|
|
|
2048
2910
|
});
|
|
2049
2911
|
it("handles status fetch failure", async () => {
|
|
2050
2912
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
2051
|
-
const exitSpy = vi
|
|
2913
|
+
const exitSpy = vi
|
|
2914
|
+
.spyOn(process, "exit")
|
|
2915
|
+
.mockImplementation((_code) => {
|
|
2916
|
+
throw new Error("process.exit");
|
|
2917
|
+
});
|
|
2052
2918
|
mockApiRequest.mockRejectedValueOnce(new Error("Workflow not found"));
|
|
2053
2919
|
await expect(workflowStatusCommand.parseAsync(["node", "cli", "-w", "wfr_xyz"])).rejects.toThrow();
|
|
2054
2920
|
consoleSpy.mockRestore();
|
|
@@ -2063,7 +2929,11 @@ describe("workflow status", () => {
|
|
|
2063
2929
|
describe("branch coverage: ApiError error paths", () => {
|
|
2064
2930
|
it("automation list returns ApiError message", async () => {
|
|
2065
2931
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
2066
|
-
const exitSpy = vi
|
|
2932
|
+
const exitSpy = vi
|
|
2933
|
+
.spyOn(process, "exit")
|
|
2934
|
+
.mockImplementation((_code) => {
|
|
2935
|
+
throw new Error("exit");
|
|
2936
|
+
});
|
|
2067
2937
|
mockApiError(403, "Forbidden");
|
|
2068
2938
|
await expect(automationListCommand.parseAsync(["node", "cli"])).rejects.toThrow();
|
|
2069
2939
|
expect(consoleSpy).toHaveBeenCalledWith("Error: Forbidden");
|
|
@@ -2072,7 +2942,11 @@ describe("branch coverage: ApiError error paths", () => {
|
|
|
2072
2942
|
});
|
|
2073
2943
|
it("automation create returns ApiError message", async () => {
|
|
2074
2944
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
2075
|
-
const exitSpy = vi
|
|
2945
|
+
const exitSpy = vi
|
|
2946
|
+
.spyOn(process, "exit")
|
|
2947
|
+
.mockImplementation((_code) => {
|
|
2948
|
+
throw new Error("exit");
|
|
2949
|
+
});
|
|
2076
2950
|
mockApiError(400, "Name required");
|
|
2077
2951
|
await expect(automationCreateCommand.parseAsync(["node", "cli", "-n", "A"])).rejects.toThrow();
|
|
2078
2952
|
expect(consoleSpy).toHaveBeenCalledWith("Error: Name required");
|
|
@@ -2081,7 +2955,11 @@ describe("branch coverage: ApiError error paths", () => {
|
|
|
2081
2955
|
});
|
|
2082
2956
|
it("automation enable returns ApiError message", async () => {
|
|
2083
2957
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
2084
|
-
const exitSpy = vi
|
|
2958
|
+
const exitSpy = vi
|
|
2959
|
+
.spyOn(process, "exit")
|
|
2960
|
+
.mockImplementation((_code) => {
|
|
2961
|
+
throw new Error("exit");
|
|
2962
|
+
});
|
|
2085
2963
|
mockApiError(404, "Automation not found");
|
|
2086
2964
|
await expect(automationEnableCommand.parseAsync(["node", "cli", "plt_missing"])).rejects.toThrow();
|
|
2087
2965
|
expect(consoleSpy).toHaveBeenCalledWith("Error: Automation not found");
|
|
@@ -2090,7 +2968,11 @@ describe("branch coverage: ApiError error paths", () => {
|
|
|
2090
2968
|
});
|
|
2091
2969
|
it("automation disable returns ApiError message", async () => {
|
|
2092
2970
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
2093
|
-
const exitSpy = vi
|
|
2971
|
+
const exitSpy = vi
|
|
2972
|
+
.spyOn(process, "exit")
|
|
2973
|
+
.mockImplementation((_code) => {
|
|
2974
|
+
throw new Error("exit");
|
|
2975
|
+
});
|
|
2094
2976
|
mockApiError(404, "Automation not found");
|
|
2095
2977
|
await expect(automationDisableCommand.parseAsync(["node", "cli", "plt_missing"])).rejects.toThrow();
|
|
2096
2978
|
expect(consoleSpy).toHaveBeenCalledWith("Error: Automation not found");
|
|
@@ -2099,7 +2981,11 @@ describe("branch coverage: ApiError error paths", () => {
|
|
|
2099
2981
|
});
|
|
2100
2982
|
it("automation trigger returns ApiError message", async () => {
|
|
2101
2983
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
2102
|
-
const exitSpy = vi
|
|
2984
|
+
const exitSpy = vi
|
|
2985
|
+
.spyOn(process, "exit")
|
|
2986
|
+
.mockImplementation((_code) => {
|
|
2987
|
+
throw new Error("exit");
|
|
2988
|
+
});
|
|
2103
2989
|
mockApiError(404, "Automation not found");
|
|
2104
2990
|
await expect(automationTriggerCommand.parseAsync(["node", "cli", "-a", "a1"])).rejects.toThrow();
|
|
2105
2991
|
expect(consoleSpy).toHaveBeenCalledWith("Error: Automation not found");
|
|
@@ -2108,7 +2994,11 @@ describe("branch coverage: ApiError error paths", () => {
|
|
|
2108
2994
|
});
|
|
2109
2995
|
it("billing credits purchase returns ApiError message", async () => {
|
|
2110
2996
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
2111
|
-
const exitSpy = vi
|
|
2997
|
+
const exitSpy = vi
|
|
2998
|
+
.spyOn(process, "exit")
|
|
2999
|
+
.mockImplementation((_code) => {
|
|
3000
|
+
throw new Error("exit");
|
|
3001
|
+
});
|
|
2112
3002
|
mockApiError(402, "Payment failed");
|
|
2113
3003
|
await expect(billingCreditsPurchaseCommand.parseAsync(["node", "cli", "-a", "10"])).rejects.toThrow();
|
|
2114
3004
|
expect(consoleSpy).toHaveBeenCalledWith("Error: Payment failed");
|
|
@@ -2117,7 +3007,11 @@ describe("branch coverage: ApiError error paths", () => {
|
|
|
2117
3007
|
});
|
|
2118
3008
|
it("billing subscription read returns ApiError message", async () => {
|
|
2119
3009
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
2120
|
-
const exitSpy = vi
|
|
3010
|
+
const exitSpy = vi
|
|
3011
|
+
.spyOn(process, "exit")
|
|
3012
|
+
.mockImplementation((_code) => {
|
|
3013
|
+
throw new Error("exit");
|
|
3014
|
+
});
|
|
2121
3015
|
mockApiError(404, "Subscription not found");
|
|
2122
3016
|
await expect(billingSubscriptionReadCommand.parseAsync(["node", "cli"])).rejects.toThrow();
|
|
2123
3017
|
expect(consoleSpy).toHaveBeenCalledWith("Error: Subscription not found");
|
|
@@ -2126,7 +3020,11 @@ describe("branch coverage: ApiError error paths", () => {
|
|
|
2126
3020
|
});
|
|
2127
3021
|
it("document list returns ApiError message", async () => {
|
|
2128
3022
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
2129
|
-
const exitSpy = vi
|
|
3023
|
+
const exitSpy = vi
|
|
3024
|
+
.spyOn(process, "exit")
|
|
3025
|
+
.mockImplementation((_code) => {
|
|
3026
|
+
throw new Error("exit");
|
|
3027
|
+
});
|
|
2130
3028
|
mockApiError(403, "Access denied");
|
|
2131
3029
|
await expect(documentListCommand.parseAsync(["node", "cli"])).rejects.toThrow();
|
|
2132
3030
|
expect(consoleSpy).toHaveBeenCalledWith("Error: Access denied");
|
|
@@ -2135,7 +3033,11 @@ describe("branch coverage: ApiError error paths", () => {
|
|
|
2135
3033
|
});
|
|
2136
3034
|
it("workspace member list returns ApiError message", async () => {
|
|
2137
3035
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
2138
|
-
const exitSpy = vi
|
|
3036
|
+
const exitSpy = vi
|
|
3037
|
+
.spyOn(process, "exit")
|
|
3038
|
+
.mockImplementation((_code) => {
|
|
3039
|
+
throw new Error("exit");
|
|
3040
|
+
});
|
|
2139
3041
|
mockApiError(403, "Not a member");
|
|
2140
3042
|
await expect(workspaceMemberListCommand.parseAsync(["node", "cli"])).rejects.toThrow();
|
|
2141
3043
|
expect(consoleSpy).toHaveBeenCalledWith("Error: Not a member");
|
|
@@ -2144,7 +3046,11 @@ describe("branch coverage: ApiError error paths", () => {
|
|
|
2144
3046
|
});
|
|
2145
3047
|
it("workflow cancel returns ApiError message", async () => {
|
|
2146
3048
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
2147
|
-
const exitSpy = vi
|
|
3049
|
+
const exitSpy = vi
|
|
3050
|
+
.spyOn(process, "exit")
|
|
3051
|
+
.mockImplementation((_code) => {
|
|
3052
|
+
throw new Error("exit");
|
|
3053
|
+
});
|
|
2148
3054
|
mockApiError(404, "Workflow not found");
|
|
2149
3055
|
await expect(workflowCancelCommand.parseAsync(["node", "cli", "-w", "wfr_abc"])).rejects.toThrow();
|
|
2150
3056
|
expect(consoleSpy).toHaveBeenCalledWith("Error: Workflow not found");
|
|
@@ -2153,7 +3059,11 @@ describe("branch coverage: ApiError error paths", () => {
|
|
|
2153
3059
|
});
|
|
2154
3060
|
it("workflow status returns ApiError message", async () => {
|
|
2155
3061
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
2156
|
-
const exitSpy = vi
|
|
3062
|
+
const exitSpy = vi
|
|
3063
|
+
.spyOn(process, "exit")
|
|
3064
|
+
.mockImplementation((_code) => {
|
|
3065
|
+
throw new Error("exit");
|
|
3066
|
+
});
|
|
2157
3067
|
mockApiError(404, "Run expired");
|
|
2158
3068
|
await expect(workflowStatusCommand.parseAsync(["node", "cli", "-w", "wfr_abc"])).rejects.toThrow();
|
|
2159
3069
|
expect(consoleSpy).toHaveBeenCalledWith("Error: Run expired");
|
|
@@ -2162,7 +3072,11 @@ describe("branch coverage: ApiError error paths", () => {
|
|
|
2162
3072
|
});
|
|
2163
3073
|
it("user preferences read returns ApiError message", async () => {
|
|
2164
3074
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
2165
|
-
const exitSpy = vi
|
|
3075
|
+
const exitSpy = vi
|
|
3076
|
+
.spyOn(process, "exit")
|
|
3077
|
+
.mockImplementation((_code) => {
|
|
3078
|
+
throw new Error("exit");
|
|
3079
|
+
});
|
|
2166
3080
|
mockApiError(401, "Unauthorized");
|
|
2167
3081
|
await expect(userPreferencesReadCommand.parseAsync(["node", "cli"])).rejects.toThrow();
|
|
2168
3082
|
expect(consoleSpy).toHaveBeenCalledWith("Error: Unauthorized");
|
|
@@ -2171,9 +3085,18 @@ describe("branch coverage: ApiError error paths", () => {
|
|
|
2171
3085
|
});
|
|
2172
3086
|
it("user preferences write returns ApiError message", async () => {
|
|
2173
3087
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
2174
|
-
const exitSpy = vi
|
|
3088
|
+
const exitSpy = vi
|
|
3089
|
+
.spyOn(process, "exit")
|
|
3090
|
+
.mockImplementation((_code) => {
|
|
3091
|
+
throw new Error("exit");
|
|
3092
|
+
});
|
|
2175
3093
|
mockApiError(400, "Invalid font size");
|
|
2176
|
-
await expect(userPreferencesWriteCommand.parseAsync([
|
|
3094
|
+
await expect(userPreferencesWriteCommand.parseAsync([
|
|
3095
|
+
"node",
|
|
3096
|
+
"cli",
|
|
3097
|
+
"--font-size",
|
|
3098
|
+
"xxx",
|
|
3099
|
+
])).rejects.toThrow();
|
|
2177
3100
|
expect(consoleSpy).toHaveBeenCalledWith("Error: Invalid font size");
|
|
2178
3101
|
consoleSpy.mockRestore();
|
|
2179
3102
|
exitSpy.mockRestore();
|
|
@@ -2189,27 +3112,40 @@ describe("branch coverage: empty/optional data branches", () => {
|
|
|
2189
3112
|
});
|
|
2190
3113
|
it("automation list with workspace option", async () => {
|
|
2191
3114
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
2192
|
-
mockApiRequest.mockResolvedValueOnce([
|
|
3115
|
+
mockApiRequest.mockResolvedValueOnce([
|
|
3116
|
+
{ id: "a1", name: "Test", status: "active", triggers: [] },
|
|
3117
|
+
]);
|
|
2193
3118
|
await automationListCommand.parseAsync(["node", "cli", "-w", "ws1"]);
|
|
2194
3119
|
expect(mockApiRequest).toHaveBeenCalledWith(expect.stringContaining("workspace_id=ws1"), expect.anything());
|
|
2195
3120
|
consoleSpy.mockRestore();
|
|
2196
3121
|
});
|
|
2197
3122
|
it("automation list shows 'none' when triggers are empty", async () => {
|
|
2198
3123
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
2199
|
-
mockApiRequest.mockResolvedValueOnce([
|
|
3124
|
+
mockApiRequest.mockResolvedValueOnce([
|
|
3125
|
+
{ id: "a1", name: "Untriggered", status: "active", triggers: [] },
|
|
3126
|
+
]);
|
|
2200
3127
|
await automationListCommand.parseAsync(["node", "cli"]);
|
|
2201
3128
|
expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("triggers=none"));
|
|
2202
3129
|
consoleSpy.mockRestore();
|
|
2203
3130
|
});
|
|
2204
3131
|
it("image create with save-to option", async () => {
|
|
2205
3132
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
2206
|
-
mockApiRequest.mockResolvedValueOnce({
|
|
3133
|
+
mockApiRequest.mockResolvedValueOnce({
|
|
3134
|
+
id: "img1",
|
|
3135
|
+
url: "https://cdn.example.com/img.png",
|
|
3136
|
+
created_at: "2026-06-08",
|
|
3137
|
+
workspace_id: "ws1",
|
|
3138
|
+
});
|
|
2207
3139
|
await imageCreateCommand.parseAsync(["node", "cli", "-p", "A cat"]);
|
|
2208
3140
|
consoleSpy.mockRestore();
|
|
2209
3141
|
});
|
|
2210
3142
|
it("conversation chat ApiError path", async () => {
|
|
2211
3143
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
2212
|
-
const exitSpy = vi
|
|
3144
|
+
const exitSpy = vi
|
|
3145
|
+
.spyOn(process, "exit")
|
|
3146
|
+
.mockImplementation((_code) => {
|
|
3147
|
+
throw new Error("exit");
|
|
3148
|
+
});
|
|
2213
3149
|
mockApiError(401, "Not authenticated");
|
|
2214
3150
|
await expect(conversationChatCommand.parseAsync(["node", "cli", "-m", "Hello"])).rejects.toThrow();
|
|
2215
3151
|
expect(consoleSpy).toHaveBeenCalledWith("Error: Not authenticated");
|
|
@@ -2218,7 +3154,11 @@ describe("branch coverage: empty/optional data branches", () => {
|
|
|
2218
3154
|
});
|
|
2219
3155
|
it("workspace list ApiError path", async () => {
|
|
2220
3156
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
2221
|
-
const exitSpy = vi
|
|
3157
|
+
const exitSpy = vi
|
|
3158
|
+
.spyOn(process, "exit")
|
|
3159
|
+
.mockImplementation((_code) => {
|
|
3160
|
+
throw new Error("exit");
|
|
3161
|
+
});
|
|
2222
3162
|
mockApiError(403, "Org not found");
|
|
2223
3163
|
await expect(workspaceListCommand.parseAsync(["node", "cli"])).rejects.toThrow();
|
|
2224
3164
|
expect(consoleSpy).toHaveBeenCalledWith("Error: Org not found");
|
|
@@ -2227,7 +3167,11 @@ describe("branch coverage: empty/optional data branches", () => {
|
|
|
2227
3167
|
});
|
|
2228
3168
|
it("org list ApiError path", async () => {
|
|
2229
3169
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
2230
|
-
const exitSpy = vi
|
|
3170
|
+
const exitSpy = vi
|
|
3171
|
+
.spyOn(process, "exit")
|
|
3172
|
+
.mockImplementation((_code) => {
|
|
3173
|
+
throw new Error("exit");
|
|
3174
|
+
});
|
|
2231
3175
|
mockApiError(401, "Token expired");
|
|
2232
3176
|
await expect(orgListCommand.parseAsync(["node", "cli"])).rejects.toThrow();
|
|
2233
3177
|
expect(consoleSpy).toHaveBeenCalledWith("Error: Token expired");
|
|
@@ -2236,7 +3180,11 @@ describe("branch coverage: empty/optional data branches", () => {
|
|
|
2236
3180
|
});
|
|
2237
3181
|
it("api-key create ApiError path", async () => {
|
|
2238
3182
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
2239
|
-
const exitSpy = vi
|
|
3183
|
+
const exitSpy = vi
|
|
3184
|
+
.spyOn(process, "exit")
|
|
3185
|
+
.mockImplementation((_code) => {
|
|
3186
|
+
throw new Error("exit");
|
|
3187
|
+
});
|
|
2240
3188
|
mockApiError(429, "Rate limit exceeded");
|
|
2241
3189
|
await expect(apiKeyCreateCommand.parseAsync(["node", "cli", "mykey"])).rejects.toThrow();
|
|
2242
3190
|
expect(consoleSpy).toHaveBeenCalledWith("Error: Rate limit exceeded");
|
|
@@ -2245,7 +3193,11 @@ describe("branch coverage: empty/optional data branches", () => {
|
|
|
2245
3193
|
});
|
|
2246
3194
|
it("plugin list ApiError path", async () => {
|
|
2247
3195
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
2248
|
-
const exitSpy = vi
|
|
3196
|
+
const exitSpy = vi
|
|
3197
|
+
.spyOn(process, "exit")
|
|
3198
|
+
.mockImplementation((_code) => {
|
|
3199
|
+
throw new Error("exit");
|
|
3200
|
+
});
|
|
2249
3201
|
mockApiError(403, "Permission denied");
|
|
2250
3202
|
await expect(pluginListCommand.parseAsync(["node", "cli"])).rejects.toThrow();
|
|
2251
3203
|
expect(consoleSpy).toHaveBeenCalledWith("Error: Permission denied");
|
|
@@ -2254,7 +3206,11 @@ describe("branch coverage: empty/optional data branches", () => {
|
|
|
2254
3206
|
});
|
|
2255
3207
|
it("billing status ApiError path", async () => {
|
|
2256
3208
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
2257
|
-
const exitSpy = vi
|
|
3209
|
+
const exitSpy = vi
|
|
3210
|
+
.spyOn(process, "exit")
|
|
3211
|
+
.mockImplementation((_code) => {
|
|
3212
|
+
throw new Error("exit");
|
|
3213
|
+
});
|
|
2258
3214
|
mockApiError(402, "Billing error");
|
|
2259
3215
|
await expect(billingStatusCommand.parseAsync(["node", "cli"])).rejects.toThrow();
|
|
2260
3216
|
expect(consoleSpy).toHaveBeenCalledWith("Error: Billing error");
|
|
@@ -2263,7 +3219,11 @@ describe("branch coverage: empty/optional data branches", () => {
|
|
|
2263
3219
|
});
|
|
2264
3220
|
it("chat send ApiError path", async () => {
|
|
2265
3221
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
2266
|
-
const exitSpy = vi
|
|
3222
|
+
const exitSpy = vi
|
|
3223
|
+
.spyOn(process, "exit")
|
|
3224
|
+
.mockImplementation((_code) => {
|
|
3225
|
+
throw new Error("exit");
|
|
3226
|
+
});
|
|
2267
3227
|
// chat.send uses native fetch (not apiRequest); mock fetch directly.
|
|
2268
3228
|
vi.spyOn(global, "fetch").mockResolvedValueOnce(new Response(JSON.stringify({ error: "Service unavailable" }), {
|
|
2269
3229
|
status: 503,
|
|
@@ -2275,7 +3235,11 @@ describe("branch coverage: empty/optional data branches", () => {
|
|
|
2275
3235
|
});
|
|
2276
3236
|
it("document read ApiError path", async () => {
|
|
2277
3237
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
2278
|
-
const exitSpy = vi
|
|
3238
|
+
const exitSpy = vi
|
|
3239
|
+
.spyOn(process, "exit")
|
|
3240
|
+
.mockImplementation((_code) => {
|
|
3241
|
+
throw new Error("exit");
|
|
3242
|
+
});
|
|
2279
3243
|
mockApiError(404, "Document not found");
|
|
2280
3244
|
await expect(documentReadCommand.parseAsync(["node", "cli", "-d", "doc1"])).rejects.toThrow();
|
|
2281
3245
|
expect(consoleSpy).toHaveBeenCalledWith("Error: Document not found");
|
|
@@ -2290,7 +3254,11 @@ describe("branch coverage: empty/optional data branches", () => {
|
|
|
2290
3254
|
});
|
|
2291
3255
|
it("workflow run ApiError path", async () => {
|
|
2292
3256
|
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => { });
|
|
2293
|
-
const exitSpy = vi
|
|
3257
|
+
const exitSpy = vi
|
|
3258
|
+
.spyOn(process, "exit")
|
|
3259
|
+
.mockImplementation((_code) => {
|
|
3260
|
+
throw new Error("exit");
|
|
3261
|
+
});
|
|
2294
3262
|
mockApiError(400, "Invalid workflow spec");
|
|
2295
3263
|
await expect(workflowRunCommand.parseAsync(["node", "cli", "-w", "wf1"])).rejects.toThrow();
|
|
2296
3264
|
expect(consoleSpy).toHaveBeenCalledWith("Error: Invalid workflow spec");
|
|
@@ -2315,7 +3283,13 @@ describe("Environment Variable Defaults", () => {
|
|
|
2315
3283
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
2316
3284
|
mockGetOrgId.mockReturnValue("env-org-123");
|
|
2317
3285
|
mockApiRequest.mockResolvedValueOnce({ members: [] });
|
|
2318
|
-
await orgMemberAddCommand.parseAsync([
|
|
3286
|
+
await orgMemberAddCommand.parseAsync([
|
|
3287
|
+
"node",
|
|
3288
|
+
"cli",
|
|
3289
|
+
"user@example.com",
|
|
3290
|
+
"--role",
|
|
3291
|
+
"admin",
|
|
3292
|
+
]);
|
|
2319
3293
|
expect(mockApiRequest).toHaveBeenCalledWith(expect.any(String), expect.objectContaining({
|
|
2320
3294
|
body: expect.stringContaining("env-org-123"),
|
|
2321
3295
|
}));
|
|
@@ -2325,7 +3299,15 @@ describe("Environment Variable Defaults", () => {
|
|
|
2325
3299
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
2326
3300
|
mockGetOrgId.mockReturnValue("env-org-123");
|
|
2327
3301
|
mockApiRequest.mockResolvedValueOnce({ members: [] });
|
|
2328
|
-
await orgMemberAddCommand.parseAsync([
|
|
3302
|
+
await orgMemberAddCommand.parseAsync([
|
|
3303
|
+
"node",
|
|
3304
|
+
"cli",
|
|
3305
|
+
"user@example.com",
|
|
3306
|
+
"--role",
|
|
3307
|
+
"admin",
|
|
3308
|
+
"--org",
|
|
3309
|
+
"cli-org-456",
|
|
3310
|
+
]);
|
|
2329
3311
|
expect(mockApiRequest).toHaveBeenCalledWith(expect.any(String), expect.objectContaining({
|
|
2330
3312
|
body: expect.stringContaining("cli-org-456"),
|
|
2331
3313
|
}));
|
|
@@ -2350,7 +3332,12 @@ describe("Environment Variable Defaults", () => {
|
|
|
2350
3332
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
2351
3333
|
mockGetWorkspaceId.mockReturnValue("env-workspace-789");
|
|
2352
3334
|
mockApiRequest.mockResolvedValueOnce([]);
|
|
2353
|
-
await workspaceMemberListCommand.parseAsync([
|
|
3335
|
+
await workspaceMemberListCommand.parseAsync([
|
|
3336
|
+
"node",
|
|
3337
|
+
"cli",
|
|
3338
|
+
"-w",
|
|
3339
|
+
"cli-workspace-xyz",
|
|
3340
|
+
]);
|
|
2354
3341
|
const calls = mockApiRequest.mock.calls;
|
|
2355
3342
|
expect(calls.length).toBeGreaterThan(0);
|
|
2356
3343
|
expect(calls[0]?.[0]).toContain("workspace_id=cli-workspace-xyz");
|
|
@@ -2375,11 +3362,17 @@ describe("Environment Variable Defaults", () => {
|
|
|
2375
3362
|
discoveredTools: ["tool1"],
|
|
2376
3363
|
});
|
|
2377
3364
|
await agentMcpRegisterCommand.parseAsync([
|
|
2378
|
-
"node",
|
|
2379
|
-
"
|
|
2380
|
-
"
|
|
2381
|
-
"-
|
|
2382
|
-
"-
|
|
3365
|
+
"node",
|
|
3366
|
+
"cli",
|
|
3367
|
+
"register",
|
|
3368
|
+
"-n",
|
|
3369
|
+
"my-mcp",
|
|
3370
|
+
"-u",
|
|
3371
|
+
"http://localhost:9000",
|
|
3372
|
+
"-t",
|
|
3373
|
+
"streamable-http",
|
|
3374
|
+
"-w",
|
|
3375
|
+
"explicit-workspace-888",
|
|
2383
3376
|
]);
|
|
2384
3377
|
expect(mockApiRequest).toHaveBeenCalledWith(expect.any(String), expect.objectContaining({
|
|
2385
3378
|
body: expect.stringContaining("explicit-workspace-888"),
|
|
@@ -2396,10 +3389,15 @@ describe("Environment Variable Defaults", () => {
|
|
|
2396
3389
|
discoveredTools: [],
|
|
2397
3390
|
});
|
|
2398
3391
|
await agentMcpRegisterCommand.parseAsync([
|
|
2399
|
-
"node",
|
|
2400
|
-
"
|
|
2401
|
-
"
|
|
2402
|
-
"-
|
|
3392
|
+
"node",
|
|
3393
|
+
"cli",
|
|
3394
|
+
"register",
|
|
3395
|
+
"-n",
|
|
3396
|
+
"my-mcp",
|
|
3397
|
+
"-u",
|
|
3398
|
+
"http://localhost:9000",
|
|
3399
|
+
"-t",
|
|
3400
|
+
"streamable-http",
|
|
2403
3401
|
]);
|
|
2404
3402
|
expect(mockApiRequest).toHaveBeenCalledWith(expect.any(String), expect.objectContaining({
|
|
2405
3403
|
body: expect.stringContaining("fallback-org-111"),
|
|
@@ -2417,7 +3415,12 @@ describe("Environment Variable Defaults", () => {
|
|
|
2417
3415
|
it("workspace member list uses OXAGEN_WORKSPACE_ID as default when no --workspace flag", async () => {
|
|
2418
3416
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
2419
3417
|
mockApiRequest.mockResolvedValueOnce([
|
|
2420
|
-
{
|
|
3418
|
+
{
|
|
3419
|
+
id: "user1",
|
|
3420
|
+
email: "user@test.com",
|
|
3421
|
+
role: "member",
|
|
3422
|
+
joined_at: "2024-01-01",
|
|
3423
|
+
},
|
|
2421
3424
|
]);
|
|
2422
3425
|
await workspaceMemberListCommand.parseAsync(["node", "cli"]);
|
|
2423
3426
|
const calls = mockApiRequest.mock.calls;
|
|
@@ -2428,11 +3431,18 @@ describe("Environment Variable Defaults", () => {
|
|
|
2428
3431
|
it("workspace member list uses explicit --workspace to override OXAGEN_WORKSPACE_ID", async () => {
|
|
2429
3432
|
const consoleSpy = vi.spyOn(console, "log").mockImplementation(() => { });
|
|
2430
3433
|
mockApiRequest.mockResolvedValueOnce([
|
|
2431
|
-
{
|
|
3434
|
+
{
|
|
3435
|
+
id: "user1",
|
|
3436
|
+
email: "user@test.com",
|
|
3437
|
+
role: "member",
|
|
3438
|
+
joined_at: "2024-01-01",
|
|
3439
|
+
},
|
|
2432
3440
|
]);
|
|
2433
3441
|
await workspaceMemberListCommand.parseAsync([
|
|
2434
|
-
"node",
|
|
2435
|
-
"
|
|
3442
|
+
"node",
|
|
3443
|
+
"cli",
|
|
3444
|
+
"-w",
|
|
3445
|
+
"explicit-ws",
|
|
2436
3446
|
]);
|
|
2437
3447
|
const calls = mockApiRequest.mock.calls;
|
|
2438
3448
|
expect(calls.length).toBeGreaterThan(0);
|