@openrig/cli 0.3.0 → 0.3.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/daemon/assets/plugins/openrig-core/.claude-plugin/plugin.json +15 -0
- package/daemon/assets/plugins/openrig-core/.codex-plugin/plugin.json +24 -0
- package/daemon/assets/plugins/openrig-core/LICENSE +200 -0
- package/daemon/assets/plugins/openrig-core/README.md +42 -0
- package/daemon/assets/plugins/openrig-core/hooks/claude.json +78 -0
- package/daemon/assets/plugins/openrig-core/hooks/codex.json +37 -0
- package/daemon/assets/{openrig-activity-hook-relay.cjs → plugins/openrig-core/hooks/scripts/activity-relay.cjs} +12 -0
- package/daemon/assets/plugins/openrig-core/hooks/scripts/compaction-restore-bridge.cjs +172 -0
- package/daemon/assets/plugins/openrig-core/skills/agent-startup-and-context-ingestion/SKILL.md +104 -0
- package/daemon/assets/plugins/openrig-core/skills/claude-compaction-restore/SKILL.md +131 -0
- package/daemon/assets/plugins/openrig-core/skills/claude-compaction-restore/scripts/precompact-hook.mjs +174 -0
- package/daemon/assets/plugins/openrig-core/skills/claude-compaction-restore/scripts/restore-from-jsonl.mjs +433 -0
- package/daemon/assets/plugins/openrig-core/skills/claude-compaction-restore/templates/compact-instruction.md +1 -0
- package/daemon/assets/plugins/openrig-core/skills/claude-compaction-restore/templates/post-compact-restore-instruction.md +1 -0
- package/daemon/assets/plugins/openrig-core/skills/forming-an-openrig-mental-model/SKILL.md +305 -0
- package/daemon/{specs/agents/shared/skills/rig-architect → assets/plugins/openrig-core/skills/openrig-architect}/SKILL.md +38 -19
- package/daemon/assets/plugins/openrig-core/skills/openrig-operator/SKILL.md +222 -0
- package/daemon/assets/plugins/openrig-core/skills/openrig-user/SKILL.md +597 -0
- package/daemon/assets/plugins/openrig-core/skills/queue-handoff/SKILL.md +122 -0
- package/daemon/assets/plugins/openrig-core/skills/seat-continuity-and-handover/SKILL.md +137 -0
- package/daemon/assets/vm-preview-fixtures/README.md +48 -0
- package/daemon/assets/vm-preview-fixtures/workflows/sample-basic-loop.yaml +79 -0
- package/daemon/dist/adapters/claude-code-adapter.d.ts +1 -3
- package/daemon/dist/adapters/claude-code-adapter.d.ts.map +1 -1
- package/daemon/dist/adapters/claude-code-adapter.js +17 -57
- package/daemon/dist/adapters/claude-code-adapter.js.map +1 -1
- package/daemon/dist/adapters/cmux-transport.d.ts.map +1 -1
- package/daemon/dist/adapters/cmux-transport.js +81 -2
- package/daemon/dist/adapters/cmux-transport.js.map +1 -1
- package/daemon/dist/adapters/cmux.d.ts +4 -0
- package/daemon/dist/adapters/cmux.d.ts.map +1 -1
- package/daemon/dist/adapters/cmux.js +87 -0
- package/daemon/dist/adapters/cmux.js.map +1 -1
- package/daemon/dist/adapters/codex-runtime-adapter.d.ts +14 -3
- package/daemon/dist/adapters/codex-runtime-adapter.d.ts.map +1 -1
- package/daemon/dist/adapters/codex-runtime-adapter.js +43 -57
- package/daemon/dist/adapters/codex-runtime-adapter.js.map +1 -1
- package/daemon/dist/db/migrations/040_workflow_specs_diagnostic.d.ts +32 -0
- package/daemon/dist/db/migrations/040_workflow_specs_diagnostic.d.ts.map +1 -0
- package/daemon/dist/db/migrations/040_workflow_specs_diagnostic.js +37 -0
- package/daemon/dist/db/migrations/040_workflow_specs_diagnostic.js.map +1 -0
- package/daemon/dist/domain/agent-manifest.d.ts.map +1 -1
- package/daemon/dist/domain/agent-manifest.js +116 -37
- package/daemon/dist/domain/agent-manifest.js.map +1 -1
- package/daemon/dist/domain/agent-resolver.js +1 -1
- package/daemon/dist/domain/agent-resolver.js.map +1 -1
- package/daemon/dist/domain/claude-compaction-enforcer.d.ts +81 -0
- package/daemon/dist/domain/claude-compaction-enforcer.d.ts.map +1 -0
- package/daemon/dist/domain/claude-compaction-enforcer.js +242 -0
- package/daemon/dist/domain/claude-compaction-enforcer.js.map +1 -0
- package/daemon/dist/domain/cmux-layout-service.d.ts +41 -0
- package/daemon/dist/domain/cmux-layout-service.d.ts.map +1 -0
- package/daemon/dist/domain/cmux-layout-service.js +184 -0
- package/daemon/dist/domain/cmux-layout-service.js.map +1 -0
- package/daemon/dist/domain/context-monitor.d.ts +15 -1
- package/daemon/dist/domain/context-monitor.d.ts.map +1 -1
- package/daemon/dist/domain/context-monitor.js +38 -3
- package/daemon/dist/domain/context-monitor.js.map +1 -1
- package/daemon/dist/domain/kernel-boot-tracker.d.ts +74 -0
- package/daemon/dist/domain/kernel-boot-tracker.d.ts.map +1 -0
- package/daemon/dist/domain/kernel-boot-tracker.js +213 -0
- package/daemon/dist/domain/kernel-boot-tracker.js.map +1 -0
- package/daemon/dist/domain/kernel-boot.d.ts +50 -0
- package/daemon/dist/domain/kernel-boot.d.ts.map +1 -0
- package/daemon/dist/domain/kernel-boot.js +147 -0
- package/daemon/dist/domain/kernel-boot.js.map +1 -0
- package/daemon/dist/domain/mission-control/mission-control-read-layer.d.ts +5 -0
- package/daemon/dist/domain/mission-control/mission-control-read-layer.d.ts.map +1 -1
- package/daemon/dist/domain/mission-control/mission-control-read-layer.js +16 -2
- package/daemon/dist/domain/mission-control/mission-control-read-layer.js.map +1 -1
- package/daemon/dist/domain/mission-control/mission-control-write-contract.d.ts.map +1 -1
- package/daemon/dist/domain/mission-control/mission-control-write-contract.js +3 -1
- package/daemon/dist/domain/mission-control/mission-control-write-contract.js.map +1 -1
- package/daemon/dist/domain/plugin-discovery-service.d.ts +150 -0
- package/daemon/dist/domain/plugin-discovery-service.d.ts.map +1 -0
- package/daemon/dist/domain/plugin-discovery-service.js +468 -0
- package/daemon/dist/domain/plugin-discovery-service.js.map +1 -0
- package/daemon/dist/domain/plugin-vendor-service.d.ts +54 -0
- package/daemon/dist/domain/plugin-vendor-service.d.ts.map +1 -0
- package/daemon/dist/domain/plugin-vendor-service.js +111 -0
- package/daemon/dist/domain/plugin-vendor-service.js.map +1 -0
- package/daemon/dist/domain/profile-resolver.d.ts +3 -3
- package/daemon/dist/domain/profile-resolver.d.ts.map +1 -1
- package/daemon/dist/domain/profile-resolver.js +7 -7
- package/daemon/dist/domain/profile-resolver.js.map +1 -1
- package/daemon/dist/domain/projection-planner.d.ts +7 -1
- package/daemon/dist/domain/projection-planner.d.ts.map +1 -1
- package/daemon/dist/domain/projection-planner.js +44 -4
- package/daemon/dist/domain/projection-planner.js.map +1 -1
- package/daemon/dist/domain/queue-repository.d.ts +8 -1
- package/daemon/dist/domain/queue-repository.d.ts.map +1 -1
- package/daemon/dist/domain/queue-repository.js +14 -5
- package/daemon/dist/domain/queue-repository.js.map +1 -1
- package/daemon/dist/domain/session-transport.d.ts.map +1 -1
- package/daemon/dist/domain/session-transport.js +33 -0
- package/daemon/dist/domain/session-transport.js.map +1 -1
- package/daemon/dist/domain/skill-library-discovery.d.ts +68 -0
- package/daemon/dist/domain/skill-library-discovery.d.ts.map +1 -0
- package/daemon/dist/domain/skill-library-discovery.js +144 -0
- package/daemon/dist/domain/skill-library-discovery.js.map +1 -0
- package/daemon/dist/domain/slices/slice-indexer.d.ts +19 -0
- package/daemon/dist/domain/slices/slice-indexer.d.ts.map +1 -1
- package/daemon/dist/domain/slices/slice-indexer.js +88 -6
- package/daemon/dist/domain/slices/slice-indexer.js.map +1 -1
- package/daemon/dist/domain/spec-library-service.d.ts +6 -0
- package/daemon/dist/domain/spec-library-service.d.ts.map +1 -1
- package/daemon/dist/domain/spec-library-service.js.map +1 -1
- package/daemon/dist/domain/spec-library-workflow-scanner.d.ts +43 -0
- package/daemon/dist/domain/spec-library-workflow-scanner.d.ts.map +1 -1
- package/daemon/dist/domain/spec-library-workflow-scanner.js +157 -3
- package/daemon/dist/domain/spec-library-workflow-scanner.js.map +1 -1
- package/daemon/dist/domain/spec-review-service.d.ts +1 -1
- package/daemon/dist/domain/spec-review-service.d.ts.map +1 -1
- package/daemon/dist/domain/spec-review-service.js +14 -1
- package/daemon/dist/domain/spec-review-service.js.map +1 -1
- package/daemon/dist/domain/types.d.ts +27 -7
- package/daemon/dist/domain/types.d.ts.map +1 -1
- package/daemon/dist/domain/types.js.map +1 -1
- package/daemon/dist/domain/user-settings/settings-store.d.ts +25 -1
- package/daemon/dist/domain/user-settings/settings-store.d.ts.map +1 -1
- package/daemon/dist/domain/user-settings/settings-store.js +186 -4
- package/daemon/dist/domain/user-settings/settings-store.js.map +1 -1
- package/daemon/dist/domain/workflow-spec-cache.d.ts +27 -0
- package/daemon/dist/domain/workflow-spec-cache.d.ts.map +1 -1
- package/daemon/dist/domain/workflow-spec-cache.js +59 -0
- package/daemon/dist/domain/workflow-spec-cache.js.map +1 -1
- package/daemon/dist/domain/workspace/default-workspace-scaffold.d.ts.map +1 -1
- package/daemon/dist/domain/workspace/default-workspace-scaffold.js +45 -0
- package/daemon/dist/domain/workspace/default-workspace-scaffold.js.map +1 -1
- package/daemon/dist/domain/workspace/getting-started-narrative.d.ts +15 -0
- package/daemon/dist/domain/workspace/getting-started-narrative.d.ts.map +1 -0
- package/daemon/dist/domain/workspace/getting-started-narrative.js +237 -0
- package/daemon/dist/domain/workspace/getting-started-narrative.js.map +1 -0
- package/daemon/dist/index.d.ts +2 -1
- package/daemon/dist/index.d.ts.map +1 -1
- package/daemon/dist/index.js +52 -17
- package/daemon/dist/index.js.map +1 -1
- package/daemon/dist/lib/pane-envelope.d.ts +7 -0
- package/daemon/dist/lib/pane-envelope.d.ts.map +1 -0
- package/daemon/dist/lib/pane-envelope.js +38 -0
- package/daemon/dist/lib/pane-envelope.js.map +1 -0
- package/daemon/dist/middleware/auth-bearer-token.d.ts +47 -5
- package/daemon/dist/middleware/auth-bearer-token.d.ts.map +1 -1
- package/daemon/dist/middleware/auth-bearer-token.js +109 -8
- package/daemon/dist/middleware/auth-bearer-token.js.map +1 -1
- package/daemon/dist/routes/kernel-status.d.ts +3 -0
- package/daemon/dist/routes/kernel-status.d.ts.map +1 -0
- package/daemon/dist/routes/kernel-status.js +40 -0
- package/daemon/dist/routes/kernel-status.js.map +1 -0
- package/daemon/dist/routes/mission-control.d.ts.map +1 -1
- package/daemon/dist/routes/mission-control.js +25 -2
- package/daemon/dist/routes/mission-control.js.map +1 -1
- package/daemon/dist/routes/missions.d.ts +3 -0
- package/daemon/dist/routes/missions.d.ts.map +1 -0
- package/daemon/dist/routes/missions.js +195 -0
- package/daemon/dist/routes/missions.js.map +1 -0
- package/daemon/dist/routes/plugins.d.ts +3 -0
- package/daemon/dist/routes/plugins.d.ts.map +1 -0
- package/daemon/dist/routes/plugins.js +223 -0
- package/daemon/dist/routes/plugins.js.map +1 -0
- package/daemon/dist/routes/rig-cmux.d.ts +3 -0
- package/daemon/dist/routes/rig-cmux.d.ts.map +1 -0
- package/daemon/dist/routes/rig-cmux.js +121 -0
- package/daemon/dist/routes/rig-cmux.js.map +1 -0
- package/daemon/dist/routes/skills.d.ts +3 -0
- package/daemon/dist/routes/skills.d.ts.map +1 -0
- package/daemon/dist/routes/skills.js +147 -0
- package/daemon/dist/routes/skills.js.map +1 -0
- package/daemon/dist/routes/slices.d.ts.map +1 -1
- package/daemon/dist/routes/slices.js +15 -0
- package/daemon/dist/routes/slices.js.map +1 -1
- package/daemon/dist/routes/spec-library.d.ts.map +1 -1
- package/daemon/dist/routes/spec-library.js +16 -1
- package/daemon/dist/routes/spec-library.js.map +1 -1
- package/daemon/dist/server.d.ts +31 -0
- package/daemon/dist/server.d.ts.map +1 -1
- package/daemon/dist/server.js +30 -0
- package/daemon/dist/server.js.map +1 -1
- package/daemon/dist/startup.d.ts.map +1 -1
- package/daemon/dist/startup.js +194 -5
- package/daemon/dist/startup.js.map +1 -1
- package/daemon/specs/agents/apps/vault-specialist/agent.yaml +0 -1
- package/daemon/specs/agents/conveyor/builder/agent.yaml +0 -1
- package/daemon/specs/agents/conveyor/lead/agent.yaml +0 -1
- package/daemon/specs/agents/conveyor/planner/agent.yaml +0 -1
- package/daemon/specs/agents/conveyor/reviewer/agent.yaml +0 -1
- package/daemon/specs/agents/design/product-designer/agent.yaml +0 -1
- package/daemon/specs/agents/development/implementer/agent.yaml +0 -1
- package/daemon/specs/agents/development/qa/agent.yaml +0 -1
- package/daemon/specs/agents/development/qa/guidance/role.md +0 -2
- package/daemon/specs/agents/orchestration/orchestrator/agent.yaml +0 -1
- package/daemon/specs/agents/research/analyst/agent.yaml +0 -1
- package/daemon/specs/agents/research/synthesizer/agent.yaml +0 -1
- package/daemon/specs/agents/review/independent-reviewer/agent.yaml +0 -1
- package/daemon/specs/agents/shared/agent.yaml +6 -6
- package/daemon/specs/agents/shared/skills/core/openrig-architect/SKILL.md +361 -0
- package/daemon/specs/agents/shared/skills/core/openrig-installer/SKILL.md +142 -0
- package/daemon/specs/agents/shared/skills/core/openrig-user/SKILL.md +6 -1
- package/daemon/specs/agents/shared/skills/core/openrig-user-settings/SKILL.md +4 -4
- package/daemon/specs/agents/shared/skills/core/rig-lifecycle/SKILL.md +116 -0
- package/daemon/specs/agents/shared/skills/pods/development-team/SKILL.md +0 -1
- package/daemon/specs/agents/shared/skills/pods/orchestration-team/SKILL.md +2 -2
- package/daemon/specs/agents/shared/skills/process/agent-browser/LOCAL-INSIGHTS.md +6 -6
- package/daemon/specs/agents/shared/skills/process/agent-browser/OPENRIG.md +40 -0
- package/daemon/specs/agents/shared/skills/process/agent-browser/SKILL.md +10 -0
- package/daemon/specs/agents/shared/skills/process/brainstorming/OPENRIG.md +48 -0
- package/daemon/specs/agents/shared/skills/process/brainstorming/SKILL.md +11 -0
- package/daemon/specs/agents/shared/skills/process/dogfood/SKILL.md +5 -0
- package/daemon/specs/agents/shared/skills/process/executing-plans/OPENRIG.md +56 -0
- package/daemon/specs/agents/shared/skills/process/executing-plans/SKILL.md +10 -0
- package/daemon/specs/agents/shared/skills/process/frontend-design/SKILL.md +5 -0
- package/daemon/specs/agents/shared/skills/process/systematic-debugging/SKILL.md +5 -0
- package/daemon/specs/agents/shared/skills/process/test-driven-development/SKILL.md +5 -0
- package/daemon/specs/agents/shared/skills/process/using-superpowers/OPENRIG.md +48 -0
- package/daemon/specs/agents/shared/skills/process/using-superpowers/SKILL.md +11 -0
- package/daemon/specs/agents/shared/skills/process/verification-before-completion/SKILL.md +5 -0
- package/daemon/specs/agents/shared/skills/process/writing-plans/OPENRIG.md +52 -0
- package/daemon/specs/agents/shared/skills/process/writing-plans/SKILL.md +12 -2
- package/daemon/specs/rigs/launch/kernel/agents/advisor/lead/agent.yaml +35 -0
- package/daemon/specs/rigs/launch/kernel/agents/advisor/lead/guidance/role.md +50 -0
- package/daemon/specs/rigs/launch/kernel/agents/advisor/lead/startup/context.md +37 -0
- package/daemon/specs/rigs/launch/kernel/agents/operator/agent/agent.yaml +35 -0
- package/daemon/specs/rigs/launch/kernel/agents/operator/agent/guidance/role.md +49 -0
- package/daemon/specs/rigs/launch/kernel/agents/operator/agent/startup/context.md +63 -0
- package/daemon/specs/rigs/launch/kernel/agents/queue/worker/agent.yaml +35 -0
- package/daemon/specs/rigs/launch/kernel/agents/queue/worker/guidance/role.md +33 -0
- package/daemon/specs/rigs/launch/kernel/agents/queue/worker/startup/context.md +30 -0
- package/daemon/specs/rigs/launch/kernel/culture/CULTURE.md +69 -0
- package/daemon/specs/rigs/launch/kernel/rig-claude-only.yaml +59 -0
- package/daemon/specs/rigs/launch/kernel/rig-codex-only.yaml +59 -0
- package/daemon/specs/rigs/launch/kernel/rig.yaml +69 -0
- package/dist/commands/config-init-workspace.d.ts.map +1 -1
- package/dist/commands/config-init-workspace.js +253 -0
- package/dist/commands/config-init-workspace.js.map +1 -1
- package/dist/commands/config.d.ts.map +1 -1
- package/dist/commands/config.js +11 -3
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/daemon.d.ts.map +1 -1
- package/dist/commands/daemon.js +53 -1
- package/dist/commands/daemon.js.map +1 -1
- package/dist/commands/heartbeat.d.ts.map +1 -1
- package/dist/commands/heartbeat.js +0 -5
- package/dist/commands/heartbeat.js.map +1 -1
- package/dist/commands/plugin.d.ts +4 -0
- package/dist/commands/plugin.d.ts.map +1 -0
- package/dist/commands/plugin.js +395 -0
- package/dist/commands/plugin.js.map +1 -0
- package/dist/commands/send.d.ts +8 -0
- package/dist/commands/send.d.ts.map +1 -1
- package/dist/commands/send.js +8 -0
- package/dist/commands/send.js.map +1 -1
- package/dist/commands/up.d.ts.map +1 -1
- package/dist/commands/up.js +13 -1
- package/dist/commands/up.js.map +1 -1
- package/dist/config-store.d.ts +18 -1
- package/dist/config-store.d.ts.map +1 -1
- package/dist/config-store.js +167 -4
- package/dist/config-store.js.map +1 -1
- package/dist/daemon-lifecycle.d.ts +20 -1
- package/dist/daemon-lifecycle.d.ts.map +1 -1
- package/dist/daemon-lifecycle.js +57 -7
- package/dist/daemon-lifecycle.js.map +1 -1
- package/dist/host-registry.d.ts +1 -1
- package/dist/host-registry.js +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/ui/dist/assets/index-C_Q5FczU.css +1 -0
- package/ui/dist/assets/index-Rl3ZBrUg.js +547 -0
- package/ui/dist/index.html +2 -2
- package/daemon/specs/agents/shared/skills/claude-compact-in-place/SKILL.md +0 -100
- package/daemon/specs/agents/shared/skills/process/containerized-e2e/SKILL.md +0 -256
- package/daemon/specs/agents/shared/skills/process/containerized-e2e/scripts/Dockerfile +0 -39
- package/daemon/specs/agents/shared/skills/process/containerized-e2e/scripts/build-e2e-image.sh +0 -37
- package/daemon/specs/agents/shared/skills/process/containerized-e2e/templates/control-plane-test.yaml +0 -40
- package/daemon/specs/agents/shared/skills/process/containerized-e2e/templates/e2e-report-template.md +0 -94
- package/daemon/specs/agents/shared/skills/process/containerized-e2e/templates/expansion-collision-fragment.yaml +0 -13
- package/daemon/specs/agents/shared/skills/process/containerized-e2e/templates/expansion-pod-fragment.yaml +0 -14
- package/ui/dist/assets/index-BDHU1JUK.js +0 -412
- package/ui/dist/assets/index-DXTyJSqu.css +0 -1
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
// V0.3.1 slice 12 walk-item 1 — mission scope data layer.
|
|
2
|
+
// V0.3.1 slice 13 walk-item 7 — extended with workflow_spec frontmatter
|
|
3
|
+
// + projected topology spec graph.
|
|
4
|
+
//
|
|
5
|
+
// GET /api/missions/:missionId — returns aggregated mission metadata
|
|
6
|
+
// (missionPath + slices + optional workflow_spec declaration + optional
|
|
7
|
+
// projected topology). Powers the Mission Overview / Progress / Topology
|
|
8
|
+
// tabs in the Project surface; pairs with useScopeMarkdown for README /
|
|
9
|
+
// PROGRESS content via the existing /api/files/read route.
|
|
10
|
+
//
|
|
11
|
+
// Returns:
|
|
12
|
+
// 200 {
|
|
13
|
+
// missionId, missionPath, slices,
|
|
14
|
+
// workflow_spec: { name, version } | null,
|
|
15
|
+
// topology: { specGraph: SpecGraphPayload | null } | null
|
|
16
|
+
// }
|
|
17
|
+
// 404 { error: "mission_not_found" } when no slices match
|
|
18
|
+
// 503 { error: "slices_indexer_unavailable" } when indexer not wired
|
|
19
|
+
// 503 { error: "slices_root_not_configured" } when indexer not ready
|
|
20
|
+
//
|
|
21
|
+
// workflow_spec is parsed lazily from <missionPath>/README.md frontmatter
|
|
22
|
+
// using the same parser the slice-indexer uses. topology.specGraph is
|
|
23
|
+
// projected via projectSpecGraph(spec, null) when the spec is in the
|
|
24
|
+
// WorkflowSpecCache; { specGraph: null } when declared but not cached;
|
|
25
|
+
// null when nothing is declared.
|
|
26
|
+
import { Hono } from "hono";
|
|
27
|
+
import * as fs from "node:fs";
|
|
28
|
+
import * as path from "node:path";
|
|
29
|
+
import { parseWorkflowSpecRef } from "../domain/slices/slice-indexer.js";
|
|
30
|
+
import { projectSpecGraph } from "../domain/workflow/slice-workflow-projection.js";
|
|
31
|
+
export function missionsRoutes() {
|
|
32
|
+
const app = new Hono();
|
|
33
|
+
app.get("/:missionId", (c) => {
|
|
34
|
+
const indexer = c.get("sliceIndexer");
|
|
35
|
+
if (!indexer) {
|
|
36
|
+
return c.json({
|
|
37
|
+
error: "slices_indexer_unavailable",
|
|
38
|
+
hint: "Mission data layer requires the SliceIndexer to be wired into AppDeps.",
|
|
39
|
+
}, 503);
|
|
40
|
+
}
|
|
41
|
+
if (!indexer.isReady()) {
|
|
42
|
+
return c.json({
|
|
43
|
+
error: "slices_root_not_configured",
|
|
44
|
+
hint: "Run rig config init-workspace, or set workspace.slices_root to workspace/missions. Supported shape: missions/<mission>/slices/<slice>.",
|
|
45
|
+
}, 503);
|
|
46
|
+
}
|
|
47
|
+
const missionId = c.req.param("missionId");
|
|
48
|
+
const allSlices = indexer.list();
|
|
49
|
+
const slices = allSlices.filter((s) => s.missionId === missionId);
|
|
50
|
+
if (slices.length === 0) {
|
|
51
|
+
return c.json({ error: "mission_not_found", missionId }, 404);
|
|
52
|
+
}
|
|
53
|
+
const missionPath = computeMissionPath(slices[0]);
|
|
54
|
+
const workflowSpec = readMissionWorkflowSpec(missionPath);
|
|
55
|
+
const topology = computeMissionTopology(workflowSpec, c.get("workflowSpecCache"));
|
|
56
|
+
const status = readMissionStatus(missionPath);
|
|
57
|
+
return c.json({
|
|
58
|
+
missionId,
|
|
59
|
+
missionPath,
|
|
60
|
+
slices,
|
|
61
|
+
workflow_spec: workflowSpec,
|
|
62
|
+
topology,
|
|
63
|
+
status,
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
// Slice 18 §3.5 — Mark mission complete (Getting Started complete-and-hide).
|
|
67
|
+
// Writes `status: complete` to the mission README.md frontmatter; the UI
|
|
68
|
+
// storytelling preview gates on this so completed missions disappear from
|
|
69
|
+
// the band. The daemon is the audit-trail surface; the UI maintains
|
|
70
|
+
// an optimistic local mirror via localStorage so the hide is instant.
|
|
71
|
+
app.post("/:missionId/complete", (c) => {
|
|
72
|
+
const indexer = c.get("sliceIndexer");
|
|
73
|
+
if (!indexer) {
|
|
74
|
+
return c.json({ error: "slices_indexer_unavailable" }, 503);
|
|
75
|
+
}
|
|
76
|
+
const missionId = c.req.param("missionId");
|
|
77
|
+
const allSlices = indexer.list();
|
|
78
|
+
const slices = allSlices.filter((s) => s.missionId === missionId);
|
|
79
|
+
if (slices.length === 0) {
|
|
80
|
+
return c.json({ error: "mission_not_found", missionId }, 404);
|
|
81
|
+
}
|
|
82
|
+
const missionPath = computeMissionPath(slices[0]);
|
|
83
|
+
try {
|
|
84
|
+
writeMissionStatusComplete(missionPath);
|
|
85
|
+
}
|
|
86
|
+
catch (err) {
|
|
87
|
+
return c.json({
|
|
88
|
+
error: "mission_complete_write_failed",
|
|
89
|
+
missionId,
|
|
90
|
+
message: err.message,
|
|
91
|
+
}, 500);
|
|
92
|
+
}
|
|
93
|
+
return c.json({ missionId, status: "complete" });
|
|
94
|
+
});
|
|
95
|
+
return app;
|
|
96
|
+
}
|
|
97
|
+
/** Slice 18 §3.5 — write `status: complete` to a mission README's
|
|
98
|
+
* frontmatter, creating the frontmatter block when absent and
|
|
99
|
+
* replacing an existing status field when present. Idempotent.
|
|
100
|
+
* Preserves unrelated frontmatter fields. */
|
|
101
|
+
function writeMissionStatusComplete(missionPath) {
|
|
102
|
+
const readmePath = path.join(missionPath, "README.md");
|
|
103
|
+
let body = fs.existsSync(readmePath) ? fs.readFileSync(readmePath, "utf-8") : "";
|
|
104
|
+
const fmMatch = body.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
105
|
+
if (fmMatch) {
|
|
106
|
+
const fmInner = fmMatch[1] ?? "";
|
|
107
|
+
const statusLineRegex = /^\s*status\s*:\s*[^\r\n]*$/m;
|
|
108
|
+
let newFm;
|
|
109
|
+
if (statusLineRegex.test(fmInner)) {
|
|
110
|
+
newFm = fmInner.replace(statusLineRegex, "status: complete");
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
newFm = fmInner.trimEnd() + "\nstatus: complete";
|
|
114
|
+
}
|
|
115
|
+
body = body.replace(fmMatch[0], `---\n${newFm}\n---`);
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
body = `---\nstatus: complete\n---\n${body}`;
|
|
119
|
+
}
|
|
120
|
+
fs.writeFileSync(readmePath, body);
|
|
121
|
+
}
|
|
122
|
+
/** Derive the mission folder's absolute path from any slice's
|
|
123
|
+
* `slicePath`. Slices live at
|
|
124
|
+
* `<missionsRoot>/<missionId>/slices/<sliceName>` per the workspace
|
|
125
|
+
* contract, so going up two levels yields the mission folder. */
|
|
126
|
+
function computeMissionPath(slice) {
|
|
127
|
+
return path.resolve(slice.slicePath, "..", "..");
|
|
128
|
+
}
|
|
129
|
+
/** Slice 18 §3.5 — parse the `status` field from the mission README's
|
|
130
|
+
* frontmatter. Returns the string when present (no enum validation —
|
|
131
|
+
* v0 callers care primarily about the "complete" value but other
|
|
132
|
+
* workflow states may appear), or null when the README is missing /
|
|
133
|
+
* the field is absent. Powers the durable storytelling-filter for
|
|
134
|
+
* Getting Started complete-and-hide. */
|
|
135
|
+
function readMissionStatus(missionPath) {
|
|
136
|
+
const readmePath = path.join(missionPath, "README.md");
|
|
137
|
+
if (!fs.existsSync(readmePath))
|
|
138
|
+
return null;
|
|
139
|
+
const raw = fs.readFileSync(readmePath, "utf-8");
|
|
140
|
+
const fm = parseSimpleFrontmatter(raw);
|
|
141
|
+
const value = fm["status"];
|
|
142
|
+
return typeof value === "string" && value.length > 0 ? value : null;
|
|
143
|
+
}
|
|
144
|
+
/** V0.3.1 slice 13 walk-item 7 — parse `workflow_spec` from the mission
|
|
145
|
+
* README's frontmatter. Returns null when the README is missing or the
|
|
146
|
+
* field is absent / malformed. Uses the same parseWorkflowSpecRef
|
|
147
|
+
* helper the slice-indexer uses so both surfaces stay in lockstep. */
|
|
148
|
+
function readMissionWorkflowSpec(missionPath) {
|
|
149
|
+
const readmePath = path.join(missionPath, "README.md");
|
|
150
|
+
if (!fs.existsSync(readmePath))
|
|
151
|
+
return null;
|
|
152
|
+
const raw = fs.readFileSync(readmePath, "utf-8");
|
|
153
|
+
const fm = parseSimpleFrontmatter(raw);
|
|
154
|
+
return parseWorkflowSpecRef(fm["workflow_spec"]);
|
|
155
|
+
}
|
|
156
|
+
/** Minimal frontmatter parser. The slice-indexer's parseFrontmatter is
|
|
157
|
+
* private; duplicating the v0 shape here is cheaper than exposing
|
|
158
|
+
* internal API and keeps the missions route's surface minimal. */
|
|
159
|
+
function parseSimpleFrontmatter(text) {
|
|
160
|
+
const m = text.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
161
|
+
if (!m)
|
|
162
|
+
return {};
|
|
163
|
+
const out = {};
|
|
164
|
+
for (const line of m[1].split(/\r?\n/)) {
|
|
165
|
+
const trimmed = line.trim();
|
|
166
|
+
if (!trimmed || trimmed.startsWith("#"))
|
|
167
|
+
continue;
|
|
168
|
+
const colonIdx = trimmed.indexOf(":");
|
|
169
|
+
if (colonIdx === -1)
|
|
170
|
+
continue;
|
|
171
|
+
const key = trimmed.slice(0, colonIdx).trim();
|
|
172
|
+
let value = trimmed.slice(colonIdx + 1).trim();
|
|
173
|
+
if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) {
|
|
174
|
+
value = value.slice(1, -1);
|
|
175
|
+
}
|
|
176
|
+
out[key] = value;
|
|
177
|
+
}
|
|
178
|
+
return out;
|
|
179
|
+
}
|
|
180
|
+
/** V0.3.1 slice 13 walk-item 7 — project the spec graph when both the
|
|
181
|
+
* declaration AND the cached spec are present. Returns the topology
|
|
182
|
+
* envelope with `specGraph: null` when declared but not yet cached;
|
|
183
|
+
* returns `null` for the whole envelope when nothing is declared. */
|
|
184
|
+
function computeMissionTopology(workflowSpec, specCache) {
|
|
185
|
+
if (!workflowSpec)
|
|
186
|
+
return null;
|
|
187
|
+
if (!specCache)
|
|
188
|
+
return { specGraph: null };
|
|
189
|
+
const row = specCache.getByNameVersion(workflowSpec.name, workflowSpec.version);
|
|
190
|
+
if (!row)
|
|
191
|
+
return { specGraph: null };
|
|
192
|
+
// WorkflowSpecRow.spec is the WorkflowSpec object the projector expects.
|
|
193
|
+
return { specGraph: projectSpecGraph(row.spec, null) };
|
|
194
|
+
}
|
|
195
|
+
//# sourceMappingURL=missions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"missions.js","sourceRoot":"","sources":["../../src/routes/missions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugins.d.ts","sourceRoot":"","sources":["../../src/routes/plugins.ts"],"names":[],"mappings":"AAwCA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAkE5B,wBAAgB,aAAa,IAAI,IAAI,CA4HpC"}
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
// Phase 3a slice 3.3 — Plugins HTTP routes (read-only).
|
|
2
|
+
//
|
|
3
|
+
// SC-29 EXCEPTION #8 declared verbatim:
|
|
4
|
+
// "Slice 3.3 (UI plugin surface) requires daemon-side plugin-discovery-service
|
|
5
|
+
// + 3 HTTP routes (GET /api/plugins, GET /api/plugins/:id, GET /api/plugins/:id/used-by)
|
|
6
|
+
// as backing API. No additional state, no SQL migration, no mutation routes.
|
|
7
|
+
// Read-only discovery surface aggregating filesystem-scan unions per
|
|
8
|
+
// DESIGN.md §5.4. Per IMPL-PRD §3.3 'Code touches' this allocation is explicit;
|
|
9
|
+
// documenting in compliance with banked SC-29 verbatim-declaration rule."
|
|
10
|
+
//
|
|
11
|
+
// SC-29 EXCEPTION #11 (slice 28 library-explorer-finishing) declared verbatim:
|
|
12
|
+
// "Slice 28 (Library Explorer finishing — founder-walk follow-up) requires:
|
|
13
|
+
// (a) two additive read-only HTTP routes — GET /api/plugins/:id/files/list
|
|
14
|
+
// and GET /api/plugins/:id/files/read — that wrap the existing path-safety
|
|
15
|
+
// machinery (resolveAllowedDirectory/File) with the discovered plugin's
|
|
16
|
+
// absolute path acting as a synthetic single-root allowlist. Enables
|
|
17
|
+
// docs-browser file navigation of a plugin's on-disk folder without
|
|
18
|
+
// requiring the operator to allowlist ~/.openrig/plugins/ in
|
|
19
|
+
// OPENRIG_FILES_ALLOWLIST.
|
|
20
|
+
// (b) one PluginEntry shape extension — skillCount: number — populated in
|
|
21
|
+
// detectPlugin() by readdir of <plugin>/skills/. Surfaces skill-count in
|
|
22
|
+
// the plugin list response so PluginsIndexPage can render the column
|
|
23
|
+
// without an N+1 detail fetch per row.
|
|
24
|
+
// No additional state, no SQL migration, no write mutations on plugin
|
|
25
|
+
// folders. Read-only docs-browser surface per slice 28 founder direction
|
|
26
|
+
// 'finishing it is 0.3.1 work, not 0.3.2'. Routing decision
|
|
27
|
+
// qitem-20260513042155-f31c11c3 (orch OPT-A authorization)."
|
|
28
|
+
//
|
|
29
|
+
// Endpoint shape:
|
|
30
|
+
// GET /api/plugins → PluginEntry[] (?runtime=, ?source= filters)
|
|
31
|
+
// GET /api/plugins/:id → PluginDetail (404 when unknown)
|
|
32
|
+
// GET /api/plugins/:id/used-by → AgentReference[]
|
|
33
|
+
// GET /api/plugins/:id/files/list?path=<rel> → FilesListResponse (slice 28)
|
|
34
|
+
// GET /api/plugins/:id/files/read?path=<rel> → FilesReadResponse (slice 28)
|
|
35
|
+
//
|
|
36
|
+
// All endpoints return 503 when the service is not provisioned in context
|
|
37
|
+
// (consistent with the existing daemon route pattern for optional services).
|
|
38
|
+
// /files/list + /files/read use the discovered plugin path as a synthetic
|
|
39
|
+
// AllowlistRoot + reuse resolveAllowedDirectory/File for path-safety.
|
|
40
|
+
import { Hono } from "hono";
|
|
41
|
+
import * as fs from "node:fs";
|
|
42
|
+
import * as path from "node:path";
|
|
43
|
+
import { resolveAllowedDirectory, resolveAllowedFile, FilePathSafetyError, } from "../domain/files/path-safety.js";
|
|
44
|
+
import { sha256Hex } from "../domain/files/file-write-service.js";
|
|
45
|
+
import { FILE_READ_TRUNCATION_BYTES } from "./files.js";
|
|
46
|
+
function getService(c) {
|
|
47
|
+
return c.get("pluginDiscoveryService");
|
|
48
|
+
}
|
|
49
|
+
function parseRuntimeFilter(value) {
|
|
50
|
+
if (value === "claude" || value === "codex")
|
|
51
|
+
return value;
|
|
52
|
+
return undefined;
|
|
53
|
+
}
|
|
54
|
+
function parseSourceFilter(value) {
|
|
55
|
+
if (value === "vendored" || value === "claude-cache" || value === "codex-cache")
|
|
56
|
+
return value;
|
|
57
|
+
return undefined;
|
|
58
|
+
}
|
|
59
|
+
function pluginRootAllowlist(absolutePath) {
|
|
60
|
+
// Synthetic single-root allowlist scoped to the plugin's folder.
|
|
61
|
+
// Reuses the existing path-safety helpers for ../ escape / symlink
|
|
62
|
+
// realpath containment checks without any allowlist env-var coupling
|
|
63
|
+
// (operator does not need to declare plugin paths in OPENRIG_FILES_ALLOWLIST).
|
|
64
|
+
//
|
|
65
|
+
// Normalize via fs.realpathSync so the containment check (realpath vs
|
|
66
|
+
// canonicalPath) holds on platforms where the input path is itself
|
|
67
|
+
// a symlink chain (e.g. macOS /tmp → /private/tmp, /var/folders →
|
|
68
|
+
// /private/var/folders). Matches decodeAllowlist's normalization in
|
|
69
|
+
// path-safety.ts.
|
|
70
|
+
let canonical;
|
|
71
|
+
try {
|
|
72
|
+
canonical = fs.realpathSync(absolutePath);
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
canonical = path.resolve(absolutePath);
|
|
76
|
+
}
|
|
77
|
+
return [{ name: "plugin", canonicalPath: canonical }];
|
|
78
|
+
}
|
|
79
|
+
function pathSafetyErrorResponse(c, err) {
|
|
80
|
+
const status = err.code === "root_unknown" ? 400
|
|
81
|
+
: err.code === "path_invalid" || err.code === "path_escape" ? 400
|
|
82
|
+
: err.code === "stat_failed" ? 404
|
|
83
|
+
: err.code === "not_a_file" || err.code === "not_a_directory" ? 400
|
|
84
|
+
: 500;
|
|
85
|
+
return c.json({ error: err.code, message: err.message, ...(err.details ?? {}) }, status);
|
|
86
|
+
}
|
|
87
|
+
export function pluginsRoutes() {
|
|
88
|
+
const router = new Hono();
|
|
89
|
+
// GET / — list discoverable plugins
|
|
90
|
+
router.get("/", (c) => {
|
|
91
|
+
const service = getService(c);
|
|
92
|
+
if (!service)
|
|
93
|
+
return c.json({ error: "plugin_discovery_unavailable" }, 503);
|
|
94
|
+
const runtimeFilter = parseRuntimeFilter(c.req.query("runtime"));
|
|
95
|
+
const sourceFilter = parseSourceFilter(c.req.query("source"));
|
|
96
|
+
// Slice 3.3 fix-C — DESIGN §5.4 union 4th category: rig-bundled
|
|
97
|
+
// <cwd>/.claude/plugins/* + <cwd>/.codex/plugins/*. The API caller
|
|
98
|
+
// (UI in rig context, CLI in slice 3.4) passes ?cwd=<path> when
|
|
99
|
+
// they want the rig-cwd discoveries included; the Library page
|
|
100
|
+
// omits it (cross-cutting view).
|
|
101
|
+
const cwd = c.req.query("cwd");
|
|
102
|
+
const cwdScanRoots = cwd ? [cwd] : undefined;
|
|
103
|
+
const plugins = service.listPlugins({ runtimeFilter, sourceFilter, cwdScanRoots });
|
|
104
|
+
return c.json(plugins);
|
|
105
|
+
});
|
|
106
|
+
// GET /:id/used-by — reverse query for agents referencing this plugin.
|
|
107
|
+
// Mounted BEFORE /:id so the literal sub-path doesn't get eaten by the
|
|
108
|
+
// bare-param catchall (per spec-library-routes Phase A R1 SSE route-order
|
|
109
|
+
// lesson banked in that file).
|
|
110
|
+
router.get("/:id/used-by", (c) => {
|
|
111
|
+
const service = getService(c);
|
|
112
|
+
if (!service)
|
|
113
|
+
return c.json({ error: "plugin_discovery_unavailable" }, 503);
|
|
114
|
+
const id = c.req.param("id");
|
|
115
|
+
return c.json(service.findUsedBy(id));
|
|
116
|
+
});
|
|
117
|
+
// Slice 28 — GET /:id/files/list?path=<rel>
|
|
118
|
+
// Lists directory entries inside the plugin's source folder. Uses the
|
|
119
|
+
// existing path-safety helpers with a synthetic single-root allowlist
|
|
120
|
+
// built from the discovered plugin's absolute path. Mounted BEFORE the
|
|
121
|
+
// bare /:id route (same route-order discipline as /:id/used-by).
|
|
122
|
+
router.get("/:id/files/list", (c) => {
|
|
123
|
+
const service = getService(c);
|
|
124
|
+
if (!service)
|
|
125
|
+
return c.json({ error: "plugin_discovery_unavailable" }, 503);
|
|
126
|
+
const id = c.req.param("id");
|
|
127
|
+
const detail = service.getPlugin(id);
|
|
128
|
+
if (!detail)
|
|
129
|
+
return c.notFound();
|
|
130
|
+
const relativePath = c.req.query("path") ?? "";
|
|
131
|
+
try {
|
|
132
|
+
const allowlist = pluginRootAllowlist(detail.entry.path);
|
|
133
|
+
const resolved = resolveAllowedDirectory(allowlist, "plugin", relativePath);
|
|
134
|
+
const entries = fs.readdirSync(resolved, { withFileTypes: true });
|
|
135
|
+
return c.json({
|
|
136
|
+
pluginId: id,
|
|
137
|
+
path: relativePath,
|
|
138
|
+
entries: entries
|
|
139
|
+
.map((entry) => {
|
|
140
|
+
const fullPath = path.join(resolved, entry.name);
|
|
141
|
+
let stat = null;
|
|
142
|
+
try {
|
|
143
|
+
stat = fs.statSync(fullPath);
|
|
144
|
+
}
|
|
145
|
+
catch { /* skip stat-failed */ }
|
|
146
|
+
return {
|
|
147
|
+
name: entry.name,
|
|
148
|
+
type: entry.isDirectory() ? "dir" : entry.isFile() ? "file" : "other",
|
|
149
|
+
size: stat?.isFile() ? stat.size : null,
|
|
150
|
+
mtime: stat ? stat.mtime.toISOString() : null,
|
|
151
|
+
};
|
|
152
|
+
})
|
|
153
|
+
.sort((a, b) => {
|
|
154
|
+
if (a.type !== b.type)
|
|
155
|
+
return a.type === "dir" ? -1 : 1;
|
|
156
|
+
return a.name.localeCompare(b.name);
|
|
157
|
+
}),
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
catch (err) {
|
|
161
|
+
if (err instanceof FilePathSafetyError)
|
|
162
|
+
return pathSafetyErrorResponse(c, err);
|
|
163
|
+
return c.json({ error: "list_failed", message: err instanceof Error ? err.message : String(err) }, 500);
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
// Slice 28 — GET /:id/files/read?path=<rel>
|
|
167
|
+
// Reads a file inside the plugin's source folder. Same truncation cap
|
|
168
|
+
// semantics as /api/files/read (FILE_READ_TRUNCATION_BYTES; hash over
|
|
169
|
+
// full content for honest edit-conflict semantics — but plugin folders
|
|
170
|
+
// are read-only at v0 so the hash is informational only).
|
|
171
|
+
router.get("/:id/files/read", (c) => {
|
|
172
|
+
const service = getService(c);
|
|
173
|
+
if (!service)
|
|
174
|
+
return c.json({ error: "plugin_discovery_unavailable" }, 503);
|
|
175
|
+
const id = c.req.param("id");
|
|
176
|
+
const detail = service.getPlugin(id);
|
|
177
|
+
if (!detail)
|
|
178
|
+
return c.notFound();
|
|
179
|
+
const relativePath = c.req.query("path") ?? "";
|
|
180
|
+
if (!relativePath)
|
|
181
|
+
return c.json({ error: "path_required" }, 400);
|
|
182
|
+
try {
|
|
183
|
+
const allowlist = pluginRootAllowlist(detail.entry.path);
|
|
184
|
+
const resolved = resolveAllowedFile(allowlist, "plugin", relativePath);
|
|
185
|
+
const stat = fs.statSync(resolved);
|
|
186
|
+
const fullContent = fs.readFileSync(resolved);
|
|
187
|
+
const truncated = stat.size > FILE_READ_TRUNCATION_BYTES;
|
|
188
|
+
const returnedContent = truncated
|
|
189
|
+
? fullContent.subarray(0, FILE_READ_TRUNCATION_BYTES)
|
|
190
|
+
: fullContent;
|
|
191
|
+
return c.json({
|
|
192
|
+
pluginId: id,
|
|
193
|
+
path: relativePath,
|
|
194
|
+
absolutePath: resolved,
|
|
195
|
+
content: returnedContent.toString("utf-8"),
|
|
196
|
+
mtime: stat.mtime.toISOString(),
|
|
197
|
+
contentHash: sha256Hex(fullContent),
|
|
198
|
+
size: stat.size,
|
|
199
|
+
truncated,
|
|
200
|
+
truncatedAtBytes: truncated ? FILE_READ_TRUNCATION_BYTES : null,
|
|
201
|
+
totalBytes: stat.size,
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
catch (err) {
|
|
205
|
+
if (err instanceof FilePathSafetyError)
|
|
206
|
+
return pathSafetyErrorResponse(c, err);
|
|
207
|
+
return c.json({ error: "read_failed", message: err instanceof Error ? err.message : String(err) }, 500);
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
// GET /:id — plugin detail
|
|
211
|
+
router.get("/:id", (c) => {
|
|
212
|
+
const service = getService(c);
|
|
213
|
+
if (!service)
|
|
214
|
+
return c.json({ error: "plugin_discovery_unavailable" }, 503);
|
|
215
|
+
const id = c.req.param("id");
|
|
216
|
+
const detail = service.getPlugin(id);
|
|
217
|
+
if (!detail)
|
|
218
|
+
return c.notFound();
|
|
219
|
+
return c.json(detail);
|
|
220
|
+
});
|
|
221
|
+
return router;
|
|
222
|
+
}
|
|
223
|
+
//# sourceMappingURL=plugins.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugins.js","sourceRoot":"","sources":["../../src/routes/plugins.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rig-cmux.d.ts","sourceRoot":"","sources":["../../src/routes/rig-cmux.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAK5B,eAAO,MAAM,aAAa,4EAAa,CAAC"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
// Slice 24 — POST /api/rigs/:rigId/cmux/launch.
|
|
2
|
+
//
|
|
3
|
+
// Per-rig "Launch in CMUX" endpoint. Coordination:
|
|
4
|
+
// 1. rigRepo.getRig(rigId) → 404 if missing
|
|
5
|
+
// 2. cmuxAdapter.isAvailable() → 503 if cmux not connected
|
|
6
|
+
// 3. nodeInventoryFn(rigId) → map logicalId → canonicalSessionName
|
|
7
|
+
// 4. order agents by rig.nodes DB order (ORDER BY created_at = pod-then-member from spec)
|
|
8
|
+
// 5. filter to running (has canonicalSessionName) → 412 if none running
|
|
9
|
+
// 6. chunkAgents into MAX_PER_WORKSPACE-sized chunks
|
|
10
|
+
// 7. pick non-colliding workspace name per chunk
|
|
11
|
+
// (auto-append -2/-3/... per README R2 + multi-workspace handling)
|
|
12
|
+
// 8. cmuxLayoutService.buildWorkspace per chunk (sequential)
|
|
13
|
+
// → 500 with partial info if any buildWorkspace fails mid-flight
|
|
14
|
+
// 9. 200 with { ok, workspaces[] }
|
|
15
|
+
//
|
|
16
|
+
// Deps wired via Hono context (see server.ts deps wiring block).
|
|
17
|
+
import { Hono } from "hono";
|
|
18
|
+
import { CmuxLayoutService } from "../domain/cmux-layout-service.js";
|
|
19
|
+
export const rigCmuxRoutes = new Hono();
|
|
20
|
+
function getDeps(c) {
|
|
21
|
+
return {
|
|
22
|
+
rigRepo: c.get("rigRepo"),
|
|
23
|
+
cmuxAdapter: c.get("cmuxAdapter"),
|
|
24
|
+
cmuxLayoutService: c.get("cmuxLayoutService"),
|
|
25
|
+
nodeInventoryFn: c.get("nodeInventoryFn"),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function pickNonCollidingName(baseName, existing) {
|
|
29
|
+
if (!existing.has(baseName))
|
|
30
|
+
return baseName;
|
|
31
|
+
let suffix = 2;
|
|
32
|
+
while (existing.has(`${baseName}-${suffix}`))
|
|
33
|
+
suffix += 1;
|
|
34
|
+
return `${baseName}-${suffix}`;
|
|
35
|
+
}
|
|
36
|
+
rigCmuxRoutes.post("/launch", async (c) => {
|
|
37
|
+
const rigId = c.req.param("rigId");
|
|
38
|
+
const { rigRepo, cmuxAdapter, cmuxLayoutService, nodeInventoryFn } = getDeps(c);
|
|
39
|
+
const rigWithRelations = rigRepo.getRig(rigId);
|
|
40
|
+
if (!rigWithRelations) {
|
|
41
|
+
return c.json({
|
|
42
|
+
ok: false,
|
|
43
|
+
error: "rig_not_found",
|
|
44
|
+
message: `Rig "${rigId}" not found — can't launch cmux workspace — try: rig ps`,
|
|
45
|
+
}, 404);
|
|
46
|
+
}
|
|
47
|
+
if (!cmuxAdapter.isAvailable()) {
|
|
48
|
+
return c.json({
|
|
49
|
+
ok: false,
|
|
50
|
+
error: "cmux_unavailable",
|
|
51
|
+
message: "cmux is not available on this host — can't launch workspace — install cmux from https://cmux.io and run: cmux ping",
|
|
52
|
+
}, 503);
|
|
53
|
+
}
|
|
54
|
+
const inventory = nodeInventoryFn(rigId);
|
|
55
|
+
// Filter inventory: a node is launchable for cmux attach only if
|
|
56
|
+
// (a) it has a canonicalSessionName recorded AND (b) sessionStatus
|
|
57
|
+
// is "running" AND (c) the attachment is tmux-compatible (default
|
|
58
|
+
// when attachmentType is null/undefined; falsey-strict reject only
|
|
59
|
+
// when an explicit non-tmux value is present). Stale entries with
|
|
60
|
+
// a recorded session name but sessionStatus="exited"/"detached"/
|
|
61
|
+
// null would attach-to-a-dead-tmux-session inside the cmux panel
|
|
62
|
+
// and fail silently — violates README HG-6 / R5 honest-failure.
|
|
63
|
+
const launchableByLogical = new Map();
|
|
64
|
+
for (const entry of inventory) {
|
|
65
|
+
if (!entry.canonicalSessionName)
|
|
66
|
+
continue;
|
|
67
|
+
if (entry.sessionStatus !== "running")
|
|
68
|
+
continue;
|
|
69
|
+
if (entry.attachmentType != null && entry.attachmentType !== "tmux")
|
|
70
|
+
continue;
|
|
71
|
+
launchableByLogical.set(entry.logicalId, entry.canonicalSessionName);
|
|
72
|
+
}
|
|
73
|
+
// rig.nodes is in DB ORDER BY created_at, which corresponds to spec
|
|
74
|
+
// pod-then-member declaration order (pods created first, members
|
|
75
|
+
// within each pod in spec order). Use that as the deterministic
|
|
76
|
+
// agent ordering — no name-based sorting per README §52.
|
|
77
|
+
const orderedSessions = [];
|
|
78
|
+
for (const node of rigWithRelations.nodes) {
|
|
79
|
+
const session = launchableByLogical.get(node.logicalId);
|
|
80
|
+
if (session)
|
|
81
|
+
orderedSessions.push(session);
|
|
82
|
+
}
|
|
83
|
+
if (orderedSessions.length === 0) {
|
|
84
|
+
const rigName = rigWithRelations.rig.name;
|
|
85
|
+
return c.json({
|
|
86
|
+
ok: false,
|
|
87
|
+
error: "rig_not_running",
|
|
88
|
+
message: `Rig "${rigName}" has no running tmux sessions — can't attach to anything — run: rig up ${rigName}`,
|
|
89
|
+
}, 412);
|
|
90
|
+
}
|
|
91
|
+
// Discover existing workspaces for collision-avoidance. If
|
|
92
|
+
// listWorkspaces fails, treat the existing set as empty — the
|
|
93
|
+
// operator can rename the resulting workspace if needed; better to
|
|
94
|
+
// ship cleanly than block on an enumeration failure.
|
|
95
|
+
const listResult = await cmuxAdapter.listWorkspaces();
|
|
96
|
+
const existingNames = new Set(listResult.ok ? listResult.data.map((w) => w.name) : []);
|
|
97
|
+
const chunks = CmuxLayoutService.chunkAgents(orderedSessions);
|
|
98
|
+
const baseName = rigWithRelations.rig.name;
|
|
99
|
+
const workspaces = [];
|
|
100
|
+
for (let i = 0; i < chunks.length; i++) {
|
|
101
|
+
const desired = i === 0 ? baseName : `${baseName}-${i + 1}`;
|
|
102
|
+
const name = pickNonCollidingName(desired, existingNames);
|
|
103
|
+
existingNames.add(name);
|
|
104
|
+
const build = await cmuxLayoutService.buildWorkspace(name, undefined, chunks[i]);
|
|
105
|
+
if (!build.ok) {
|
|
106
|
+
return c.json({
|
|
107
|
+
ok: false,
|
|
108
|
+
error: "build_workspace_failed",
|
|
109
|
+
message: build.message,
|
|
110
|
+
partial: workspaces,
|
|
111
|
+
}, 500);
|
|
112
|
+
}
|
|
113
|
+
workspaces.push({
|
|
114
|
+
name: build.data.workspaceName,
|
|
115
|
+
agents: build.data.agents,
|
|
116
|
+
blanks: build.data.blanks,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
return c.json({ ok: true, workspaces });
|
|
120
|
+
});
|
|
121
|
+
//# sourceMappingURL=rig-cmux.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rig-cmux.js","sourceRoot":"","sources":["../../src/routes/rig-cmux.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../src/routes/skills.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AA6C5B,wBAAgB,YAAY,IAAI,IAAI,CAuFnC"}
|