@claudexor/control-api 1.0.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.
Files changed (43) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +7 -0
  3. package/dist/artifact-paths.d.ts +3 -0
  4. package/dist/artifact-paths.d.ts.map +1 -0
  5. package/dist/artifact-paths.js +36 -0
  6. package/dist/artifact-paths.js.map +1 -0
  7. package/dist/candidates.d.ts +3 -0
  8. package/dist/candidates.d.ts.map +1 -0
  9. package/dist/candidates.js +77 -0
  10. package/dist/candidates.js.map +1 -0
  11. package/dist/daemon-server.d.ts +196 -0
  12. package/dist/daemon-server.d.ts.map +1 -0
  13. package/dist/daemon-server.js +1971 -0
  14. package/dist/daemon-server.js.map +1 -0
  15. package/dist/index.d.ts +2 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +2 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/run-events-stream.d.ts +28 -0
  20. package/dist/run-events-stream.d.ts.map +1 -0
  21. package/dist/run-events-stream.js +146 -0
  22. package/dist/run-events-stream.js.map +1 -0
  23. package/dist/run-start.d.ts +14 -0
  24. package/dist/run-start.d.ts.map +1 -0
  25. package/dist/run-start.js +99 -0
  26. package/dist/run-start.js.map +1 -0
  27. package/dist/run-timeline.d.ts +22 -0
  28. package/dist/run-timeline.d.ts.map +1 -0
  29. package/dist/run-timeline.js +155 -0
  30. package/dist/run-timeline.js.map +1 -0
  31. package/dist/sse-shared.d.ts +11 -0
  32. package/dist/sse-shared.d.ts.map +1 -0
  33. package/dist/sse-shared.js +47 -0
  34. package/dist/sse-shared.js.map +1 -0
  35. package/dist/thread-projection.d.ts +12 -0
  36. package/dist/thread-projection.d.ts.map +1 -0
  37. package/dist/thread-projection.js +83 -0
  38. package/dist/thread-projection.js.map +1 -0
  39. package/dist/thread-turn-routes.d.ts +63 -0
  40. package/dist/thread-turn-routes.d.ts.map +1 -0
  41. package/dist/thread-turn-routes.js +317 -0
  42. package/dist/thread-turn-routes.js.map +1 -0
  43. package/package.json +45 -0
@@ -0,0 +1,317 @@
1
+ import { ControlRunStartInfo, ControlRunStartRequest } from "@claudexor/schema";
2
+ /**
3
+ * Chain `work` onto the thread's serialization chain and drop the entry once
4
+ * settled so the Map cannot grow unbounded across a thread's lifetime.
5
+ */
6
+ function chainOnThread(ctx, threadId, work) {
7
+ const previous = ctx.threadTurnChains.get(threadId) ?? Promise.resolve();
8
+ const chained = previous.catch(() => undefined).then(work);
9
+ const entry = chained.then(() => undefined, () => undefined).finally(() => {
10
+ if (ctx.threadTurnChains.get(threadId) === entry)
11
+ ctx.threadTurnChains.delete(threadId);
12
+ });
13
+ ctx.threadTurnChains.set(threadId, entry);
14
+ return chained;
15
+ }
16
+ function errStatus(err, fallback = 400) {
17
+ return err && typeof err === "object" && "status" in err ? Number(err.status) : fallback;
18
+ }
19
+ /** A typed throw's machine code (e.g. the trust gate's), null when absent or
20
+ * non-string (a numeric errno-style `code` must not leak into the typed
21
+ * refusal contract). ONE owner — daemon-server's refusal recorder reuses it. */
22
+ export function errCode(err) {
23
+ const code = err && typeof err === "object" && "code" in err ? err.code : null;
24
+ return typeof code === "string" && code ? code : null;
25
+ }
26
+ /**
27
+ * Persist an enqueue failure on a pre-created turn (refused-turn honesty,
28
+ * INV-093). Shared by every pre-create-then-enqueue path OUTSIDE these
29
+ * routes (direct POST /runs with threadId, rerun_with_feedback). Marked
30
+ * retryable=false: these are enqueue-throw paths — no job was recorded, so
31
+ * the retry endpoint has nothing to replay. Best-effort by
32
+ * contract: recording must never mask the original error (callers always
33
+ * return it), and errCode yields null for absent/non-string codes.
34
+ */
35
+ export function recordTurnEnqueueFailure(setTurnEnqueueError, turnId, err) {
36
+ if (!turnId || !setTurnEnqueueError)
37
+ return;
38
+ try {
39
+ setTurnEnqueueError(turnId, err instanceof Error ? err.message : String(err), errCode(err), false);
40
+ }
41
+ catch {
42
+ /* recording the refusal must not mask the original error */
43
+ }
44
+ }
45
+ /**
46
+ * POST /threads/:id/turns — create the turn record FIRST (single-writer), then
47
+ * enqueue its run. Per-thread serialization: concurrent turns on one thread
48
+ * would race the head_run_id lineage (check-then-act across awaits).
49
+ */
50
+ export function handleThreadTurnCreate(ctx, res, threadId, body) {
51
+ return chainOnThread(ctx, threadId, async () => {
52
+ // Once the turn record exists, any later failure in this handler must
53
+ // land ON the turn (honest inline refusal) — not only in one HTTP
54
+ // response that a reloading client never sees.
55
+ let createdTurnId = null;
56
+ try {
57
+ const detail = await ctx.threadDetail(threadId);
58
+ const thread = detail.thread;
59
+ let prompt = String(body["prompt"] ?? "");
60
+ let mode = typeof body["mode"] === "string" ? body["mode"] : thread.mode;
61
+ const planRunId = typeof body["planRunId"] === "string" ? body["planRunId"] : null;
62
+ // "Implement plan": prefix the approved plan from an earlier turn into
63
+ // the prompt and force agent mode. The plan run must belong to THIS
64
+ // thread (no cross-thread artifact reads).
65
+ if (planRunId) {
66
+ if (!(thread.run_ids ?? []).includes(planRunId)) {
67
+ throw Object.assign(new Error(`planRunId ${planRunId} is not a turn of this thread`), { status: 400 });
68
+ }
69
+ const planText = await ctx.readRunArtifactText(planRunId, "final/plan.md");
70
+ if (!planText || !planText.trim()) {
71
+ // Fail loudly: "Implement plan" with an unreadable plan must NOT
72
+ // silently run the bare prompt as agent (review r2 #7).
73
+ throw Object.assign(new Error(`plan run ${planRunId} has no readable final/plan.md to implement`), { status: 400 });
74
+ }
75
+ prompt = `Implement the following approved plan. Deviate only where the code contradicts it, and say so.\n\n${planText}\n\n## Additional instruction\n${prompt}`.trim();
76
+ mode = "agent";
77
+ }
78
+ // Agent turns run "live" in the execution tree (in-place project or the
79
+ // thread worktree — the runner resolves which from thread.workspace).
80
+ const isolation = mode === "agent" ? "live" : "envelope";
81
+ // Sticky routing inheritance (thin gateway — pure DTO passthrough, the
82
+ // engine's orderPool/resolveCandidateAdapters owns all ordering): pool/
83
+ // primary precedence is per-turn body > thread sticky > omit (engine then
84
+ // auto-pools doctor-ok / falls back to config primary).
85
+ // The pool THIS turn routes/races over: a per-turn override, else the
86
+ // thread's sticky pool, else omit.
87
+ const turnPool = Array.isArray(body["harnesses"])
88
+ ? body["harnesses"]
89
+ : (thread.eligible_harnesses && thread.eligible_harnesses.length > 0 ? thread.eligible_harnesses : undefined);
90
+ // Inherit the sticky primary ONLY when it stays valid in that pool. If the
91
+ // pool (per-turn OR the inherited thread pool) does not contain the primary
92
+ // — e.g. the user dropped the primary harness from the pool via the "⋯"
93
+ // chips — drop the bias rather than drag it along; the engine would
94
+ // otherwise reject the turn with "primary not in pool".
95
+ const inheritPrimary = body["primaryHarness"] === undefined && thread.primary_harness
96
+ && (!turnPool || turnPool.includes(thread.primary_harness))
97
+ ? thread.primary_harness
98
+ : undefined;
99
+ const params = ctx.normalizeStart(ControlRunStartRequest.parse({
100
+ ...body,
101
+ prompt,
102
+ scope: thread.repo ? { kind: "project", root: thread.repo.root } : { kind: "none" },
103
+ mode,
104
+ execution: { isolation },
105
+ threadId,
106
+ parentRunId: thread.head_run_id ?? undefined,
107
+ planRunId: planRunId ?? undefined,
108
+ authPreference: typeof body["authPreference"] === "string" ? body["authPreference"] : thread.auth_preference,
109
+ ...(inheritPrimary ? { primaryHarness: inheritPrimary } : {}),
110
+ ...(body["harnesses"] === undefined && thread.eligible_harnesses && thread.eligible_harnesses.length > 0
111
+ ? { harnesses: thread.eligible_harnesses }
112
+ : {}),
113
+ }));
114
+ // Single-writer: create the turn (run_id=null) BEFORE enqueue and pass
115
+ // its id in the params; the daemon runner binds the started run to it.
116
+ // This means a queued-but-not-yet-started turn is still recorded, so we
117
+ // NEVER cancel the job on a wait timeout (the old #18 race).
118
+ const turn = (await ctx.createThreadTurn(threadId, prompt, {
119
+ // No explicit kind: the store auto-detects initial vs followup so the
120
+ // FIRST turn of a thread is "initial", not "followup" (review #4).
121
+ parentRunId: thread.head_run_id ?? null,
122
+ planRunId,
123
+ attachments: params.attachments,
124
+ }));
125
+ createdTurnId = turn.id;
126
+ // Strip base64 attachment bytes from the enqueued params: jobs.json must
127
+ // never carry the bytes (the turn holds the resolved scoped paths, and
128
+ // the run reads them back from the turn at start).
129
+ const { attachments: _att, ...enqueueParams } = params;
130
+ // ENQUEUE phase: a throw here means NO job was recorded — persist the
131
+ // refusal as retryable:false (nothing to replay).
132
+ let job;
133
+ try {
134
+ job = await ctx.daemon.enqueue({ ...enqueueParams, turnId: turn.id });
135
+ }
136
+ catch (err) {
137
+ const message = err instanceof Error ? err.message : "enqueue failed";
138
+ try {
139
+ ctx.setTurnEnqueueError?.(turn.id, message, errCode(err), false);
140
+ }
141
+ catch {
142
+ /* recording the refusal must not mask the original error */
143
+ }
144
+ // Untyped enqueue throws are INFRA failures (daemon socket down) —
145
+ // 500, matching POST /runs; typed statuses pass through.
146
+ return ctx.json(res, errStatus(err, 500), { error: message, turnId: turn.id, retryable: false });
147
+ }
148
+ // POST-ENQUEUE phase: the job EXISTS now. A status-poll throw here is
149
+ // transient observation loss, NOT a refusal — record nothing on the
150
+ // turn (the run may be starting fine; the runner hook records real
151
+ // pre-start deaths) and never claim retryable:false.
152
+ let rec;
153
+ try {
154
+ rec = await ctx.waitForRunStart(job.id);
155
+ }
156
+ catch (err) {
157
+ return ctx.json(res, 500, {
158
+ error: `job ${job.id} was accepted but its start could not be observed: ${err instanceof Error ? err.message : String(err)}`,
159
+ jobId: job.id,
160
+ turnId: turn.id,
161
+ threadId,
162
+ });
163
+ }
164
+ if (rec.runId && rec.runDir) {
165
+ return ctx.json(res, 200, {
166
+ ...ControlRunStartInfo.parse({ jobId: rec.id, runId: rec.runId, taskId: rec.taskId, runDir: rec.runDir }),
167
+ turnId: turn.id,
168
+ threadId,
169
+ });
170
+ }
171
+ // A job that went TERMINAL without ever binding a run is a pre-start
172
+ // failure (trust/preflight refusal inside the runner): report it as one
173
+ // (mirrors POST /runs' 500), never as an accepted queued turn. The
174
+ // daemon hook has already persisted the refusal on the turn record.
175
+ if (ctx.isTerminalState(rec.state)) {
176
+ return ctx.json(res, 500, { jobId: rec.id, turnId: turn.id, threadId, state: rec.state, error: rec.error ?? `run ended pre-start: ${rec.state}` });
177
+ }
178
+ // The turn IS recorded (turnId) and the job is canonical in the daemon;
179
+ // the runner binds the run when it starts. Return 202 without cancelling.
180
+ return ctx.json(res, 202, { jobId: rec.id, turnId: turn.id, threadId, state: rec.state });
181
+ }
182
+ catch (err) {
183
+ const message = err instanceof Error ? err.message : "bad request";
184
+ // PRE-ENQUEUE failures only reach here (plan read, param validation,
185
+ // turn creation) — the enqueue and status-wait phases return from
186
+ // their own catches above. When the turn was already recorded, persist
187
+ // the refusal so a thread reload still shows it (no silent orphan);
188
+ // no job exists -> retryable:false.
189
+ if (createdTurnId) {
190
+ try {
191
+ ctx.setTurnEnqueueError?.(createdTurnId, message, errCode(err), false);
192
+ }
193
+ catch {
194
+ /* recording the refusal must not mask the original error */
195
+ }
196
+ }
197
+ return ctx.json(res, errStatus(err), {
198
+ error: message,
199
+ ...(createdTurnId ? { turnId: createdTurnId, retryable: false } : {}),
200
+ });
201
+ }
202
+ });
203
+ }
204
+ /**
205
+ * POST /threads/:id/turns/:turnId/retry — re-enqueue a REFUSED turn (same
206
+ * prompt/options/attachment refs: the job registry is the SSOT of enqueue
207
+ * params, replayed verbatim). No duplicate bubble: the run binds to the SAME
208
+ * turn, which also clears enqueue_error.
209
+ */
210
+ export function handleThreadTurnRetry(ctx, res, threadId, turnId) {
211
+ // Same per-thread serialization as turn creation: a retry racing a new
212
+ // turn would otherwise interleave lineage bookkeeping.
213
+ return chainOnThread(ctx, threadId, async () => {
214
+ try {
215
+ const detail = await ctx.threadDetail(threadId);
216
+ const turns = detail.turns;
217
+ const turn = turns.find((t) => t["id"] === turnId);
218
+ if (!turn)
219
+ throw Object.assign(new Error(`no such turn on this thread: ${turnId}`), { status: 404 });
220
+ if (turn["run_id"]) {
221
+ throw Object.assign(new Error(`turn ${turnId} already has a run; retry only repairs refused turns`), { status: 409 });
222
+ }
223
+ const recorded = turn["enqueue_error"];
224
+ if (!recorded) {
225
+ throw Object.assign(new Error(`turn ${turnId} has no recorded refusal; its job may still be queued or starting`), { status: 409 });
226
+ }
227
+ // Recorded as NOT replayable (the original enqueue threw before any
228
+ // job existed): refuse immediately — no registry lookup can find
229
+ // params that were never recorded.
230
+ if (recorded.retryable === false) {
231
+ throw Object.assign(new Error(`turn ${turnId} has no recorded enqueue attempt to replay; send a new message instead`), { status: 409 });
232
+ }
233
+ // Retry repairs the TAIL of the conversation only. Re-running an OLDER
234
+ // refused turn would bind its run as the thread's new head (bindTurnRun
235
+ // advances head_run_id unconditionally) and silently reorder lineage
236
+ // that later turns already advanced — refuse loudly instead.
237
+ const lastTurn = turns[turns.length - 1];
238
+ if (lastTurn && lastTurn["id"] !== turnId) {
239
+ throw Object.assign(new Error(`turn ${turnId} is not the latest turn of this thread; the conversation moved on — send a new message instead`), { status: 409 });
240
+ }
241
+ const jobs = (await ctx.daemon.list())
242
+ .filter((r) => {
243
+ const p = r.params;
244
+ return Boolean(p && typeof p === "object" && p.turnId === turnId);
245
+ })
246
+ .sort((a, b) => String(a.createdAt ?? "").localeCompare(String(b.createdAt ?? "")));
247
+ const last = jobs[jobs.length - 1];
248
+ if (!last) {
249
+ // The refusal happened before any job existed (enqueue itself threw):
250
+ // there are no recorded params to replay faithfully — honest refusal.
251
+ throw Object.assign(new Error(`turn ${turnId} has no recorded enqueue attempt to replay; send a new message instead`), { status: 409 });
252
+ }
253
+ if (last.state === "queued" || last.state === "running") {
254
+ throw Object.assign(new Error(`turn ${turnId} already has an active job (${last.state})`), { status: 409 });
255
+ }
256
+ // REPLAY-ENQUEUE phase. Deliberately NO eager clear of the old refusal:
257
+ // the daemon hook (a fast-failing replay) can write a FRESH refusal at
258
+ // ANY point after enqueue, and no timestamp compare can fully close
259
+ // that race (same-millisecond writes). The stale refusal stays visible
260
+ // for the queued window; truth converges on the next transition —
261
+ // bindTurnRun clears it when the run starts, the hook replaces it when
262
+ // the replay fails. Honest, ordering-independent, no lost refusals.
263
+ let job;
264
+ try {
265
+ job = await ctx.daemon.enqueue(last.params);
266
+ }
267
+ catch (err) {
268
+ // A failed replay ENQUEUE is a fresh refusal — but the ORIGINAL job
269
+ // params remain in the registry, so the turn STAYS replayable.
270
+ // Untyped throws are infra failures — 500 (matching POST /runs).
271
+ const message = err instanceof Error ? err.message : "enqueue failed";
272
+ try {
273
+ ctx.setTurnEnqueueError?.(turnId, message, errCode(err), true);
274
+ }
275
+ catch {
276
+ /* recording the refusal must not mask the original error */
277
+ }
278
+ return ctx.json(res, errStatus(err, 500), { error: message, turnId, threadId });
279
+ }
280
+ // POST-ENQUEUE: the replay job exists; a status-poll throw is
281
+ // observation loss, NOT a refusal — record nothing on the turn.
282
+ let rec;
283
+ try {
284
+ rec = await ctx.waitForRunStart(job.id);
285
+ }
286
+ catch (err) {
287
+ return ctx.json(res, 500, {
288
+ error: `replay job ${job.id} was accepted but its start could not be observed: ${err instanceof Error ? err.message : String(err)}`,
289
+ jobId: job.id,
290
+ turnId,
291
+ threadId,
292
+ });
293
+ }
294
+ if (rec.runId && rec.runDir) {
295
+ return ctx.json(res, 200, {
296
+ ...ControlRunStartInfo.parse({ jobId: rec.id, runId: rec.runId, taskId: rec.taskId, runDir: rec.runDir }),
297
+ turnId,
298
+ threadId,
299
+ });
300
+ }
301
+ // A job that went TERMINAL without ever binding a run is a pre-start
302
+ // failure (trust/preflight refusal inside the runner) — report it as
303
+ // one (mirrors POST /runs), never as an accepted queued turn. The
304
+ // runner hook has already persisted the refusal on the turn.
305
+ if (ctx.isTerminalState(rec.state)) {
306
+ return ctx.json(res, 500, { jobId: rec.id, turnId, threadId, state: rec.state, error: rec.error ?? `run ended pre-start: ${rec.state}` });
307
+ }
308
+ return ctx.json(res, 202, { jobId: rec.id, turnId, threadId, state: rec.state });
309
+ }
310
+ catch (err) {
311
+ // Guard refusals only (404/409): never overwrite the original recorded
312
+ // refusal with bookkeeping noise.
313
+ return ctx.json(res, errStatus(err), { error: err instanceof Error ? err.message : "bad request" });
314
+ }
315
+ });
316
+ }
317
+ //# sourceMappingURL=thread-turn-routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"thread-turn-routes.js","sourceRoot":"","sources":["../src/thread-turn-routes.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "@claudexor/control-api",
3
+ "version": "1.0.1",
4
+ "license": "MIT",
5
+ "description": "Loopback HTTP+SSE control surface for GUI/service clients: token-auth, Host/Origin guard, live run event stream with Last-Event-ID replay. Runner injected (no second scheduler).",
6
+ "type": "module",
7
+ "main": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "default": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "dependencies": {
19
+ "yaml": "^2.6.1",
20
+ "@claudexor/delivery": "1.0.1",
21
+ "@claudexor/event-log": "1.0.1",
22
+ "@claudexor/util": "1.0.1",
23
+ "@claudexor/schema": "1.0.1",
24
+ "@claudexor/secrets": "1.0.1"
25
+ },
26
+ "repository": {
27
+ "type": "git",
28
+ "url": "git+https://github.com/razzant/claudexor.git",
29
+ "directory": "packages/control-api"
30
+ },
31
+ "homepage": "https://github.com/razzant/claudexor#readme",
32
+ "bugs": {
33
+ "url": "https://github.com/razzant/claudexor/issues"
34
+ },
35
+ "engines": {
36
+ "node": ">=20.19"
37
+ },
38
+ "publishConfig": {
39
+ "access": "public"
40
+ },
41
+ "scripts": {
42
+ "build": "tsc",
43
+ "typecheck": "tsc --noEmit"
44
+ }
45
+ }