agent-dealer 0.2.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundle/server/dist/adapters/agent-deck-bind.js +443 -0
- package/bundle/server/dist/adapters/agent-deck-bind.test.js +454 -0
- package/bundle/server/dist/adapters/agent-deck.js +38 -50
- package/bundle/server/dist/adapters/agent-deck.test.js +63 -0
- package/bundle/server/dist/adapters/agent-health.js +230 -33
- package/bundle/server/dist/adapters/agent-health.test.js +237 -0
- package/bundle/server/dist/adapters/authority-lifecycle.js +289 -0
- package/bundle/server/dist/adapters/codex-scoped-config.js +103 -0
- package/bundle/server/dist/adapters/execution-authority.js +103 -0
- package/bundle/server/dist/adapters/execution-authority.test.js +166 -0
- package/bundle/server/dist/adapters/external.js +0 -1
- package/bundle/server/dist/adapters/git-worktree.js +514 -0
- package/bundle/server/dist/adapters/git-worktree.test.js +502 -0
- package/bundle/server/dist/adapters/github.js +170 -0
- package/bundle/server/dist/adapters/github.test.js +205 -0
- package/bundle/server/dist/adapters/linear-inbox.js +199 -30
- package/bundle/server/dist/adapters/linear-inbox.test.js +35 -0
- package/bundle/server/dist/adapters/linear-sync.js +3 -101
- package/bundle/server/dist/adapters/managed-repo.js +168 -0
- package/bundle/server/dist/adapters/managed-repo.test.js +63 -0
- package/bundle/server/dist/adapters/outbound-delivery.js +83 -0
- package/bundle/server/dist/adapters/outbound-delivery.test.js +53 -0
- package/bundle/server/dist/adapters/reflect-authority.js +43 -0
- package/bundle/server/dist/cli-env.js +26 -0
- package/bundle/server/dist/cli-env.test.js +14 -1
- package/bundle/server/dist/coordinator/abort.integration.test.js +74 -0
- package/bundle/server/dist/coordinator/admission.js +330 -0
- package/bundle/server/dist/coordinator/admission.test.js +338 -0
- package/bundle/server/dist/coordinator/args.js +128 -0
- package/bundle/server/dist/coordinator/args.test.js +132 -0
- package/bundle/server/dist/coordinator/authority-recovery.integration.test.js +661 -0
- package/bundle/server/dist/coordinator/auto-merge.integration.test.js +363 -0
- package/bundle/server/dist/coordinator/auto-merge.js +286 -0
- package/bundle/server/dist/coordinator/auto-merge.timeout.test.js +14 -0
- package/bundle/server/dist/coordinator/branch-progress.js +81 -0
- package/bundle/server/dist/coordinator/clock-jump.js +98 -0
- package/bundle/server/dist/coordinator/commands.js +1088 -0
- package/bundle/server/dist/coordinator/commands.test.js +554 -0
- package/bundle/server/dist/coordinator/deck-outage-config.js +32 -0
- package/bundle/server/dist/coordinator/deck-outage.integration.test.js +200 -0
- package/bundle/server/dist/coordinator/dependencies.js +242 -0
- package/bundle/server/dist/coordinator/dependency-readiness.integration.test.js +535 -0
- package/bundle/server/dist/coordinator/developer-effect.js +959 -0
- package/bundle/server/dist/coordinator/developer-effect.test.js +1143 -0
- package/bundle/server/dist/coordinator/dispatcher.js +58 -0
- package/bundle/server/dist/coordinator/dispatcher.test.js +81 -0
- package/bundle/server/dist/coordinator/effect-registry.js +17 -0
- package/bundle/server/dist/coordinator/execution-env.integration.test.js +122 -0
- package/bundle/server/dist/coordinator/failure-reason.js +273 -0
- package/bundle/server/dist/coordinator/failure-reason.test.js +234 -0
- package/bundle/server/dist/coordinator/guidance.js +33 -0
- package/bundle/server/dist/coordinator/guidance.test.js +110 -0
- package/bundle/server/dist/coordinator/human-resolution.js +88 -0
- package/bundle/server/dist/coordinator/human-resolution.test.js +72 -0
- package/bundle/server/dist/coordinator/intent-forecast.js +13 -0
- package/bundle/server/dist/coordinator/intent-forecast.test.js +34 -0
- package/bundle/server/dist/coordinator/latest-failure.js +100 -0
- package/bundle/server/dist/coordinator/latest-failure.test.js +125 -0
- package/bundle/server/dist/coordinator/metrics.js +35 -0
- package/bundle/server/dist/coordinator/metrics.test.js +52 -0
- package/bundle/server/dist/coordinator/permissions.js +127 -0
- package/bundle/server/dist/coordinator/permissions.test.js +184 -0
- package/bundle/server/dist/coordinator/presumed-dead-budget.integration.test.js +146 -0
- package/bundle/server/dist/coordinator/process-liveness.js +191 -0
- package/bundle/server/dist/coordinator/profile-snapshot.js +20 -0
- package/bundle/server/dist/coordinator/profile-snapshot.test.js +118 -0
- package/bundle/server/dist/coordinator/projection.js +147 -0
- package/bundle/server/dist/coordinator/projection.test.js +121 -0
- package/bundle/server/dist/coordinator/prompts.js +164 -0
- package/bundle/server/dist/coordinator/prompts.test.js +177 -0
- package/bundle/server/dist/coordinator/queue-by-default.integration.test.js +271 -0
- package/bundle/server/dist/coordinator/reclaim-republish.integration.test.js +372 -0
- package/bundle/server/dist/coordinator/recovery.js +466 -0
- package/bundle/server/dist/coordinator/recovery.test.js +164 -0
- package/bundle/server/dist/coordinator/reflect-trigger.js +218 -0
- package/bundle/server/dist/coordinator/reflect-trigger.test.js +324 -0
- package/bundle/server/dist/coordinator/repair-cycle.integration.test.js +234 -0
- package/bundle/server/dist/coordinator/restart-recovery.integration.test.js +363 -0
- package/bundle/server/dist/coordinator/reviewer-effect.js +507 -0
- package/bundle/server/dist/coordinator/reviewer-effect.test.js +612 -0
- package/bundle/server/dist/coordinator/reviewer-result.js +38 -0
- package/bundle/server/dist/coordinator/reviewer-result.test.js +45 -0
- package/bundle/server/dist/coordinator/routing.js +160 -0
- package/bundle/server/dist/coordinator/routing.test.js +336 -0
- package/bundle/server/dist/coordinator/session-lifecycle.integration.test.js +127 -0
- package/bundle/server/dist/coordinator/session-lifecycle.js +280 -0
- package/bundle/server/dist/coordinator/session-lifecycle.test.js +121 -0
- package/bundle/server/dist/coordinator/session-progress.js +351 -0
- package/bundle/server/dist/coordinator/session-progress.test.js +190 -0
- package/bundle/server/dist/coordinator/session-timeouts.js +33 -0
- package/bundle/server/dist/coordinator/sleep-recovery.integration.test.js +233 -0
- package/bundle/server/dist/coordinator/spawn.js +49 -0
- package/bundle/server/dist/coordinator/sync-issue-base-branch.js +18 -0
- package/bundle/server/dist/coordinator/usage-cap-config.js +10 -0
- package/bundle/server/dist/coordinator/usage-cap-defer.js +189 -0
- package/bundle/server/dist/coordinator/usage-cap.integration.test.js +193 -0
- package/bundle/server/dist/coordinator/usage.js +40 -0
- package/bundle/server/dist/coordinator/usage.test.js +69 -0
- package/bundle/server/dist/coordinator/verification-receipt.js +333 -0
- package/bundle/server/dist/coordinator/verification-receipt.test.js +382 -0
- package/bundle/server/dist/coordinator/worker-loop.js +363 -0
- package/bundle/server/dist/coordinator/worker-loop.test.js +327 -0
- package/bundle/server/dist/coordinator/workflow-instances.test.js +45 -0
- package/bundle/server/dist/coordinator/worktree-owner-liveness.js +82 -0
- package/bundle/server/dist/coordinator/worktree-owner-liveness.test.js +199 -0
- package/bundle/server/dist/db/artifacts-issue-columns.test.js +18 -0
- package/bundle/server/dist/db/authority-attempts-stale-at-migration.test.js +65 -0
- package/bundle/server/dist/db/idempotency-index-migration.test.js +57 -0
- package/bundle/server/dist/db/index.js +359 -7
- package/bundle/server/dist/db/linear-inbox-unlock.test.js +67 -0
- package/bundle/server/dist/db/migrate-to-issues.js +824 -0
- package/bundle/server/dist/db/migrate-to-issues.test.js +842 -0
- package/bundle/server/dist/db/schema.sql +311 -1
- package/bundle/server/dist/db/schema.test.js +66 -0
- package/bundle/server/dist/db/worker-session-pid-migration.test.js +112 -0
- package/bundle/server/dist/dev-review-cli-happy-path.integration.test.js +338 -0
- package/bundle/server/dist/direct-start-liveness.integration.test.js +350 -0
- package/bundle/server/dist/index.js +58 -5
- package/bundle/server/dist/paths.js +40 -4
- package/bundle/server/dist/paths.test.js +42 -0
- package/bundle/server/dist/pid-marker-claim-child.js +18 -0
- package/bundle/server/dist/pid-marker-hold-arbiter-child.js +24 -0
- package/bundle/server/dist/pid-marker.js +141 -0
- package/bundle/server/dist/pid-marker.test.js +208 -0
- package/bundle/server/dist/queue/approve-deliver.js +128 -28
- package/bundle/server/dist/queue/reflect-schedule.js +25 -0
- package/bundle/server/dist/queue/result-qa.js +1 -1
- package/bundle/server/dist/queue/send-gate.test.js +172 -36
- package/bundle/server/dist/repository/agents.js +55 -18
- package/bundle/server/dist/repository/artifacts-for-issue.js +42 -0
- package/bundle/server/dist/repository/artifacts-for-issue.test.js +48 -0
- package/bundle/server/dist/repository/artifacts.js +47 -0
- package/bundle/server/dist/repository/artifacts.test.js +48 -0
- package/bundle/server/dist/repository/authority-attempts.js +189 -0
- package/bundle/server/dist/repository/findings.js +70 -0
- package/bundle/server/dist/repository/findings.test.js +68 -0
- package/bundle/server/dist/repository/human-actions.js +142 -0
- package/bundle/server/dist/repository/human-actions.test.js +123 -0
- package/bundle/server/dist/repository/intake-settings.js +5 -59
- package/bundle/server/dist/repository/issues.js +305 -0
- package/bundle/server/dist/repository/issues.test.js +69 -0
- package/bundle/server/dist/repository/outbound-drafts.js +28 -0
- package/bundle/server/dist/repository/queue-entries.js +162 -0
- package/bundle/server/dist/repository/review-publications.js +153 -0
- package/bundle/server/dist/repository/review-publications.test.js +78 -0
- package/bundle/server/dist/repository/runs-external-id.test.js +5 -3
- package/bundle/server/dist/repository/runs.js +4 -211
- package/bundle/server/dist/repository/runtime-availability.js +54 -0
- package/bundle/server/dist/repository/usage-events.js +60 -0
- package/bundle/server/dist/repository/usage-events.test.js +56 -0
- package/bundle/server/dist/repository/work-items.js +305 -0
- package/bundle/server/dist/repository/work-items.test.js +142 -0
- package/bundle/server/dist/repository/worker-sessions.js +219 -0
- package/bundle/server/dist/repository/worker-sessions.test.js +60 -0
- package/bundle/server/dist/repository/workflow-events.js +193 -0
- package/bundle/server/dist/repository/workflow-events.test.js +89 -0
- package/bundle/server/dist/resolve-tsx-bin.js +19 -0
- package/bundle/server/dist/routes/human-actions.js +68 -0
- package/bundle/server/dist/routes/human-actions.test.js +284 -0
- package/bundle/server/dist/routes/index.js +29 -496
- package/bundle/server/dist/routes/issues.js +240 -0
- package/bundle/server/dist/routes/issues.test.js +451 -0
- package/bundle/server/dist/routes/queue.js +41 -0
- package/bundle/server/dist/routes/queue.test.js +78 -0
- package/bundle/server/dist/runners/claude-args.js +18 -30
- package/bundle/server/dist/runners/claude.js +19 -163
- package/bundle/server/dist/runners/claude.test.js +15 -70
- package/bundle/server/dist/runners/codex-args.js +59 -0
- package/bundle/server/dist/runners/codex-args.test.js +72 -0
- package/bundle/server/dist/runners/codex-jsonl.js +150 -0
- package/bundle/server/dist/runners/codex-jsonl.test.js +36 -0
- package/bundle/server/dist/runners/codex-resume.test.js +19 -0
- package/bundle/server/dist/runners/codex.js +46 -0
- package/bundle/server/dist/runners/models-codex.test.js +14 -0
- package/bundle/server/dist/runners/models.js +53 -1
- package/bundle/server/dist/runners/persist.js +4 -1
- package/bundle/server/dist/runners/process-registry.js +11 -0
- package/bundle/server/dist/runners/prompts.js +13 -280
- package/bundle/server/dist/runners/prompts.test.js +22 -153
- package/bundle/server/dist/runners/qa.js +17 -1
- package/bundle/server/dist/runners/reflect.js +4 -16
- package/bundle/server/dist/runners/spawn-cli.js +197 -0
- package/bundle/server/dist/runners/spawn-cli.test.js +130 -0
- package/bundle/server/dist/runners/stream-json.js +0 -141
- package/bundle/server/dist/runners/usage-cap.js +242 -0
- package/bundle/server/dist/runners/usage-cap.test.js +97 -0
- package/bundle/server/dist/server-liveness.js +37 -0
- package/bundle/server/dist/server-liveness.test.js +82 -0
- package/bundle/server/dist/static-ui.test.js +44 -0
- package/bundle/server/package.json +4 -2
- package/bundle/server/static-ui/assets/index-BTtPGYpY.js +60 -0
- package/bundle/server/static-ui/assets/index-BxTx4b1d.css +1 -0
- package/bundle/server/static-ui/index.html +2 -2
- package/bundle/shared/dist/agents.d.ts +262 -133
- package/bundle/shared/dist/agents.js +85 -19
- package/bundle/shared/dist/cursor-auth-health.d.ts +12 -0
- package/bundle/shared/dist/cursor-auth-health.js +36 -0
- package/bundle/shared/dist/cursor-auth-health.test.d.ts +1 -0
- package/bundle/shared/dist/cursor-auth-health.test.js +40 -0
- package/bundle/shared/dist/findings.d.ts +46 -0
- package/bundle/shared/dist/findings.js +17 -0
- package/bundle/shared/dist/findings.test.d.ts +1 -0
- package/bundle/shared/dist/findings.test.js +20 -0
- package/bundle/shared/dist/github-repo.d.ts +28 -0
- package/bundle/shared/dist/github-repo.js +98 -0
- package/bundle/shared/dist/github-repo.test.d.ts +1 -0
- package/bundle/shared/dist/github-repo.test.js +32 -0
- package/bundle/shared/dist/human-actions.d.ts +66 -0
- package/bundle/shared/dist/human-actions.js +51 -0
- package/bundle/shared/dist/human-actions.test.d.ts +1 -0
- package/bundle/shared/dist/human-actions.test.js +57 -0
- package/bundle/shared/dist/index.d.ts +567 -757
- package/bundle/shared/dist/index.js +22 -36
- package/bundle/shared/dist/issues.d.ts +385 -0
- package/bundle/shared/dist/issues.js +169 -0
- package/bundle/shared/dist/issues.test.d.ts +1 -0
- package/bundle/shared/dist/issues.test.js +72 -0
- package/bundle/shared/dist/outbound-draft.d.ts +6 -0
- package/bundle/shared/dist/outbound-draft.js +4 -0
- package/bundle/shared/dist/plan-triage.d.ts +6 -6
- package/bundle/shared/dist/profile-snapshot.d.ts +154 -0
- package/bundle/shared/dist/profile-snapshot.js +145 -0
- package/bundle/shared/dist/profile-snapshot.test.d.ts +1 -0
- package/bundle/shared/dist/profile-snapshot.test.js +67 -0
- package/bundle/shared/dist/queue-entries.d.ts +89 -0
- package/bundle/shared/dist/queue-entries.js +19 -0
- package/bundle/shared/dist/result-qa.d.ts +2 -2
- package/bundle/shared/dist/runtime-auth-health.d.ts +66 -0
- package/bundle/shared/dist/runtime-auth-health.js +186 -0
- package/bundle/shared/dist/runtime-auth-health.test.d.ts +1 -0
- package/bundle/shared/dist/runtime-auth-health.test.js +200 -0
- package/bundle/shared/dist/runtime-availability.d.ts +51 -0
- package/bundle/shared/dist/runtime-availability.js +13 -0
- package/bundle/shared/dist/runtime.d.ts +1 -1
- package/bundle/shared/dist/runtime.js +1 -1
- package/bundle/shared/dist/usage-events.d.ts +36 -0
- package/bundle/shared/dist/usage-events.js +13 -0
- package/bundle/shared/dist/worker-sessions.d.ts +140 -0
- package/bundle/shared/dist/worker-sessions.js +70 -0
- package/bundle/shared/dist/worker-sessions.test.d.ts +1 -0
- package/bundle/shared/dist/worker-sessions.test.js +39 -0
- package/bundle/shared/dist/workflow.d.ts +78 -0
- package/bundle/shared/dist/workflow.js +59 -0
- package/bundle/shared/dist/workflow.test.d.ts +1 -0
- package/bundle/shared/dist/workflow.test.js +61 -0
- package/bundle/shared/package.json +1 -1
- package/dist/action.d.ts +1 -0
- package/dist/action.js +50 -0
- package/dist/action.test.d.ts +1 -0
- package/dist/action.test.js +70 -0
- package/dist/agent.d.ts +1 -0
- package/dist/agent.js +17 -0
- package/dist/agent.test.d.ts +1 -0
- package/dist/agent.test.js +19 -0
- package/dist/cli-check.d.ts +7 -0
- package/dist/cli-check.js +40 -0
- package/dist/doctor.js +59 -1
- package/dist/http.d.ts +5 -0
- package/dist/http.js +19 -0
- package/dist/index.js +28 -0
- package/dist/issue.d.ts +35 -0
- package/dist/issue.js +143 -0
- package/dist/issue.test.d.ts +1 -0
- package/dist/issue.test.js +240 -0
- package/dist/lifecycle.contract.test.d.ts +1 -0
- package/dist/lifecycle.contract.test.js +135 -0
- package/dist/queue.d.ts +11 -0
- package/dist/queue.js +60 -0
- package/dist/queue.test.d.ts +1 -0
- package/dist/queue.test.js +46 -0
- package/dist/test-fetch-stub.d.ts +6 -0
- package/dist/test-fetch-stub.js +31 -0
- package/package.json +2 -1
- package/templates/prod.env.example +1 -1
- package/bundle/server/static-ui/assets/index-B_7S7xJb.js +0 -79
- package/bundle/server/static-ui/assets/index-QYv3zmE6.css +0 -1
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/** "legacy" is migration-only — the new coordinator never spawns it. */
|
|
3
|
+
export declare const WorkerSessionRole: z.ZodEnum<["developer", "reviewer", "legacy"]>;
|
|
4
|
+
export type WorkerSessionRole = z.infer<typeof WorkerSessionRole>;
|
|
5
|
+
export declare const WorkerSessionStatus: z.ZodEnum<["queued", "running", "done", "failed", "timed_out", "cancelled"]>;
|
|
6
|
+
export type WorkerSessionStatus = z.infer<typeof WorkerSessionStatus>;
|
|
7
|
+
export declare const WorkerSession: z.ZodObject<{
|
|
8
|
+
id: z.ZodString;
|
|
9
|
+
issueId: z.ZodString;
|
|
10
|
+
role: z.ZodEnum<["developer", "reviewer", "legacy"]>;
|
|
11
|
+
round: z.ZodNumber;
|
|
12
|
+
agentId: z.ZodNullable<z.ZodString>;
|
|
13
|
+
runtime: z.ZodNullable<z.ZodEnum<["claude_code", "cursor_local", "codex_local"]>>;
|
|
14
|
+
model: z.ZodNullable<z.ZodString>;
|
|
15
|
+
budgetJson: z.ZodNullable<z.ZodString>;
|
|
16
|
+
worktreePath: z.ZodNullable<z.ZodString>;
|
|
17
|
+
/** Immutable SHA supplied to this session; required in practice for reviewer sessions. */
|
|
18
|
+
inputSha: z.ZodNullable<z.ZodString>;
|
|
19
|
+
status: z.ZodEnum<["queued", "running", "done", "failed", "timed_out", "cancelled"]>;
|
|
20
|
+
/** Runtime-native session id (e.g. Claude session_id) for resume/inspection. */
|
|
21
|
+
sessionRef: z.ZodNullable<z.ZodString>;
|
|
22
|
+
logPath: z.ZodNullable<z.ZodString>;
|
|
23
|
+
exitCode: z.ZodNullable<z.ZodNumber>;
|
|
24
|
+
errorJson: z.ZodNullable<z.ZodString>;
|
|
25
|
+
/** Migration/provider metadata (e.g. original legacy run id). */
|
|
26
|
+
metadataJson: z.ZodNullable<z.ZodString>;
|
|
27
|
+
/**
|
|
28
|
+
* Immutable execution-profile snapshot (serialized ProfileSnapshot) frozen when the
|
|
29
|
+
* session is created, so a later profile edit never rewrites this session's contract.
|
|
30
|
+
*/
|
|
31
|
+
profileSnapshotJson: z.ZodNullable<z.ZodString>;
|
|
32
|
+
/**
|
|
33
|
+
* The spawned CLI's OS pid, the identity of the coordinator process that spawned it
|
|
34
|
+
* (NOT-124), and that pid's OS-reported start time (NOT-131). All null until the CLI
|
|
35
|
+
* actually starts, and for any session whose spawn never reports one.
|
|
36
|
+
*
|
|
37
|
+
* `processOwner` alone settles liveness for a pid this coordinator spawned. Across a
|
|
38
|
+
* restart it no longer matches, and the pid on its own proves nothing — the OS recycles
|
|
39
|
+
* pids, so `kill(pid, 0)` could succeed forever against an unrelated program.
|
|
40
|
+
* `processStartedAt` is what keeps the evidence usable there: a recycled pid always
|
|
41
|
+
* started later, so an exact match identifies the process and not merely the number. A
|
|
42
|
+
* row written before NOT-131 has none and reads as "no evidence", never as alive.
|
|
43
|
+
*/
|
|
44
|
+
processPid: z.ZodNullable<z.ZodNumber>;
|
|
45
|
+
processOwner: z.ZodNullable<z.ZodString>;
|
|
46
|
+
processStartedAt: z.ZodNullable<z.ZodString>;
|
|
47
|
+
createdAt: z.ZodString;
|
|
48
|
+
startedAt: z.ZodNullable<z.ZodString>;
|
|
49
|
+
heartbeatAt: z.ZodNullable<z.ZodString>;
|
|
50
|
+
completedAt: z.ZodNullable<z.ZodString>;
|
|
51
|
+
updatedAt: z.ZodString;
|
|
52
|
+
}, "strip", z.ZodTypeAny, {
|
|
53
|
+
status: "queued" | "running" | "done" | "failed" | "timed_out" | "cancelled";
|
|
54
|
+
id: string;
|
|
55
|
+
issueId: string;
|
|
56
|
+
role: "developer" | "reviewer" | "legacy";
|
|
57
|
+
round: number;
|
|
58
|
+
agentId: string | null;
|
|
59
|
+
runtime: "claude_code" | "cursor_local" | "codex_local" | null;
|
|
60
|
+
model: string | null;
|
|
61
|
+
budgetJson: string | null;
|
|
62
|
+
worktreePath: string | null;
|
|
63
|
+
inputSha: string | null;
|
|
64
|
+
sessionRef: string | null;
|
|
65
|
+
logPath: string | null;
|
|
66
|
+
exitCode: number | null;
|
|
67
|
+
errorJson: string | null;
|
|
68
|
+
metadataJson: string | null;
|
|
69
|
+
profileSnapshotJson: string | null;
|
|
70
|
+
processPid: number | null;
|
|
71
|
+
processOwner: string | null;
|
|
72
|
+
processStartedAt: string | null;
|
|
73
|
+
createdAt: string;
|
|
74
|
+
startedAt: string | null;
|
|
75
|
+
heartbeatAt: string | null;
|
|
76
|
+
completedAt: string | null;
|
|
77
|
+
updatedAt: string;
|
|
78
|
+
}, {
|
|
79
|
+
status: "queued" | "running" | "done" | "failed" | "timed_out" | "cancelled";
|
|
80
|
+
id: string;
|
|
81
|
+
issueId: string;
|
|
82
|
+
role: "developer" | "reviewer" | "legacy";
|
|
83
|
+
round: number;
|
|
84
|
+
agentId: string | null;
|
|
85
|
+
runtime: "claude_code" | "cursor_local" | "codex_local" | null;
|
|
86
|
+
model: string | null;
|
|
87
|
+
budgetJson: string | null;
|
|
88
|
+
worktreePath: string | null;
|
|
89
|
+
inputSha: string | null;
|
|
90
|
+
sessionRef: string | null;
|
|
91
|
+
logPath: string | null;
|
|
92
|
+
exitCode: number | null;
|
|
93
|
+
errorJson: string | null;
|
|
94
|
+
metadataJson: string | null;
|
|
95
|
+
profileSnapshotJson: string | null;
|
|
96
|
+
processPid: number | null;
|
|
97
|
+
processOwner: string | null;
|
|
98
|
+
processStartedAt: string | null;
|
|
99
|
+
createdAt: string;
|
|
100
|
+
startedAt: string | null;
|
|
101
|
+
heartbeatAt: string | null;
|
|
102
|
+
completedAt: string | null;
|
|
103
|
+
updatedAt: string;
|
|
104
|
+
}>;
|
|
105
|
+
export type WorkerSession = z.infer<typeof WorkerSession>;
|
|
106
|
+
export declare const CreateWorkerSessionInput: z.ZodObject<{
|
|
107
|
+
issueId: z.ZodString;
|
|
108
|
+
role: z.ZodEnum<["developer", "reviewer", "legacy"]>;
|
|
109
|
+
round: z.ZodNumber;
|
|
110
|
+
agentId: z.ZodNullable<z.ZodString>;
|
|
111
|
+
runtime: z.ZodNullable<z.ZodEnum<["claude_code", "cursor_local", "codex_local"]>>;
|
|
112
|
+
model: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
113
|
+
budgetJson: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
114
|
+
inputSha: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
115
|
+
metadataJson: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
116
|
+
profileSnapshotJson: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
117
|
+
}, "strip", z.ZodTypeAny, {
|
|
118
|
+
issueId: string;
|
|
119
|
+
role: "developer" | "reviewer" | "legacy";
|
|
120
|
+
round: number;
|
|
121
|
+
agentId: string | null;
|
|
122
|
+
runtime: "claude_code" | "cursor_local" | "codex_local" | null;
|
|
123
|
+
model?: string | null | undefined;
|
|
124
|
+
budgetJson?: string | null | undefined;
|
|
125
|
+
inputSha?: string | null | undefined;
|
|
126
|
+
metadataJson?: string | null | undefined;
|
|
127
|
+
profileSnapshotJson?: string | null | undefined;
|
|
128
|
+
}, {
|
|
129
|
+
issueId: string;
|
|
130
|
+
role: "developer" | "reviewer" | "legacy";
|
|
131
|
+
round: number;
|
|
132
|
+
agentId: string | null;
|
|
133
|
+
runtime: "claude_code" | "cursor_local" | "codex_local" | null;
|
|
134
|
+
model?: string | null | undefined;
|
|
135
|
+
budgetJson?: string | null | undefined;
|
|
136
|
+
inputSha?: string | null | undefined;
|
|
137
|
+
metadataJson?: string | null | undefined;
|
|
138
|
+
profileSnapshotJson?: string | null | undefined;
|
|
139
|
+
}>;
|
|
140
|
+
export type CreateWorkerSessionInput = z.infer<typeof CreateWorkerSessionInput>;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { Runtime } from "./runtime.js";
|
|
3
|
+
/** "legacy" is migration-only — the new coordinator never spawns it. */
|
|
4
|
+
export const WorkerSessionRole = z.enum(["developer", "reviewer", "legacy"]);
|
|
5
|
+
export const WorkerSessionStatus = z.enum([
|
|
6
|
+
"queued",
|
|
7
|
+
"running",
|
|
8
|
+
"done",
|
|
9
|
+
"failed",
|
|
10
|
+
"timed_out",
|
|
11
|
+
"cancelled",
|
|
12
|
+
]);
|
|
13
|
+
export const WorkerSession = z.object({
|
|
14
|
+
id: z.string().uuid(),
|
|
15
|
+
issueId: z.string().uuid(),
|
|
16
|
+
role: WorkerSessionRole,
|
|
17
|
+
round: z.number().int().min(1),
|
|
18
|
+
agentId: z.string().uuid().nullable(),
|
|
19
|
+
runtime: Runtime.nullable(),
|
|
20
|
+
model: z.string().nullable(),
|
|
21
|
+
budgetJson: z.string().nullable(),
|
|
22
|
+
worktreePath: z.string().nullable(),
|
|
23
|
+
/** Immutable SHA supplied to this session; required in practice for reviewer sessions. */
|
|
24
|
+
inputSha: z.string().nullable(),
|
|
25
|
+
status: WorkerSessionStatus,
|
|
26
|
+
/** Runtime-native session id (e.g. Claude session_id) for resume/inspection. */
|
|
27
|
+
sessionRef: z.string().nullable(),
|
|
28
|
+
logPath: z.string().nullable(),
|
|
29
|
+
exitCode: z.number().int().nullable(),
|
|
30
|
+
errorJson: z.string().nullable(),
|
|
31
|
+
/** Migration/provider metadata (e.g. original legacy run id). */
|
|
32
|
+
metadataJson: z.string().nullable(),
|
|
33
|
+
/**
|
|
34
|
+
* Immutable execution-profile snapshot (serialized ProfileSnapshot) frozen when the
|
|
35
|
+
* session is created, so a later profile edit never rewrites this session's contract.
|
|
36
|
+
*/
|
|
37
|
+
profileSnapshotJson: z.string().nullable(),
|
|
38
|
+
/**
|
|
39
|
+
* The spawned CLI's OS pid, the identity of the coordinator process that spawned it
|
|
40
|
+
* (NOT-124), and that pid's OS-reported start time (NOT-131). All null until the CLI
|
|
41
|
+
* actually starts, and for any session whose spawn never reports one.
|
|
42
|
+
*
|
|
43
|
+
* `processOwner` alone settles liveness for a pid this coordinator spawned. Across a
|
|
44
|
+
* restart it no longer matches, and the pid on its own proves nothing — the OS recycles
|
|
45
|
+
* pids, so `kill(pid, 0)` could succeed forever against an unrelated program.
|
|
46
|
+
* `processStartedAt` is what keeps the evidence usable there: a recycled pid always
|
|
47
|
+
* started later, so an exact match identifies the process and not merely the number. A
|
|
48
|
+
* row written before NOT-131 has none and reads as "no evidence", never as alive.
|
|
49
|
+
*/
|
|
50
|
+
processPid: z.number().int().nullable(),
|
|
51
|
+
processOwner: z.string().nullable(),
|
|
52
|
+
processStartedAt: z.string().nullable(),
|
|
53
|
+
createdAt: z.string(),
|
|
54
|
+
startedAt: z.string().nullable(),
|
|
55
|
+
heartbeatAt: z.string().nullable(),
|
|
56
|
+
completedAt: z.string().nullable(),
|
|
57
|
+
updatedAt: z.string(),
|
|
58
|
+
});
|
|
59
|
+
export const CreateWorkerSessionInput = z.object({
|
|
60
|
+
issueId: z.string().uuid(),
|
|
61
|
+
role: WorkerSessionRole,
|
|
62
|
+
round: z.number().int().min(1),
|
|
63
|
+
agentId: z.string().uuid().nullable(),
|
|
64
|
+
runtime: Runtime.nullable(),
|
|
65
|
+
model: z.string().nullable().optional(),
|
|
66
|
+
budgetJson: z.string().nullable().optional(),
|
|
67
|
+
inputSha: z.string().nullable().optional(),
|
|
68
|
+
metadataJson: z.string().nullable().optional(),
|
|
69
|
+
profileSnapshotJson: z.string().nullable().optional(),
|
|
70
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { test } from "node:test";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
import { WorkerSession, WorkerSessionRole, WorkerSessionStatus } from "./worker-sessions.js";
|
|
4
|
+
test("WorkerSession schema parses a queued developer session", () => {
|
|
5
|
+
const session = {
|
|
6
|
+
id: "44444444-4444-4444-4444-444444444444",
|
|
7
|
+
issueId: "11111111-1111-1111-1111-111111111111",
|
|
8
|
+
role: "developer",
|
|
9
|
+
round: 1,
|
|
10
|
+
agentId: "22222222-2222-2222-2222-222222222222",
|
|
11
|
+
runtime: "claude_code",
|
|
12
|
+
model: null,
|
|
13
|
+
budgetJson: null,
|
|
14
|
+
worktreePath: null,
|
|
15
|
+
inputSha: null,
|
|
16
|
+
status: "queued",
|
|
17
|
+
sessionRef: null,
|
|
18
|
+
logPath: null,
|
|
19
|
+
exitCode: null,
|
|
20
|
+
errorJson: null,
|
|
21
|
+
metadataJson: null,
|
|
22
|
+
profileSnapshotJson: null,
|
|
23
|
+
processPid: null,
|
|
24
|
+
processOwner: null,
|
|
25
|
+
processStartedAt: null,
|
|
26
|
+
createdAt: new Date().toISOString(),
|
|
27
|
+
startedAt: null,
|
|
28
|
+
heartbeatAt: null,
|
|
29
|
+
completedAt: null,
|
|
30
|
+
updatedAt: new Date().toISOString(),
|
|
31
|
+
};
|
|
32
|
+
assert.deepStrictEqual(WorkerSession.parse(session), session);
|
|
33
|
+
});
|
|
34
|
+
test("WorkerSessionRole accepts the legacy migration-only role", () => {
|
|
35
|
+
assert.equal(WorkerSessionRole.parse("legacy"), "legacy");
|
|
36
|
+
});
|
|
37
|
+
test("WorkerSessionStatus rejects an invalid status", () => {
|
|
38
|
+
assert.throws(() => WorkerSessionStatus.parse("bogus"));
|
|
39
|
+
});
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const WorkflowInstanceOutcome: z.ZodEnum<["done", "closed", "migrated"]>;
|
|
3
|
+
export type WorkflowInstanceOutcome = z.infer<typeof WorkflowInstanceOutcome>;
|
|
4
|
+
export declare const WorkflowInstance: z.ZodObject<{
|
|
5
|
+
id: z.ZodString;
|
|
6
|
+
issueId: z.ZodString;
|
|
7
|
+
workflowVersion: z.ZodString;
|
|
8
|
+
startedAt: z.ZodString;
|
|
9
|
+
completedAt: z.ZodNullable<z.ZodString>;
|
|
10
|
+
outcome: z.ZodNullable<z.ZodEnum<["done", "closed", "migrated"]>>;
|
|
11
|
+
}, "strip", z.ZodTypeAny, {
|
|
12
|
+
id: string;
|
|
13
|
+
issueId: string;
|
|
14
|
+
startedAt: string;
|
|
15
|
+
completedAt: string | null;
|
|
16
|
+
workflowVersion: string;
|
|
17
|
+
outcome: "done" | "closed" | "migrated" | null;
|
|
18
|
+
}, {
|
|
19
|
+
id: string;
|
|
20
|
+
issueId: string;
|
|
21
|
+
startedAt: string;
|
|
22
|
+
completedAt: string | null;
|
|
23
|
+
workflowVersion: string;
|
|
24
|
+
outcome: "done" | "closed" | "migrated" | null;
|
|
25
|
+
}>;
|
|
26
|
+
export type WorkflowInstance = z.infer<typeof WorkflowInstance>;
|
|
27
|
+
export declare const WorkflowEventType: z.ZodEnum<["issue.created", "workflow.started", "worker.started", "worker.completed", "worker.failed", "worker.deferred", "worktree.ready", "deck.connected", "brief.resolved", "branch.pushed", "checks.started", "pull_request.opened", "pull_request.updated", "checks.completed", "review.submitted", "repair.started", "guidance.added", "human_action.requested", "human_action.resolved", "final_review.requested", "issue.completed", "issue.closed", "legacy.imported"]>;
|
|
28
|
+
export type WorkflowEventType = z.infer<typeof WorkflowEventType>;
|
|
29
|
+
export declare const WorkflowEvent: z.ZodObject<{
|
|
30
|
+
id: z.ZodString;
|
|
31
|
+
issueId: z.ZodString;
|
|
32
|
+
/** Nullable only for issue creation/guidance emitted before any workflow starts. */
|
|
33
|
+
workflowInstanceId: z.ZodNullable<z.ZodString>;
|
|
34
|
+
workerSessionId: z.ZodNullable<z.ZodString>;
|
|
35
|
+
type: z.ZodEnum<["issue.created", "workflow.started", "worker.started", "worker.completed", "worker.failed", "worker.deferred", "worktree.ready", "deck.connected", "brief.resolved", "branch.pushed", "checks.started", "pull_request.opened", "pull_request.updated", "checks.completed", "review.submitted", "repair.started", "guidance.added", "human_action.requested", "human_action.resolved", "final_review.requested", "issue.completed", "issue.closed", "legacy.imported"]>;
|
|
36
|
+
actorType: z.ZodEnum<["human", "developer", "reviewer", "system"]>;
|
|
37
|
+
actorRef: z.ZodNullable<z.ZodString>;
|
|
38
|
+
/** Issue status at emit time — lets the timeline render without re-deriving state. */
|
|
39
|
+
stage: z.ZodString;
|
|
40
|
+
round: z.ZodNullable<z.ZodNumber>;
|
|
41
|
+
payloadJson: z.ZodNullable<z.ZodString>;
|
|
42
|
+
artifactRef: z.ZodNullable<z.ZodString>;
|
|
43
|
+
/** Provider-native key (e.g. GitHub delivery id) for idempotent re-ingestion. */
|
|
44
|
+
idempotencyKey: z.ZodNullable<z.ZodString>;
|
|
45
|
+
causationEventId: z.ZodNullable<z.ZodString>;
|
|
46
|
+
ts: z.ZodString;
|
|
47
|
+
}, "strip", z.ZodTypeAny, {
|
|
48
|
+
type: "issue.created" | "workflow.started" | "worker.started" | "worker.completed" | "worker.failed" | "worker.deferred" | "worktree.ready" | "deck.connected" | "brief.resolved" | "branch.pushed" | "checks.started" | "pull_request.opened" | "pull_request.updated" | "checks.completed" | "review.submitted" | "repair.started" | "guidance.added" | "human_action.requested" | "human_action.resolved" | "final_review.requested" | "issue.completed" | "issue.closed" | "legacy.imported";
|
|
49
|
+
id: string;
|
|
50
|
+
issueId: string;
|
|
51
|
+
round: number | null;
|
|
52
|
+
workflowInstanceId: string | null;
|
|
53
|
+
workerSessionId: string | null;
|
|
54
|
+
actorType: "developer" | "reviewer" | "human" | "system";
|
|
55
|
+
actorRef: string | null;
|
|
56
|
+
stage: string;
|
|
57
|
+
payloadJson: string | null;
|
|
58
|
+
artifactRef: string | null;
|
|
59
|
+
idempotencyKey: string | null;
|
|
60
|
+
causationEventId: string | null;
|
|
61
|
+
ts: string;
|
|
62
|
+
}, {
|
|
63
|
+
type: "issue.created" | "workflow.started" | "worker.started" | "worker.completed" | "worker.failed" | "worker.deferred" | "worktree.ready" | "deck.connected" | "brief.resolved" | "branch.pushed" | "checks.started" | "pull_request.opened" | "pull_request.updated" | "checks.completed" | "review.submitted" | "repair.started" | "guidance.added" | "human_action.requested" | "human_action.resolved" | "final_review.requested" | "issue.completed" | "issue.closed" | "legacy.imported";
|
|
64
|
+
id: string;
|
|
65
|
+
issueId: string;
|
|
66
|
+
round: number | null;
|
|
67
|
+
workflowInstanceId: string | null;
|
|
68
|
+
workerSessionId: string | null;
|
|
69
|
+
actorType: "developer" | "reviewer" | "human" | "system";
|
|
70
|
+
actorRef: string | null;
|
|
71
|
+
stage: string;
|
|
72
|
+
payloadJson: string | null;
|
|
73
|
+
artifactRef: string | null;
|
|
74
|
+
idempotencyKey: string | null;
|
|
75
|
+
causationEventId: string | null;
|
|
76
|
+
ts: string;
|
|
77
|
+
}>;
|
|
78
|
+
export type WorkflowEvent = z.infer<typeof WorkflowEvent>;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export const WorkflowInstanceOutcome = z.enum(["done", "closed", "migrated"]);
|
|
3
|
+
export const WorkflowInstance = z.object({
|
|
4
|
+
id: z.string().uuid(),
|
|
5
|
+
issueId: z.string().uuid(),
|
|
6
|
+
workflowVersion: z.string(),
|
|
7
|
+
startedAt: z.string(),
|
|
8
|
+
completedAt: z.string().nullable(),
|
|
9
|
+
outcome: WorkflowInstanceOutcome.nullable(),
|
|
10
|
+
});
|
|
11
|
+
export const WorkflowEventType = z.enum([
|
|
12
|
+
"issue.created",
|
|
13
|
+
"workflow.started",
|
|
14
|
+
"worker.started",
|
|
15
|
+
"worker.completed",
|
|
16
|
+
"worker.failed",
|
|
17
|
+
"worker.deferred",
|
|
18
|
+
/** Mid-session milestones (NOT-109) — low volume, not per-tool-call. */
|
|
19
|
+
"worktree.ready",
|
|
20
|
+
"deck.connected",
|
|
21
|
+
"brief.resolved",
|
|
22
|
+
"branch.pushed",
|
|
23
|
+
"checks.started",
|
|
24
|
+
"pull_request.opened",
|
|
25
|
+
"pull_request.updated",
|
|
26
|
+
"checks.completed",
|
|
27
|
+
"review.submitted",
|
|
28
|
+
"repair.started",
|
|
29
|
+
"guidance.added",
|
|
30
|
+
"human_action.requested",
|
|
31
|
+
"human_action.resolved",
|
|
32
|
+
"final_review.requested",
|
|
33
|
+
"issue.completed",
|
|
34
|
+
"issue.closed",
|
|
35
|
+
/** Migration-only — the NOT-66 cutover repoints a legacy `events` row under this type,
|
|
36
|
+
* preserving the original type/payload inside `payloadJson` (see `role: "legacy"` on
|
|
37
|
+
* `WorkerSessionRole` and `outcome: "migrated"` on `WorkflowInstanceOutcome` for the same
|
|
38
|
+
* migration-sentinel pattern). The new coordinator never emits it. */
|
|
39
|
+
"legacy.imported",
|
|
40
|
+
]);
|
|
41
|
+
export const WorkflowEvent = z.object({
|
|
42
|
+
id: z.string().uuid(),
|
|
43
|
+
issueId: z.string().uuid(),
|
|
44
|
+
/** Nullable only for issue creation/guidance emitted before any workflow starts. */
|
|
45
|
+
workflowInstanceId: z.string().uuid().nullable(),
|
|
46
|
+
workerSessionId: z.string().uuid().nullable(),
|
|
47
|
+
type: WorkflowEventType,
|
|
48
|
+
actorType: z.enum(["human", "developer", "reviewer", "system"]),
|
|
49
|
+
actorRef: z.string().nullable(),
|
|
50
|
+
/** Issue status at emit time — lets the timeline render without re-deriving state. */
|
|
51
|
+
stage: z.string(),
|
|
52
|
+
round: z.number().int().nullable(),
|
|
53
|
+
payloadJson: z.string().nullable(),
|
|
54
|
+
artifactRef: z.string().nullable(),
|
|
55
|
+
/** Provider-native key (e.g. GitHub delivery id) for idempotent re-ingestion. */
|
|
56
|
+
idempotencyKey: z.string().nullable(),
|
|
57
|
+
causationEventId: z.string().uuid().nullable(),
|
|
58
|
+
ts: z.string(),
|
|
59
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { test } from "node:test";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
import { WorkflowEvent, WorkflowEventType, WorkflowInstance } from "./workflow.js";
|
|
4
|
+
test("WorkflowInstance schema parses a running instance", () => {
|
|
5
|
+
const instance = {
|
|
6
|
+
id: "55555555-5555-5555-5555-555555555555",
|
|
7
|
+
issueId: "11111111-1111-1111-1111-111111111111",
|
|
8
|
+
workflowVersion: "dev_reviewer_v1",
|
|
9
|
+
startedAt: new Date().toISOString(),
|
|
10
|
+
completedAt: null,
|
|
11
|
+
outcome: null,
|
|
12
|
+
};
|
|
13
|
+
assert.deepStrictEqual(WorkflowInstance.parse(instance), instance);
|
|
14
|
+
});
|
|
15
|
+
test("WorkflowEventType accepts every PRD §9.2 event type", () => {
|
|
16
|
+
const types = [
|
|
17
|
+
"issue.created",
|
|
18
|
+
"workflow.started",
|
|
19
|
+
"worker.started",
|
|
20
|
+
"worker.completed",
|
|
21
|
+
"worker.failed",
|
|
22
|
+
"worktree.ready",
|
|
23
|
+
"deck.connected",
|
|
24
|
+
"brief.resolved",
|
|
25
|
+
"branch.pushed",
|
|
26
|
+
"checks.started",
|
|
27
|
+
"pull_request.opened",
|
|
28
|
+
"pull_request.updated",
|
|
29
|
+
"checks.completed",
|
|
30
|
+
"review.submitted",
|
|
31
|
+
"repair.started",
|
|
32
|
+
"guidance.added",
|
|
33
|
+
"human_action.requested",
|
|
34
|
+
"human_action.resolved",
|
|
35
|
+
"final_review.requested",
|
|
36
|
+
"issue.completed",
|
|
37
|
+
"issue.closed",
|
|
38
|
+
];
|
|
39
|
+
for (const t of types) {
|
|
40
|
+
assert.equal(WorkflowEventType.parse(t), t);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
test("WorkflowEvent allows a nullable workflow_instance_id for pre-workflow guidance", () => {
|
|
44
|
+
const event = {
|
|
45
|
+
id: "66666666-6666-6666-6666-666666666666",
|
|
46
|
+
issueId: "11111111-1111-1111-1111-111111111111",
|
|
47
|
+
workflowInstanceId: null,
|
|
48
|
+
workerSessionId: null,
|
|
49
|
+
type: "guidance.added",
|
|
50
|
+
actorType: "human",
|
|
51
|
+
actorRef: "yusuke",
|
|
52
|
+
stage: "ready",
|
|
53
|
+
round: null,
|
|
54
|
+
payloadJson: JSON.stringify({ markdown: "please prioritize the login bug" }),
|
|
55
|
+
artifactRef: null,
|
|
56
|
+
idempotencyKey: null,
|
|
57
|
+
causationEventId: null,
|
|
58
|
+
ts: new Date().toISOString(),
|
|
59
|
+
};
|
|
60
|
+
assert.deepStrictEqual(WorkflowEvent.parse(event), event);
|
|
61
|
+
});
|
package/dist/action.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function runActionCommand(args: string[]): Promise<number>;
|
package/dist/action.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { apiFetch } from "./http.js";
|
|
2
|
+
function flag(args, name) {
|
|
3
|
+
const idx = args.indexOf(name);
|
|
4
|
+
return idx >= 0 ? args[idx + 1] : undefined;
|
|
5
|
+
}
|
|
6
|
+
/** Parses responseOptionsJson so `action list` surfaces the valid choices directly,
|
|
7
|
+
* instead of forcing the caller to decode a JSON-encoded string within the JSON output. */
|
|
8
|
+
function withChoices(action) {
|
|
9
|
+
let choices = [];
|
|
10
|
+
if (action.responseOptionsJson) {
|
|
11
|
+
try {
|
|
12
|
+
choices = JSON.parse(action.responseOptionsJson);
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
choices = [];
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return { ...action, choices };
|
|
19
|
+
}
|
|
20
|
+
export async function runActionCommand(args) {
|
|
21
|
+
const [subcommand, ...rest] = args;
|
|
22
|
+
try {
|
|
23
|
+
if (subcommand === "list") {
|
|
24
|
+
const result = (await apiFetch("/api/human-actions"));
|
|
25
|
+
console.log(JSON.stringify(result.map(withChoices), null, 2));
|
|
26
|
+
return 0;
|
|
27
|
+
}
|
|
28
|
+
if (subcommand === "resolve") {
|
|
29
|
+
const id = rest[0];
|
|
30
|
+
const choice = flag(rest, "--choice");
|
|
31
|
+
const resolvedBy = flag(rest, "--by");
|
|
32
|
+
if (!id || !choice || !resolvedBy) {
|
|
33
|
+
console.error("resolve requires an action id, --choice, and --by");
|
|
34
|
+
return 1;
|
|
35
|
+
}
|
|
36
|
+
const result = await apiFetch(`/api/human-actions/${id}/resolve`, {
|
|
37
|
+
method: "POST",
|
|
38
|
+
body: { choice, resolvedBy },
|
|
39
|
+
});
|
|
40
|
+
console.log(JSON.stringify(result, null, 2));
|
|
41
|
+
return 0;
|
|
42
|
+
}
|
|
43
|
+
console.error(`Unknown action subcommand: ${subcommand}`);
|
|
44
|
+
return 1;
|
|
45
|
+
}
|
|
46
|
+
catch (err) {
|
|
47
|
+
console.error(err.message);
|
|
48
|
+
return 1;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { test } from "node:test";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
import { runActionCommand } from "./action.js";
|
|
4
|
+
import { stubFetch } from "./test-fetch-stub.js";
|
|
5
|
+
test("action list calls GET /api/human-actions and surfaces parsed choices", async () => {
|
|
6
|
+
const stub = stubFetch("/api/human-actions", "GET", [
|
|
7
|
+
{
|
|
8
|
+
id: "a1",
|
|
9
|
+
issueId: "i1",
|
|
10
|
+
workflowInstanceId: null,
|
|
11
|
+
actionType: "final_review",
|
|
12
|
+
reason: "done",
|
|
13
|
+
question: "Accept?",
|
|
14
|
+
evidenceJson: null,
|
|
15
|
+
responseOptionsJson: JSON.stringify([{ choice: "complete", label: "Accept — merge & mark done" }]),
|
|
16
|
+
continuationPreviewJson: null,
|
|
17
|
+
status: "open",
|
|
18
|
+
resolutionJson: null,
|
|
19
|
+
resolvedBy: null,
|
|
20
|
+
requestedAt: "2026-01-01T00:00:00.000Z",
|
|
21
|
+
resolvedAt: null,
|
|
22
|
+
},
|
|
23
|
+
]);
|
|
24
|
+
const originalLog = console.log;
|
|
25
|
+
let printed = "";
|
|
26
|
+
console.log = (msg) => {
|
|
27
|
+
printed = msg;
|
|
28
|
+
};
|
|
29
|
+
try {
|
|
30
|
+
const code = await runActionCommand(["list"]);
|
|
31
|
+
assert.equal(code, 0);
|
|
32
|
+
stub.assertCalled();
|
|
33
|
+
const [action] = JSON.parse(printed);
|
|
34
|
+
assert.deepEqual(action.choices, [{ choice: "complete", label: "Accept — merge & mark done" }]);
|
|
35
|
+
}
|
|
36
|
+
finally {
|
|
37
|
+
console.log = originalLog;
|
|
38
|
+
stub.restore();
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
test("action resolve requires an id, --choice, and --by", async () => {
|
|
42
|
+
const code = await runActionCommand(["resolve", "a1", "--choice", "complete"]);
|
|
43
|
+
assert.equal(code, 1);
|
|
44
|
+
});
|
|
45
|
+
test("action resolve calls POST /api/human-actions/:id/resolve with resolvedBy and choice", async () => {
|
|
46
|
+
const stub = stubFetch("/api/human-actions/a1/resolve", "POST", { issueStatus: "closed" });
|
|
47
|
+
try {
|
|
48
|
+
const code = await runActionCommand(["resolve", "a1", "--choice", "complete", "--by", "alice"]);
|
|
49
|
+
assert.equal(code, 0);
|
|
50
|
+
const body = stub.assertCalled();
|
|
51
|
+
assert.deepEqual(body, { choice: "complete", resolvedBy: "alice" });
|
|
52
|
+
}
|
|
53
|
+
finally {
|
|
54
|
+
stub.restore();
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
test("action resolve returns nonzero on API failure", async () => {
|
|
58
|
+
const stub = stubFetch("/api/human-actions/a1/resolve", "POST", { error: "bad choice" }, 400);
|
|
59
|
+
try {
|
|
60
|
+
const code = await runActionCommand(["resolve", "a1", "--choice", "bogus", "--by", "alice"]);
|
|
61
|
+
assert.equal(code, 1);
|
|
62
|
+
}
|
|
63
|
+
finally {
|
|
64
|
+
stub.restore();
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
test("unknown action subcommand returns nonzero", async () => {
|
|
68
|
+
const code = await runActionCommand(["bogus"]);
|
|
69
|
+
assert.equal(code, 1);
|
|
70
|
+
});
|
package/dist/agent.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function runAgentCommand(args: string[]): Promise<number>;
|
package/dist/agent.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { apiFetch } from "./http.js";
|
|
2
|
+
export async function runAgentCommand(args) {
|
|
3
|
+
const [subcommand] = args;
|
|
4
|
+
try {
|
|
5
|
+
if (subcommand === "list") {
|
|
6
|
+
const result = await apiFetch("/api/agents");
|
|
7
|
+
console.log(JSON.stringify(result, null, 2));
|
|
8
|
+
return 0;
|
|
9
|
+
}
|
|
10
|
+
console.error(`Unknown agent subcommand: ${subcommand}`);
|
|
11
|
+
return 1;
|
|
12
|
+
}
|
|
13
|
+
catch (err) {
|
|
14
|
+
console.error(err.message);
|
|
15
|
+
return 1;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { test } from "node:test";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
import { runAgentCommand } from "./agent.js";
|
|
4
|
+
import { stubFetch } from "./test-fetch-stub.js";
|
|
5
|
+
test("agent list calls GET /api/agents and exits 0", async () => {
|
|
6
|
+
const stub = stubFetch("/api/agents", "GET", { agents: [], issueCount: 0 });
|
|
7
|
+
try {
|
|
8
|
+
const code = await runAgentCommand(["list"]);
|
|
9
|
+
assert.equal(code, 0);
|
|
10
|
+
stub.assertCalled();
|
|
11
|
+
}
|
|
12
|
+
finally {
|
|
13
|
+
stub.restore();
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
test("unknown agent subcommand returns nonzero", async () => {
|
|
17
|
+
const code = await runAgentCommand(["bogus"]);
|
|
18
|
+
assert.equal(code, 1);
|
|
19
|
+
});
|
package/dist/cli-check.d.ts
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
/** Match server cli-env resolution for doctor checks. */
|
|
2
2
|
export declare function resolveClaudeBin(): string;
|
|
3
|
+
/** Match server cli-env resolution for Cursor Agent CLI. */
|
|
4
|
+
export declare function resolveCursorBin(): string;
|
|
5
|
+
export declare function cursorInvokeArgs(args: string[]): string[];
|
|
3
6
|
export declare function claudeAvailable(): Promise<{
|
|
4
7
|
ok: boolean;
|
|
5
8
|
bin: string;
|
|
6
9
|
}>;
|
|
10
|
+
export declare function cursorAvailable(): Promise<{
|
|
11
|
+
ok: boolean;
|
|
12
|
+
bin: string;
|
|
13
|
+
}>;
|