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
|
@@ -1,39 +1,17 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import { parseRunBudget } from "@agent-dealer/shared";
|
|
4
|
-
import { addArtifact, createRun, findActiveByExternalId, getRun, listArtifacts, listEvents, listRuns, updateRunFields, transitionRun, getLatestArtifact, markPlanTriageConsumed, patchRunPhaseBudget, updateRunBudget, } from "../repository/runs.js";
|
|
5
|
-
import { createAgent, deleteAgent, getAgent, listAgents, updateAgent, } from "../repository/agents.js";
|
|
1
|
+
import { CreateAgentInput, UpdateAgentInput, Runtime } from "@agent-dealer/shared";
|
|
2
|
+
import { createAgent, deleteAgent, listAgents, updateAgent, } from "../repository/agents.js";
|
|
6
3
|
import { listAgentsWithHealth } from "../adapters/agent-health.js";
|
|
7
|
-
import {
|
|
8
|
-
import { approveRunWithDeliver } from "../queue/approve-deliver.js";
|
|
9
|
-
import { recordPlanDelegation } from "../queue/plan-delegation.js";
|
|
10
|
-
import { askResultQuestion } from "../queue/result-qa.js";
|
|
11
|
-
import { rejectPendingOutboundDrafts, deliverInFlight } from "../repository/outbound-drafts.js";
|
|
12
|
-
import { getActiveLogPath } from "../runners/claude.js";
|
|
13
|
-
import { fetchAgentDeckDecks } from "../adapters/agent-deck.js";
|
|
4
|
+
import { fetchDecks } from "../adapters/agent-deck.js";
|
|
14
5
|
import { testAgentDeckConnection } from "../adapters/agent-deck.js";
|
|
15
|
-
import {
|
|
16
|
-
import { syncLinearForRun } from "../adapters/linear-sync.js";
|
|
17
|
-
import { buildLineageUsageSummary } from "../usage-summary.js";
|
|
18
|
-
import { buildLineageTraceSummary } from "../trace-summary.js";
|
|
19
|
-
import { getLinearIntakeConfig, getLinearIntakeConfigView, patchLinearIntakeConfig, getAgentDeckConfig, patchAgentDeckConfig, } from "../repository/intake-settings.js";
|
|
20
|
-
import { resolveAgentForIssue } from "../intake/agent-routing.js";
|
|
6
|
+
import { listLinearCandidates, lookupLinearIssue, parseLinearIssueRef, } from "../adapters/linear-inbox.js";
|
|
21
7
|
import { listRuntimeModels } from "../runners/models.js";
|
|
22
8
|
async function resolveDeckName(deckId) {
|
|
23
9
|
if (!deckId)
|
|
24
10
|
return null;
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
return decksRes.data?.find((d) => d.id === deckId)?.name ?? null;
|
|
28
|
-
}
|
|
29
|
-
catch {
|
|
11
|
+
const result = await fetchDecks();
|
|
12
|
+
if (!result.ok)
|
|
30
13
|
return null;
|
|
31
|
-
|
|
32
|
-
}
|
|
33
|
-
function assertAgentConfigured(run) {
|
|
34
|
-
if (!run.runtime) {
|
|
35
|
-
throw new Error("Select an agent runtime before plan mode or execution");
|
|
36
|
-
}
|
|
14
|
+
return result.decks.find((d) => d.id === deckId)?.name ?? null;
|
|
37
15
|
}
|
|
38
16
|
export async function registerRoutes(app) {
|
|
39
17
|
app.get("/health", async () => ({ ok: true }));
|
|
@@ -46,60 +24,8 @@ export async function registerRoutes(app) {
|
|
|
46
24
|
const { models, source } = await listRuntimeModels(parsed.data, { refresh });
|
|
47
25
|
return { runtime: parsed.data, models, source };
|
|
48
26
|
});
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
if (!status)
|
|
52
|
-
return listRuns();
|
|
53
|
-
const statuses = status.split(",");
|
|
54
|
-
return listRuns(statuses);
|
|
55
|
-
});
|
|
56
|
-
app.get("/api/runs/:id", async (req, reply) => {
|
|
57
|
-
const { id } = req.params;
|
|
58
|
-
const run = getRun(id);
|
|
59
|
-
if (!run)
|
|
60
|
-
return reply.status(404).send({ error: "Not found" });
|
|
61
|
-
const artifacts = listArtifacts(id);
|
|
62
|
-
return {
|
|
63
|
-
run,
|
|
64
|
-
artifacts,
|
|
65
|
-
events: listEvents(id),
|
|
66
|
-
usageSummary: buildLineageUsageSummary(run, { artifactsByRunId: { [id]: artifacts } }),
|
|
67
|
-
traceSummary: buildLineageTraceSummary(run),
|
|
68
|
-
};
|
|
69
|
-
});
|
|
70
|
-
/** Tail NDJSON log — transcript or stream_trace artifact. */
|
|
71
|
-
app.get("/api/runs/:id/log-tail", async (req, reply) => {
|
|
72
|
-
const { id } = req.params;
|
|
73
|
-
const run = getRun(id);
|
|
74
|
-
if (!run)
|
|
75
|
-
return reply.status(404).send({ error: "Not found" });
|
|
76
|
-
const kind = req.query.kind ?? "transcript";
|
|
77
|
-
const artifacts = listArtifacts(id);
|
|
78
|
-
const artifact = artifacts.find((a) => a.kind === kind && a.blobPath) ??
|
|
79
|
-
artifacts.find((a) => a.kind === "transcript" && a.blobPath) ??
|
|
80
|
-
artifacts.find((a) => a.kind === "stream_trace" && a.blobPath);
|
|
81
|
-
const livePath = getActiveLogPath(id);
|
|
82
|
-
const blobPath = artifact?.blobPath ?? livePath;
|
|
83
|
-
if (!blobPath)
|
|
84
|
-
return reply.status(404).send({ error: "No log artifact" });
|
|
85
|
-
if (!fs.existsSync(blobPath)) {
|
|
86
|
-
return reply.status(404).send({ error: "Log file missing on disk" });
|
|
87
|
-
}
|
|
88
|
-
const max = Math.min(Number(req.query.max ?? 50000), 200000);
|
|
89
|
-
const raw = fs.readFileSync(blobPath, "utf8");
|
|
90
|
-
return { content: raw.slice(-max), path: blobPath, kind: artifact?.kind ?? kind, live: !!livePath };
|
|
91
|
-
});
|
|
92
|
-
app.get("/api/intake/linear/status", async () => testLinearConnection());
|
|
93
|
-
app.get("/api/intake/linear/config", async () => getLinearIntakeConfigView());
|
|
94
|
-
app.patch("/api/intake/linear/config", async (req, reply) => {
|
|
95
|
-
try {
|
|
96
|
-
const patch = LinearIntakeConfigPatch.parse(req.body);
|
|
97
|
-
return patchLinearIntakeConfig(patch);
|
|
98
|
-
}
|
|
99
|
-
catch (e) {
|
|
100
|
-
return reply.status(400).send({ error: String(e) });
|
|
101
|
-
}
|
|
102
|
-
});
|
|
27
|
+
// Linear lookup for the Issues home "New issue" flow — the only intake surface left
|
|
28
|
+
// after NOT-71 removed the Inbox page and its promote-to-run pipeline.
|
|
103
29
|
app.get("/api/intake/linear", async (_req, reply) => {
|
|
104
30
|
try {
|
|
105
31
|
const candidates = await listLinearCandidates();
|
|
@@ -109,386 +35,22 @@ export async function registerRoutes(app) {
|
|
|
109
35
|
return reply.status(502).send({ error: String(e), candidates: [] });
|
|
110
36
|
}
|
|
111
37
|
});
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
}
|
|
118
|
-
catch (e) {
|
|
119
|
-
return reply.status(502).send({ error: String(e) });
|
|
38
|
+
/** Free-form kick lookup: `?q=NOT-103` or a Linear issue URL. */
|
|
39
|
+
app.get("/api/intake/linear/lookup", async (req, reply) => {
|
|
40
|
+
const q = typeof req.query.q === "string" ? req.query.q : "";
|
|
41
|
+
if (!parseLinearIssueRef(q)) {
|
|
42
|
+
return reply.status(400).send({ error: "Provide a Linear identifier (e.g. NOT-103) or issue URL" });
|
|
120
43
|
}
|
|
121
|
-
if (!issue)
|
|
122
|
-
return reply.status(404).send({ error: "Linear issue not found" });
|
|
123
44
|
try {
|
|
124
|
-
const
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
catch (e) {
|
|
129
|
-
return reply.status(400).send({ error: String(e) });
|
|
130
|
-
}
|
|
131
|
-
});
|
|
132
|
-
app.post("/api/intake/linear/:issueId/promote", async (req, reply) => {
|
|
133
|
-
const { issueId } = req.params;
|
|
134
|
-
const input = PromoteLinearInput.parse(req.body);
|
|
135
|
-
let issue;
|
|
136
|
-
try {
|
|
137
|
-
issue = await getLinearIssue(issueId);
|
|
45
|
+
const candidate = await lookupLinearIssue(q);
|
|
46
|
+
if (!candidate)
|
|
47
|
+
return reply.status(404).send({ error: "Linear issue not found" });
|
|
48
|
+
return { candidate };
|
|
138
49
|
}
|
|
139
50
|
catch (e) {
|
|
140
51
|
return reply.status(502).send({ error: String(e) });
|
|
141
52
|
}
|
|
142
|
-
if (!issue)
|
|
143
|
-
return reply.status(404).send({ error: "Linear issue not found" });
|
|
144
|
-
const active = findActiveByExternalId("linear", issue.id);
|
|
145
|
-
if (active) {
|
|
146
|
-
return reply.status(409).send({
|
|
147
|
-
error: "Active run already exists for this issue",
|
|
148
|
-
runId: active.id,
|
|
149
|
-
});
|
|
150
|
-
}
|
|
151
|
-
let agentId;
|
|
152
|
-
try {
|
|
153
|
-
const settings = getLinearIntakeConfig();
|
|
154
|
-
const resolved = await resolveAgentForIssue(issue, settings, input.agentId);
|
|
155
|
-
agentId = resolved.agentId;
|
|
156
|
-
}
|
|
157
|
-
catch (e) {
|
|
158
|
-
return reply.status(400).send({ error: String(e) });
|
|
159
|
-
}
|
|
160
|
-
if (!getAgent(agentId)) {
|
|
161
|
-
return reply.status(400).send({ error: "Agent not found" });
|
|
162
|
-
}
|
|
163
|
-
let run;
|
|
164
|
-
try {
|
|
165
|
-
run = createRun({
|
|
166
|
-
title: `${issue.identifier}: ${issue.title}`,
|
|
167
|
-
description: issue.description,
|
|
168
|
-
taskCategory: "code",
|
|
169
|
-
status: "plan_pending",
|
|
170
|
-
agentId,
|
|
171
|
-
planModel: input.planModel ?? undefined,
|
|
172
|
-
}, { source: "linear", externalId: issue.id, externalLabel: issue.identifier });
|
|
173
|
-
}
|
|
174
|
-
catch (e) {
|
|
175
|
-
return reply.status(400).send({ error: String(e) });
|
|
176
|
-
}
|
|
177
|
-
addArtifact(run.id, "task_snapshot", {
|
|
178
|
-
title: issue.title,
|
|
179
|
-
description: issue.description,
|
|
180
|
-
source: "linear",
|
|
181
|
-
externalId: issue.identifier,
|
|
182
|
-
url: issue.url,
|
|
183
|
-
agent: {
|
|
184
|
-
agentId: run.agentId,
|
|
185
|
-
agentName: run.agentName,
|
|
186
|
-
runtime: run.runtime,
|
|
187
|
-
deckId: run.deckId,
|
|
188
|
-
deckName: run.deckName,
|
|
189
|
-
playbookId: run.playbookId,
|
|
190
|
-
},
|
|
191
|
-
}, "system");
|
|
192
|
-
schedulePlanDraft(run);
|
|
193
|
-
return reply.status(201).send(run);
|
|
194
53
|
});
|
|
195
|
-
app.post("/api/runs", async (req, reply) => {
|
|
196
|
-
const input = CreateRunInput.parse(req.body);
|
|
197
|
-
if (!getAgent(input.agentId)) {
|
|
198
|
-
return reply.status(400).send({ error: "Agent not found" });
|
|
199
|
-
}
|
|
200
|
-
let run;
|
|
201
|
-
try {
|
|
202
|
-
run = createRun(input);
|
|
203
|
-
}
|
|
204
|
-
catch (e) {
|
|
205
|
-
return reply.status(400).send({ error: String(e) });
|
|
206
|
-
}
|
|
207
|
-
addArtifact(run.id, "task_snapshot", {
|
|
208
|
-
title: run.title,
|
|
209
|
-
description: run.description,
|
|
210
|
-
source: run.source,
|
|
211
|
-
externalId: run.externalId,
|
|
212
|
-
agent: {
|
|
213
|
-
agentId: run.agentId,
|
|
214
|
-
agentName: run.agentName,
|
|
215
|
-
runtime: run.runtime,
|
|
216
|
-
deckId: run.deckId,
|
|
217
|
-
deckName: run.deckName,
|
|
218
|
-
playbookId: run.playbookId,
|
|
219
|
-
},
|
|
220
|
-
}, "system");
|
|
221
|
-
if (input.acceptanceCriteria) {
|
|
222
|
-
addArtifact(run.id, "acceptance_criteria", { markdown: input.acceptanceCriteria }, "human");
|
|
223
|
-
}
|
|
224
|
-
schedulePlanDraft(run);
|
|
225
|
-
return reply.status(201).send(run);
|
|
226
|
-
});
|
|
227
|
-
app.patch("/api/runs/:id/agent", async (req, reply) => {
|
|
228
|
-
const { id } = req.params;
|
|
229
|
-
const run = getRun(id);
|
|
230
|
-
if (!run)
|
|
231
|
-
return reply.status(404).send({ error: "Not found" });
|
|
232
|
-
if (!["plan_pending", "queued"].includes(run.status)) {
|
|
233
|
-
return reply.status(400).send({ error: "Agent config locked after plan approval" });
|
|
234
|
-
}
|
|
235
|
-
const input = AgentConfigInput.parse(req.body);
|
|
236
|
-
const deckName = await resolveDeckName(input.deckId);
|
|
237
|
-
const updated = updateRunFields(id, {
|
|
238
|
-
runtime: input.runtime,
|
|
239
|
-
deck_id: input.deckId ?? null,
|
|
240
|
-
deck_name: deckName,
|
|
241
|
-
playbook_id: input.playbookId ?? null,
|
|
242
|
-
plan_model: input.planModel !== undefined ? input.planModel : undefined,
|
|
243
|
-
execute_model: input.executeModel !== undefined ? input.executeModel : undefined,
|
|
244
|
-
});
|
|
245
|
-
if (input.budget !== undefined) {
|
|
246
|
-
return updateRunBudget(id, input.budget);
|
|
247
|
-
}
|
|
248
|
-
return updated;
|
|
249
|
-
});
|
|
250
|
-
app.post("/api/runs/:id/draft-plan", async (req, reply) => {
|
|
251
|
-
const { id } = req.params;
|
|
252
|
-
const run = getRun(id);
|
|
253
|
-
if (!run)
|
|
254
|
-
return reply.status(404).send({ error: "Not found" });
|
|
255
|
-
if (!["plan_pending", "queued"].includes(run.status)) {
|
|
256
|
-
return reply.status(400).send({ error: "Re-draft only in plan_pending" });
|
|
257
|
-
}
|
|
258
|
-
const input = DraftPlanInput.parse(req.body ?? {});
|
|
259
|
-
if (input.planModel !== undefined) {
|
|
260
|
-
updateRunFields(id, { plan_model: input.planModel });
|
|
261
|
-
}
|
|
262
|
-
if (input.planBudget !== undefined) {
|
|
263
|
-
patchRunPhaseBudget(id, "plan", input.planBudget);
|
|
264
|
-
}
|
|
265
|
-
try {
|
|
266
|
-
assertAgentConfigured(getRun(id));
|
|
267
|
-
const scheduled = scheduleRedraft(getRun(id), {
|
|
268
|
-
feedback: input.feedback,
|
|
269
|
-
editedMarkdown: input.editedMarkdown,
|
|
270
|
-
});
|
|
271
|
-
if (!scheduled) {
|
|
272
|
-
return reply.status(409).send({ error: "Plan draft already in progress" });
|
|
273
|
-
}
|
|
274
|
-
return reply.status(202).send(getRun(id));
|
|
275
|
-
}
|
|
276
|
-
catch (e) {
|
|
277
|
-
return reply.status(400).send({ error: String(e) });
|
|
278
|
-
}
|
|
279
|
-
});
|
|
280
|
-
app.patch("/api/runs/:id/plan", async (req, reply) => {
|
|
281
|
-
const { id } = req.params;
|
|
282
|
-
const run = getRun(id);
|
|
283
|
-
if (!run)
|
|
284
|
-
return reply.status(404).send({ error: "Not found" });
|
|
285
|
-
const input = UpdatePlanInput.parse(req.body);
|
|
286
|
-
if (input.approve) {
|
|
287
|
-
const hasPlan = listArtifacts(id).some((a) => a.kind === "draft_plan") ||
|
|
288
|
-
input.planMarkdown.trim().length > 0;
|
|
289
|
-
if (!hasPlan) {
|
|
290
|
-
return reply.status(400).send({ error: "Plan not ready — wait for the agent to finish planning" });
|
|
291
|
-
}
|
|
292
|
-
assertAgentConfigured(run);
|
|
293
|
-
const patch = {};
|
|
294
|
-
if (input.planModel !== undefined) {
|
|
295
|
-
patch.plan_model = input.planModel;
|
|
296
|
-
}
|
|
297
|
-
// null/empty = "Default" — do not wipe a seeded execute_model; only set explicit picks
|
|
298
|
-
if (input.executeModel?.trim()) {
|
|
299
|
-
patch.execute_model = input.executeModel.trim();
|
|
300
|
-
}
|
|
301
|
-
else if (input.planModel?.trim()) {
|
|
302
|
-
patch.execute_model = input.planModel.trim();
|
|
303
|
-
}
|
|
304
|
-
if (Object.keys(patch).length > 0) {
|
|
305
|
-
updateRunFields(id, patch);
|
|
306
|
-
}
|
|
307
|
-
if (input.planBudget !== undefined) {
|
|
308
|
-
patchRunPhaseBudget(id, "plan", input.planBudget);
|
|
309
|
-
}
|
|
310
|
-
if (input.executeBudget !== undefined) {
|
|
311
|
-
patchRunPhaseBudget(id, "execute", input.executeBudget);
|
|
312
|
-
}
|
|
313
|
-
recordPlanDelegation(id);
|
|
314
|
-
markPlanTriageConsumed(id);
|
|
315
|
-
try {
|
|
316
|
-
transitionRun(id, "plan_approved");
|
|
317
|
-
}
|
|
318
|
-
catch (e) {
|
|
319
|
-
return reply.status(409).send({ error: String(e) });
|
|
320
|
-
}
|
|
321
|
-
addArtifact(id, "approved_plan", { markdown: input.planMarkdown }, "human");
|
|
322
|
-
const updated = getRun(id);
|
|
323
|
-
syncLinearForRun(updated, "plan_approved").catch((e) => console.error("[linear-sync] plan_approved:", e));
|
|
324
|
-
await forceDispatch();
|
|
325
|
-
return updated;
|
|
326
|
-
}
|
|
327
|
-
addArtifact(id, "draft_plan", { markdown: input.planMarkdown }, "human");
|
|
328
|
-
markPlanTriageConsumed(id);
|
|
329
|
-
if (run.status === "queued") {
|
|
330
|
-
return transitionRun(id, "plan_pending");
|
|
331
|
-
}
|
|
332
|
-
return getRun(id);
|
|
333
|
-
});
|
|
334
|
-
app.post("/api/runs/:id/plan/answers", async (req, reply) => {
|
|
335
|
-
const { id } = req.params;
|
|
336
|
-
let input;
|
|
337
|
-
try {
|
|
338
|
-
input = PlanAnswersInput.parse(req.body);
|
|
339
|
-
}
|
|
340
|
-
catch (e) {
|
|
341
|
-
return reply.status(400).send({ error: String(e) });
|
|
342
|
-
}
|
|
343
|
-
const result = submitPlanAnswers(id, input);
|
|
344
|
-
if (!result.ok)
|
|
345
|
-
return reply.status(result.code).send({ error: result.error });
|
|
346
|
-
return { run: result.run, outcome: result.outcome };
|
|
347
|
-
});
|
|
348
|
-
app.post("/api/runs/:id/qa", async (req, reply) => {
|
|
349
|
-
const { id } = req.params;
|
|
350
|
-
let input;
|
|
351
|
-
try {
|
|
352
|
-
input = ResultQaInput.parse(req.body);
|
|
353
|
-
}
|
|
354
|
-
catch (e) {
|
|
355
|
-
return reply.status(400).send({ error: String(e) });
|
|
356
|
-
}
|
|
357
|
-
const result = askResultQuestion(id, input.question);
|
|
358
|
-
if (!result.ok)
|
|
359
|
-
return reply.status(result.code).send({ error: result.error });
|
|
360
|
-
return reply.status(202).send({ exchange: result.exchange });
|
|
361
|
-
});
|
|
362
|
-
app.post("/api/runs/:id/kick", async (req, reply) => {
|
|
363
|
-
const { id } = req.params;
|
|
364
|
-
const run = getRun(id);
|
|
365
|
-
if (!run)
|
|
366
|
-
return reply.status(404).send({ error: "Not found" });
|
|
367
|
-
const input = KickRunInput.parse(req.body ?? {});
|
|
368
|
-
const runtime = input.runtime ?? run.runtime;
|
|
369
|
-
if (!runtime) {
|
|
370
|
-
return reply.status(400).send({ error: "Select an agent runtime before execution" });
|
|
371
|
-
}
|
|
372
|
-
const deckId = input.deckId ?? run.deckId ?? undefined;
|
|
373
|
-
const playbookId = input.playbookId ?? run.playbookId ?? undefined;
|
|
374
|
-
const deckName = deckId ? await resolveDeckName(deckId) : run.deckName;
|
|
375
|
-
const patch = {
|
|
376
|
-
deck_id: deckId ?? null,
|
|
377
|
-
deck_name: deckName ?? null,
|
|
378
|
-
playbook_id: playbookId ?? null,
|
|
379
|
-
runtime,
|
|
380
|
-
};
|
|
381
|
-
if (input.executeModel?.trim()) {
|
|
382
|
-
patch.execute_model = input.executeModel.trim();
|
|
383
|
-
}
|
|
384
|
-
if (run.status === "plan_pending") {
|
|
385
|
-
return reply.status(400).send({ error: "Approve the plan before starting execution" });
|
|
386
|
-
}
|
|
387
|
-
if (run.status !== "plan_approved") {
|
|
388
|
-
return reply.status(400).send({ error: `Cannot kick from status ${run.status}` });
|
|
389
|
-
}
|
|
390
|
-
updateRunFields(id, patch);
|
|
391
|
-
if (input.executeBudget !== undefined) {
|
|
392
|
-
patchRunPhaseBudget(id, "execute", input.executeBudget);
|
|
393
|
-
}
|
|
394
|
-
const updated = getRun(id);
|
|
395
|
-
await kickRun(updated);
|
|
396
|
-
await forceDispatch();
|
|
397
|
-
return getRun(id);
|
|
398
|
-
});
|
|
399
|
-
app.post("/api/runs/:id/approve", async (req, reply) => {
|
|
400
|
-
const { id } = req.params;
|
|
401
|
-
const input = ApproveRunInput.parse(req.body ?? {});
|
|
402
|
-
const result = await approveRunWithDeliver(id, {
|
|
403
|
-
outboundBody: input.outboundBody,
|
|
404
|
-
});
|
|
405
|
-
if (!result.ok) {
|
|
406
|
-
return reply.status(result.code).send({ error: result.error });
|
|
407
|
-
}
|
|
408
|
-
return result.run;
|
|
409
|
-
});
|
|
410
|
-
app.post("/api/runs/:id/retry", async (req, reply) => {
|
|
411
|
-
const { id } = req.params;
|
|
412
|
-
const run = getRun(id);
|
|
413
|
-
if (!run)
|
|
414
|
-
return reply.status(404).send({ error: "Not found" });
|
|
415
|
-
if (run.status !== "review" && run.status !== "failed") {
|
|
416
|
-
return reply.status(400).send({ error: "Retry only from review or failed" });
|
|
417
|
-
}
|
|
418
|
-
if (deliverInFlight.has(id)) {
|
|
419
|
-
return reply.status(409).send({ error: "Deliver in progress — wait before retrying" });
|
|
420
|
-
}
|
|
421
|
-
const approvedPlan = getLatestArtifact(id, "approved_plan");
|
|
422
|
-
if (!approvedPlan?.contentJson) {
|
|
423
|
-
return reply.status(400).send({ error: "No approved plan — cannot retry execution" });
|
|
424
|
-
}
|
|
425
|
-
const input = RetryRunInput.parse(req.body);
|
|
426
|
-
addArtifact(id, "feedback", { markdown: input.feedback }, "human");
|
|
427
|
-
rejectPendingOutboundDrafts(id);
|
|
428
|
-
const retry = createRun({
|
|
429
|
-
title: run.title,
|
|
430
|
-
description: run.description ?? undefined,
|
|
431
|
-
taskCategory: run.taskCategory,
|
|
432
|
-
repo: run.repo ?? undefined,
|
|
433
|
-
artifactWorkspace: run.artifactWorkspace ?? undefined,
|
|
434
|
-
acceptanceCriteria: run.acceptanceCriteria ?? undefined,
|
|
435
|
-
status: "plan_approved",
|
|
436
|
-
agentId: run.agentId ?? BUILTIN_AGENT_CLAUDE_ID,
|
|
437
|
-
planModel: run.planModel ?? undefined,
|
|
438
|
-
budget: parseRunBudget(run.budgetJson),
|
|
439
|
-
}, { source: run.source, externalId: run.externalId ?? undefined, externalLabel: run.externalLabel ?? undefined, lineageId: run.lineageId ?? run.id });
|
|
440
|
-
updateRunFields(retry.id, {
|
|
441
|
-
deck_id: run.deckId,
|
|
442
|
-
deck_name: run.deckName,
|
|
443
|
-
playbook_id: run.playbookId,
|
|
444
|
-
runtime: run.runtime,
|
|
445
|
-
execute_model: input.executeModel ?? input.planModel ?? run.executeModel,
|
|
446
|
-
});
|
|
447
|
-
if (input.executeBudget !== undefined) {
|
|
448
|
-
patchRunPhaseBudget(retry.id, "execute", input.executeBudget);
|
|
449
|
-
}
|
|
450
|
-
try {
|
|
451
|
-
addArtifact(retry.id, "approved_plan", JSON.parse(approvedPlan.contentJson), approvedPlan.author);
|
|
452
|
-
}
|
|
453
|
-
catch {
|
|
454
|
-
return reply.status(500).send({ error: "Failed to copy approved plan" });
|
|
455
|
-
}
|
|
456
|
-
const parentSnap = getLatestArtifact(id, "task_snapshot");
|
|
457
|
-
if (parentSnap?.contentJson) {
|
|
458
|
-
try {
|
|
459
|
-
addArtifact(retry.id, "task_snapshot", JSON.parse(parentSnap.contentJson), "system");
|
|
460
|
-
}
|
|
461
|
-
catch {
|
|
462
|
-
/* keep retry run usable without snapshot */
|
|
463
|
-
}
|
|
464
|
-
}
|
|
465
|
-
addArtifact(retry.id, "feedback", { markdown: input.feedback }, "human");
|
|
466
|
-
const parentDoc = getLatestArtifact(id, "document");
|
|
467
|
-
if (parentDoc?.contentJson) {
|
|
468
|
-
try {
|
|
469
|
-
addArtifact(retry.id, "document", JSON.parse(parentDoc.contentJson), "system");
|
|
470
|
-
}
|
|
471
|
-
catch {
|
|
472
|
-
/* deliverable will be seeded at execution if needed */
|
|
473
|
-
}
|
|
474
|
-
}
|
|
475
|
-
const retryRun = getRun(retry.id);
|
|
476
|
-
addArtifact(id, "feedback", { supersededBy: retry.id, note: "Retry — replaced by new run" }, "system");
|
|
477
|
-
transitionRun(id, "cancelled");
|
|
478
|
-
syncLinearForRun(retryRun, "retry").catch((e) => console.error("[linear-sync] retry:", e));
|
|
479
|
-
scheduleReflect(run, { trigger: "retry", feedback: input.feedback });
|
|
480
|
-
await forceDispatch();
|
|
481
|
-
return reply.status(201).send(retryRun);
|
|
482
|
-
});
|
|
483
|
-
app.post("/api/runs/:id/cancel", async (req, reply) => {
|
|
484
|
-
const { id } = req.params;
|
|
485
|
-
const run = getRun(id);
|
|
486
|
-
if (!run)
|
|
487
|
-
return reply.status(404).send({ error: "Not found" });
|
|
488
|
-
cancelActiveRun(id);
|
|
489
|
-
return transitionRun(id, "cancelled");
|
|
490
|
-
});
|
|
491
|
-
app.get("/api/snapshot", async () => getSnapshotAsync());
|
|
492
54
|
app.get("/api/agents", async () => {
|
|
493
55
|
const agents = await listAgentsWithHealth(listAgents());
|
|
494
56
|
return {
|
|
@@ -521,61 +83,32 @@ export async function registerRoutes(app) {
|
|
|
521
83
|
return { ok: true };
|
|
522
84
|
});
|
|
523
85
|
app.get("/api/agent-deck/status", async () => testAgentDeckConnection());
|
|
524
|
-
app.get("/api/agent-deck/config", async () => getAgentDeckConfig());
|
|
525
|
-
app.patch("/api/agent-deck/config", async (req, reply) => {
|
|
526
|
-
try {
|
|
527
|
-
const patch = AgentDeckConfigPatch.parse(req.body);
|
|
528
|
-
const config = patchAgentDeckConfig(patch);
|
|
529
|
-
return config;
|
|
530
|
-
}
|
|
531
|
-
catch (e) {
|
|
532
|
-
return reply.status(400).send({ error: String(e) });
|
|
533
|
-
}
|
|
534
|
-
});
|
|
535
86
|
app.get("/api/agent-deck/decks", async (_req, reply) => {
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
return reply.status(502).send({ error: String(e), data: [] });
|
|
87
|
+
const result = await fetchDecks();
|
|
88
|
+
if (!result.ok) {
|
|
89
|
+
const status = result.code === "DECK_UNAVAILABLE" ? 502 : 403;
|
|
90
|
+
return reply.status(status).send({ error: result.message, code: result.code, data: [] });
|
|
541
91
|
}
|
|
92
|
+
return { data: result.decks };
|
|
542
93
|
});
|
|
543
94
|
app.get("/api/agent-deck/decks/:deckId/playbooks", async (req, reply) => {
|
|
544
95
|
const { deckId } = req.params;
|
|
545
96
|
const { getAgentDeckApiUrl } = await import("../adapters/agent-deck.js");
|
|
546
97
|
const base = getAgentDeckApiUrl();
|
|
547
98
|
try {
|
|
548
|
-
const res = await fetch(`${base}/api/decks/${deckId}/playbooks`, {
|
|
99
|
+
const res = await fetch(`${base}/api/launch/decks/${encodeURIComponent(deckId)}/playbooks`, {
|
|
549
100
|
signal: AbortSignal.timeout(5000),
|
|
550
101
|
});
|
|
551
102
|
if (!res.ok)
|
|
552
103
|
throw new Error(`Agent Deck API error: ${res.status}`);
|
|
553
|
-
|
|
104
|
+
const json = (await res.json());
|
|
105
|
+
if (json.success === false)
|
|
106
|
+
throw new Error(json.message ?? "Agent Deck playbooks request failed");
|
|
107
|
+
const playbooks = Array.isArray(json.data) ? json.data : (json.data?.playbooks ?? []);
|
|
108
|
+
return { data: playbooks };
|
|
554
109
|
}
|
|
555
110
|
catch (e) {
|
|
556
111
|
return reply.status(502).send({ error: String(e), data: [] });
|
|
557
112
|
}
|
|
558
113
|
});
|
|
559
|
-
app.get("/api/events", async (req, reply) => {
|
|
560
|
-
reply.raw.writeHead(200, {
|
|
561
|
-
"Content-Type": "text/event-stream",
|
|
562
|
-
"Cache-Control": "no-cache",
|
|
563
|
-
Connection: "keep-alive",
|
|
564
|
-
});
|
|
565
|
-
const send = async () => {
|
|
566
|
-
const snap = await getSnapshotAsync();
|
|
567
|
-
reply.raw.write(`data: ${JSON.stringify(snap)}\n\n`);
|
|
568
|
-
};
|
|
569
|
-
await send();
|
|
570
|
-
const unsub = subscribe(() => {
|
|
571
|
-
send().catch(console.error);
|
|
572
|
-
});
|
|
573
|
-
const heartbeat = setInterval(() => {
|
|
574
|
-
reply.raw.write(": heartbeat\n\n");
|
|
575
|
-
}, 15000);
|
|
576
|
-
req.raw.on("close", () => {
|
|
577
|
-
unsub();
|
|
578
|
-
clearInterval(heartbeat);
|
|
579
|
-
});
|
|
580
|
-
});
|
|
581
114
|
}
|