@claudexor/control-api 3.0.4 → 3.1.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/dist/artifact-serve-routes.d.ts +46 -1
- package/dist/artifact-serve-routes.d.ts.map +1 -1
- package/dist/artifact-serve-routes.js +172 -8
- package/dist/artifact-serve-routes.js.map +1 -1
- package/dist/candidates.d.ts.map +1 -1
- package/dist/candidates.js +14 -1
- package/dist/candidates.js.map +1 -1
- package/dist/daemon-server.d.ts +67 -3
- package/dist/daemon-server.d.ts.map +1 -1
- package/dist/daemon-server.js +349 -50
- package/dist/daemon-server.js.map +1 -1
- package/dist/operation-catalog.d.ts +10 -1
- package/dist/operation-catalog.d.ts.map +1 -1
- package/dist/operation-catalog.js +150 -18
- package/dist/operation-catalog.js.map +1 -1
- package/dist/operation-parameters.d.ts +34 -0
- package/dist/operation-parameters.d.ts.map +1 -0
- package/dist/operation-parameters.js +52 -0
- package/dist/operation-parameters.js.map +1 -0
- package/dist/problem-response.d.ts +43 -0
- package/dist/problem-response.d.ts.map +1 -1
- package/dist/problem-response.js +192 -0
- package/dist/problem-response.js.map +1 -1
- package/dist/project-routes.d.ts +1 -0
- package/dist/project-routes.d.ts.map +1 -1
- package/dist/project-routes.js +18 -1
- package/dist/project-routes.js.map +1 -1
- package/dist/run-apply-routes.d.ts +6 -1
- package/dist/run-apply-routes.d.ts.map +1 -1
- package/dist/run-apply-routes.js +32 -2
- package/dist/run-apply-routes.js.map +1 -1
- package/dist/run-events-stream.d.ts.map +1 -1
- package/dist/run-events-stream.js +99 -64
- package/dist/run-events-stream.js.map +1 -1
- package/dist/run-list.d.ts +74 -0
- package/dist/run-list.d.ts.map +1 -0
- package/dist/run-list.js +156 -0
- package/dist/run-list.js.map +1 -0
- package/dist/run-retry-routes.d.ts.map +1 -1
- package/dist/run-retry-routes.js +38 -1
- package/dist/run-retry-routes.js.map +1 -1
- package/dist/run-start.d.ts +14 -1
- package/dist/run-start.d.ts.map +1 -1
- package/dist/run-start.js +50 -1
- package/dist/run-start.js.map +1 -1
- package/dist/run-timeline.d.ts +44 -3
- package/dist/run-timeline.d.ts.map +1 -1
- package/dist/run-timeline.js +143 -24
- package/dist/run-timeline.js.map +1 -1
- package/dist/thread-projection.d.ts.map +1 -1
- package/dist/thread-projection.js +6 -0
- package/dist/thread-projection.js.map +1 -1
- package/dist/thread-turn-routes.d.ts.map +1 -1
- package/dist/thread-turn-routes.js +20 -23
- package/dist/thread-turn-routes.js.map +1 -1
- package/package.json +6 -6
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-events-stream.js","sourceRoot":"","sources":["../src/run-events-stream.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAErC,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAcjF;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,GAAoB,EACpB,EAAU,EACV,WAAmB,EACnB,GAAoB,EACpB,GAAmB;IAEnB,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAClC,IAAI,CAAC,GAAG;QAAE,OAAO,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC,CAAC;IAC9D,8DAA8D;IAC9D,sEAAsE;IACtE,yEAAyE;IACzE,0BAA0B;IAC1B,IAAI,UAAU,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACtE,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE;QACjB,cAAc,EAAE,mBAAmB;QACnC,eAAe,EAAE,wBAAwB;QACzC,UAAU,EAAE,YAAY;KACzB,CAAC,CAAC;IACH,GAAG,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;IAC7B,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAExB,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,IAAI,KAAK,GAAG,EAAE,CAAC;IACf,IAAI,MAAM,GAAG,KAAK,CAAC;IACnB,IAAI,WAAqC,CAAC;IAC1C,MAAM,OAAO,GAAG,GAAG,EAAE;QACnB,MAAM,GAAG,IAAI,CAAC;QACd,aAAa,CAAC,KAAK,CAAC,CAAC;QACrB,aAAa,CAAC,SAAS,CAAC,CAAC;QACzB,WAAW,EAAE,EAAE,CAAC;QAChB,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC7B,CAAC,CAAC;IACF,4EAA4E;IAC5E,6EAA6E;IAC7E,MAAM,SAAS,GAAG,WAAW,CAAC,GAAG,EAAE;QACjC,IAAI,CAAC,MAAM;YAAE,GAAG,CAAC,KAAK,CAAC,UAAU,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IACrD,CAAC,EAAE,GAAG,CAAC,IAAI,CAAC,WAAW,IAAI,MAAM,CAAC,CAAC;IACnC,SAAS,CAAC,KAAK,EAAE,EAAE,CAAC;IACpB,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,MAAM,cAAc,GAAG,KAAK,IAAI,EAAE;QAChC,IAAI,MAAM,IAAI,QAAQ;
|
|
1
|
+
{"version":3,"file":"run-events-stream.js","sourceRoot":"","sources":["../src/run-events-stream.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAErC,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAcjF;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,GAAoB,EACpB,EAAU,EACV,WAAmB,EACnB,GAAoB,EACpB,GAAmB;IAEnB,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAClC,IAAI,CAAC,GAAG;QAAE,OAAO,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC,CAAC;IAC9D,8DAA8D;IAC9D,sEAAsE;IACtE,yEAAyE;IACzE,0BAA0B;IAC1B,IAAI,UAAU,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACtE,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE;QACjB,cAAc,EAAE,mBAAmB;QACnC,eAAe,EAAE,wBAAwB;QACzC,UAAU,EAAE,YAAY;KACzB,CAAC,CAAC;IACH,GAAG,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;IAC7B,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAExB,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,IAAI,KAAK,GAAG,EAAE,CAAC;IACf,IAAI,MAAM,GAAG,KAAK,CAAC;IACnB,IAAI,WAAqC,CAAC;IAC1C,MAAM,OAAO,GAAG,GAAG,EAAE;QACnB,MAAM,GAAG,IAAI,CAAC;QACd,aAAa,CAAC,KAAK,CAAC,CAAC;QACrB,aAAa,CAAC,SAAS,CAAC,CAAC;QACzB,WAAW,EAAE,EAAE,CAAC;QAChB,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC7B,CAAC,CAAC;IACF,4EAA4E;IAC5E,6EAA6E;IAC7E,MAAM,SAAS,GAAG,WAAW,CAAC,GAAG,EAAE;QACjC,IAAI,CAAC,MAAM;YAAE,GAAG,CAAC,KAAK,CAAC,UAAU,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IACrD,CAAC,EAAE,GAAG,CAAC,IAAI,CAAC,WAAW,IAAI,MAAM,CAAC,CAAC;IACnC,SAAS,CAAC,KAAK,EAAE,EAAE,CAAC;IACpB,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,wEAAwE;IACxE,6EAA6E;IAC7E,0EAA0E;IAC1E,6EAA6E;IAC7E,qCAAqC;IACrC,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,MAAM,cAAc,GAAG,KAAK,IAAI,EAAE;QAChC,IAAI,MAAM;YAAE,OAAO;QACnB,IAAI,QAAQ,EAAE,CAAC;YACb,OAAO,GAAG,IAAI,CAAC;YACf,OAAO;QACT,CAAC;QACD,sEAAsE;QACtE,uEAAuE;QACvE,qEAAqE;QACrE,gEAAgE;QAChE,QAAQ,GAAG,IAAI,CAAC;QAChB,IAAI,CAAC;YACH,uEAAuE;YACvE,2EAA2E;YAC3E,8CAA8C;YAC9C,SAAS,CAAC;gBACR,OAAO,GAAG,KAAK,CAAC;gBAChB,IAAI,CAAC,UAAU,EAAE,CAAC;oBAChB,oEAAoE;oBACpE,mEAAmE;oBACnE,yDAAyD;oBACzD,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC;oBACrE,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;wBAClB,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;oBACnD,CAAC;yBAAM,IAAI,eAAe,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;wBAC7C,GAAG,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;wBACtC,GAAG,CAAC,GAAG,EAAE,CAAC;wBACV,OAAO,EAAE,CAAC;wBACV,OAAO;oBACT,CAAC;yBAAM,CAAC;wBACN,IAAI,OAAO;4BAAE,SAAS;wBACtB,OAAO;oBACT,CAAC;gBACH,CAAC;gBACD,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;oBAC5B,IAAI,OAAO;wBAAE,SAAS;oBACtB,OAAO;gBACT,CAAC;gBACD,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,GAAG,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;gBAC5E,MAAM,GAAG,UAAU,CAAC;gBACpB,KAAK,GAAG,IAAI,CAAC;gBACb,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;oBACxB,MAAM,IAAI,CAAC,CAAC;oBACZ,sEAAsE;oBACtE,kEAAkE;oBAClE,mDAAmD;oBACnD,IAAI,GAAG,GAAG,MAAM,CAAC;oBACjB,IAAI,IAAI,GAAG,KAAK,CAAC;oBACjB,IAAI,CAAC;wBACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAoC,CAAC;wBAClE,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,IAAI,KAAK,CAAC,CAAC;wBACpC,IAAI,OAAO,MAAM,CAAC,GAAG,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC;4BAAE,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC;oBACtF,CAAC;oBAAC,MAAM,CAAC;wBACP,IAAI,GAAG,WAAW,CAAC;oBACrB,CAAC;oBACD,IAAI,GAAG,IAAI,WAAW;wBAAE,SAAS;oBACjC,mEAAmE;oBACnE,gEAAgE;oBAChE,yDAAyD;oBACzD,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,GAAG,YAAY,IAAI,WAAW,eAAe,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;wBAChF,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;4BAClC,MAAM,IAAI,GAAG,GAAS,EAAE;gCACtB,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;gCACvB,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;gCACvB,OAAO,EAAE,CAAC;4BACZ,CAAC,CAAC;4BACF,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;4BACxB,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;wBAC1B,CAAC,CAAC,CAAC;wBACH,IAAI,MAAM;4BAAE,OAAO;oBACrB,CAAC;oBACD,IAAI,IAAI,KAAK,eAAe,IAAI,IAAI,KAAK,YAAY,IAAI,IAAI,KAAK,aAAa,EAAE,CAAC;wBAChF,GAAG,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;wBACtC,GAAG,CAAC,GAAG,EAAE,CAAC;wBACV,OAAO,EAAE,CAAC;wBACV,OAAO;oBACT,CAAC;gBACH,CAAC;gBACD,yEAAyE;gBACzE,6DAA6D;gBAC7D,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;oBAAE,SAAS;gBAC/B,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC;gBACrE,IAAI,eAAe,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;oBACtC,sEAAsE;oBACtE,kEAAkE;oBAClE,qEAAqE;oBACrE,qEAAqE;oBACrE,uEAAuE;oBACvE,qEAAqE;oBACrE,MAAM,IAAI,GAAG,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;oBACrD,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,OAAO;wBAAE,SAAS;oBAC/C,GAAG,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;oBACtC,GAAG,CAAC,GAAG,EAAE,CAAC;oBACV,OAAO,EAAE,CAAC;oBACV,OAAO;gBACT,CAAC;gBACD,IAAI,OAAO;oBAAE,SAAS;gBACtB,OAAO;YACT,CAAC;QACH,CAAC;gBAAS,CAAC;YACT,QAAQ,GAAG,KAAK,CAAC;QACnB,CAAC;IACH,CAAC,CAAC;IACF,wEAAwE;IACxE,yEAAyE;IACzE,WAAW,GAAG,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE;QAC9C,IAAI,CAAC,MAAM,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,EAAE,CAAC;YAAE,KAAK,cAAc,EAAE,CAAC;IAC/E,CAAC,CAAC,CAAC;IACH,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,KAAK,cAAc,EAAE,EAAE,GAAG,CAAC,IAAI,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC;IAC/E,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC;IAChB,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACzB,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACzB,MAAM,cAAc,EAAE,CAAC;AACzB,CAAC"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GET /v2/runs pagination + cache-bounding helpers (QA-052).
|
|
3
|
+
*
|
|
4
|
+
* The route used to map EVERY retained daemon record on every call, silently
|
|
5
|
+
* ignore `limit`/`state`/`cursor`, and clear its whole summary cache past a
|
|
6
|
+
* guard. This module owns the honest, bounded server half:
|
|
7
|
+
* - a strict typed query (limit / state / opaque keyset cursor);
|
|
8
|
+
* - deterministic newest-first `(createdAt desc, id desc)` ordering;
|
|
9
|
+
* - keyset paging that survives concurrent inserts/prunes (walks the set once,
|
|
10
|
+
* no duplicates or omissions), so projection work is bounded by page size
|
|
11
|
+
* rather than total retained records;
|
|
12
|
+
* - an LRU-bounded map primitive so the summary cache evicts its oldest entry
|
|
13
|
+
* instead of a wholesale clear-and-rehydrate thrash.
|
|
14
|
+
*/
|
|
15
|
+
import { ControlRunState } from "@claudexor/schema";
|
|
16
|
+
/** Only the record fields keyset ordering + cursors depend on (structural). */
|
|
17
|
+
export interface RunListRecord {
|
|
18
|
+
id: string;
|
|
19
|
+
state: string;
|
|
20
|
+
createdAt?: string;
|
|
21
|
+
}
|
|
22
|
+
export interface RunListCursor {
|
|
23
|
+
createdAt: string;
|
|
24
|
+
id: string;
|
|
25
|
+
}
|
|
26
|
+
export interface RunListQuery {
|
|
27
|
+
limit: number;
|
|
28
|
+
state: ControlRunState | null;
|
|
29
|
+
cursor: RunListCursor | null;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Parse + validate the GET /v2/runs query. Unknown params are refused (strict
|
|
33
|
+
* doctrine, matching sibling routes that call `assertOnlyQueryParams`); a typoed
|
|
34
|
+
* `limit`, a foreign `state`, or a malformed `cursor` fails loudly with a typed
|
|
35
|
+
* 400 instead of being silently ignored.
|
|
36
|
+
*/
|
|
37
|
+
export declare function parseRunListQuery(url: URL): RunListQuery;
|
|
38
|
+
/** Newest-first deterministic order: `(createdAt desc, id desc)`. Records with
|
|
39
|
+
* no `createdAt` sort last (empty string) with `id` as the stable tiebreak, so
|
|
40
|
+
* the traversal is total and duplicate-free even across foreign record shapes. */
|
|
41
|
+
export declare function orderRunRecords<T extends RunListRecord>(records: readonly T[]): T[];
|
|
42
|
+
/**
|
|
43
|
+
* Index of the first record strictly after `cursor` within an already-ordered
|
|
44
|
+
* list. Comparison-based (not id-equality) so a cursor whose record was pruned
|
|
45
|
+
* between pages still resumes at the correct neighbor — no duplicate, no gap.
|
|
46
|
+
*/
|
|
47
|
+
export declare function indexAfterCursor(ordered: readonly RunListRecord[], cursor: RunListCursor): number;
|
|
48
|
+
export declare function encodeRunCursor(rec: RunListRecord): string;
|
|
49
|
+
/** Strict opaque-cursor decode: base64url alphabet only, exactly one separator,
|
|
50
|
+
* non-empty id. Anything else is a typed 400 (never a silent full-list fall
|
|
51
|
+
* back), mirroring the QA-061 run-event cursor contract. */
|
|
52
|
+
export declare function decodeRunCursor(raw: string): RunListCursor;
|
|
53
|
+
/**
|
|
54
|
+
* Select one bounded page from the raw daemon records: order newest-first,
|
|
55
|
+
* apply the optional `state` filter, then keyset-slice by cursor + limit. All of
|
|
56
|
+
* it happens on the raw records BEFORE any summary is materialized, so the
|
|
57
|
+
* caller only fingerprints/projects the returned page — work bounded by page
|
|
58
|
+
* size, not total retained records (QA-052).
|
|
59
|
+
*/
|
|
60
|
+
export declare function selectRunListPage<T extends RunListRecord>(records: readonly T[], query: RunListQuery): {
|
|
61
|
+
page: T[];
|
|
62
|
+
hasMore: boolean;
|
|
63
|
+
nextCursor: string | null;
|
|
64
|
+
};
|
|
65
|
+
/** Move an existing key to the most-recently-used position and read it. */
|
|
66
|
+
export declare function lruGet<K, V>(map: Map<K, V>, key: K): V | undefined;
|
|
67
|
+
/**
|
|
68
|
+
* Insert/refresh `key` at the MRU position, then evict least-recently-used keys
|
|
69
|
+
* until the map is within `cap`. Replaces the old wholesale `.clear()` guard:
|
|
70
|
+
* one stale entry drops at a time, so a large retained set never triggers a
|
|
71
|
+
* full-cache rehydration wave.
|
|
72
|
+
*/
|
|
73
|
+
export declare function lruSet<K, V>(map: Map<K, V>, key: K, value: V, cap: number): void;
|
|
74
|
+
//# sourceMappingURL=run-list.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-list.d.ts","sourceRoot":"","sources":["../src/run-list.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAGpD,+EAA+E;AAC/E,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAUD,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,eAAe,GAAG,IAAI,CAAC;IAC9B,MAAM,EAAE,aAAa,GAAG,IAAI,CAAC;CAC9B;AAcD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,GAAG,GAAG,YAAY,CAoCxD;AAED;;kFAEkF;AAClF,wBAAgB,eAAe,CAAC,CAAC,SAAS,aAAa,EAAE,OAAO,EAAE,SAAS,CAAC,EAAE,GAAG,CAAC,EAAE,CAQnF;AAUD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,SAAS,aAAa,EAAE,EAAE,MAAM,EAAE,aAAa,GAAG,MAAM,CAIjG;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAE1D;AAED;;4DAE4D;AAC5D,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,CAiB1D;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,aAAa,EACvD,OAAO,EAAE,SAAS,CAAC,EAAE,EACrB,KAAK,EAAE,YAAY,GAClB;IAAE,IAAI,EAAE,CAAC,EAAE,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAQ5D;AAED,2EAA2E;AAC3E,wBAAgB,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,SAAS,CAOlE;AAED;;;;;GAKG;AACH,wBAAgB,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAQhF"}
|
package/dist/run-list.js
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GET /v2/runs pagination + cache-bounding helpers (QA-052).
|
|
3
|
+
*
|
|
4
|
+
* The route used to map EVERY retained daemon record on every call, silently
|
|
5
|
+
* ignore `limit`/`state`/`cursor`, and clear its whole summary cache past a
|
|
6
|
+
* guard. This module owns the honest, bounded server half:
|
|
7
|
+
* - a strict typed query (limit / state / opaque keyset cursor);
|
|
8
|
+
* - deterministic newest-first `(createdAt desc, id desc)` ordering;
|
|
9
|
+
* - keyset paging that survives concurrent inserts/prunes (walks the set once,
|
|
10
|
+
* no duplicates or omissions), so projection work is bounded by page size
|
|
11
|
+
* rather than total retained records;
|
|
12
|
+
* - an LRU-bounded map primitive so the summary cache evicts its oldest entry
|
|
13
|
+
* instead of a wholesale clear-and-rehydrate thrash.
|
|
14
|
+
*/
|
|
15
|
+
import { ControlRunState } from "@claudexor/schema";
|
|
16
|
+
import { assertOnlyQueryParams, singleQuery } from "./query.js";
|
|
17
|
+
/** Default page size when the caller sends no `limit` — newest-first, so the
|
|
18
|
+
* default page always contains every active (queued/running) run a thread-first
|
|
19
|
+
* client needs to discover without downloading all terminal history. */
|
|
20
|
+
const RUN_LIST_DEFAULT_LIMIT = 200;
|
|
21
|
+
/** Hard cap on an explicit `limit`; a larger request is a typed 400, never a
|
|
22
|
+
* silently honored unbounded read. */
|
|
23
|
+
const RUN_LIST_MAX_LIMIT = 1_000;
|
|
24
|
+
function invalidRunListQuery(message, code) {
|
|
25
|
+
return Object.assign(new Error(message), {
|
|
26
|
+
status: 400,
|
|
27
|
+
code,
|
|
28
|
+
requiredActions: code === "invalid_run_list_cursor" ? ["resnapshot"] : ["retry_with_valid_query"],
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Parse + validate the GET /v2/runs query. Unknown params are refused (strict
|
|
33
|
+
* doctrine, matching sibling routes that call `assertOnlyQueryParams`); a typoed
|
|
34
|
+
* `limit`, a foreign `state`, or a malformed `cursor` fails loudly with a typed
|
|
35
|
+
* 400 instead of being silently ignored.
|
|
36
|
+
*/
|
|
37
|
+
export function parseRunListQuery(url) {
|
|
38
|
+
assertOnlyQueryParams(url, ["limit", "state", "cursor"]);
|
|
39
|
+
let limit = RUN_LIST_DEFAULT_LIMIT;
|
|
40
|
+
const limitRaw = singleQuery(url, "limit");
|
|
41
|
+
if (limitRaw !== undefined) {
|
|
42
|
+
if (!/^[1-9][0-9]*$/.test(limitRaw)) {
|
|
43
|
+
throw invalidRunListQuery("limit must be a positive integer", "invalid_run_list_query");
|
|
44
|
+
}
|
|
45
|
+
const value = Number(limitRaw);
|
|
46
|
+
if (!Number.isSafeInteger(value) || value > RUN_LIST_MAX_LIMIT) {
|
|
47
|
+
throw invalidRunListQuery(`limit must be between 1 and ${RUN_LIST_MAX_LIMIT}`, "invalid_run_list_query");
|
|
48
|
+
}
|
|
49
|
+
limit = value;
|
|
50
|
+
}
|
|
51
|
+
let state = null;
|
|
52
|
+
const stateRaw = singleQuery(url, "state");
|
|
53
|
+
if (stateRaw !== undefined) {
|
|
54
|
+
const parsed = ControlRunState.safeParse(stateRaw);
|
|
55
|
+
if (!parsed.success) {
|
|
56
|
+
throw invalidRunListQuery(`state must be one of: ${ControlRunState.options.join(", ")}`, "invalid_run_list_query");
|
|
57
|
+
}
|
|
58
|
+
state = parsed.data;
|
|
59
|
+
}
|
|
60
|
+
const cursorRaw = singleQuery(url, "cursor");
|
|
61
|
+
const cursor = cursorRaw === undefined ? null : decodeRunCursor(cursorRaw);
|
|
62
|
+
return { limit, state, cursor };
|
|
63
|
+
}
|
|
64
|
+
/** Newest-first deterministic order: `(createdAt desc, id desc)`. Records with
|
|
65
|
+
* no `createdAt` sort last (empty string) with `id` as the stable tiebreak, so
|
|
66
|
+
* the traversal is total and duplicate-free even across foreign record shapes. */
|
|
67
|
+
export function orderRunRecords(records) {
|
|
68
|
+
return [...records].sort((a, b) => {
|
|
69
|
+
const ac = a.createdAt ?? "";
|
|
70
|
+
const bc = b.createdAt ?? "";
|
|
71
|
+
if (ac !== bc)
|
|
72
|
+
return ac < bc ? 1 : -1;
|
|
73
|
+
if (a.id !== b.id)
|
|
74
|
+
return a.id < b.id ? 1 : -1;
|
|
75
|
+
return 0;
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
/** True when `rec` sorts strictly AFTER the cursor key in newest-first order
|
|
79
|
+
* (i.e. is older, or same instant with a smaller id). */
|
|
80
|
+
function recordSortsAfterCursor(rec, cursor) {
|
|
81
|
+
const rc = rec.createdAt ?? "";
|
|
82
|
+
if (rc !== cursor.createdAt)
|
|
83
|
+
return rc < cursor.createdAt;
|
|
84
|
+
return rec.id < cursor.id;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Index of the first record strictly after `cursor` within an already-ordered
|
|
88
|
+
* list. Comparison-based (not id-equality) so a cursor whose record was pruned
|
|
89
|
+
* between pages still resumes at the correct neighbor — no duplicate, no gap.
|
|
90
|
+
*/
|
|
91
|
+
export function indexAfterCursor(ordered, cursor) {
|
|
92
|
+
let i = 0;
|
|
93
|
+
while (i < ordered.length && !recordSortsAfterCursor(ordered[i], cursor))
|
|
94
|
+
i++;
|
|
95
|
+
return i;
|
|
96
|
+
}
|
|
97
|
+
export function encodeRunCursor(rec) {
|
|
98
|
+
return Buffer.from(`${rec.createdAt ?? ""}\0${rec.id}`, "utf8").toString("base64url");
|
|
99
|
+
}
|
|
100
|
+
/** Strict opaque-cursor decode: base64url alphabet only, exactly one separator,
|
|
101
|
+
* non-empty id. Anything else is a typed 400 (never a silent full-list fall
|
|
102
|
+
* back), mirroring the QA-061 run-event cursor contract. */
|
|
103
|
+
export function decodeRunCursor(raw) {
|
|
104
|
+
if (!/^[A-Za-z0-9_-]+$/.test(raw)) {
|
|
105
|
+
throw invalidRunListQuery("cursor is malformed; refetch the run list and resume from its nextCursor", "invalid_run_list_cursor");
|
|
106
|
+
}
|
|
107
|
+
const decoded = Buffer.from(raw, "base64url").toString("utf8");
|
|
108
|
+
const sep = decoded.indexOf("\0");
|
|
109
|
+
const id = sep < 0 ? "" : decoded.slice(sep + 1);
|
|
110
|
+
if (sep < 0 || id.length === 0 || id.includes("\0")) {
|
|
111
|
+
throw invalidRunListQuery("cursor is malformed; refetch the run list and resume from its nextCursor", "invalid_run_list_cursor");
|
|
112
|
+
}
|
|
113
|
+
return { createdAt: decoded.slice(0, sep), id };
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Select one bounded page from the raw daemon records: order newest-first,
|
|
117
|
+
* apply the optional `state` filter, then keyset-slice by cursor + limit. All of
|
|
118
|
+
* it happens on the raw records BEFORE any summary is materialized, so the
|
|
119
|
+
* caller only fingerprints/projects the returned page — work bounded by page
|
|
120
|
+
* size, not total retained records (QA-052).
|
|
121
|
+
*/
|
|
122
|
+
export function selectRunListPage(records, query) {
|
|
123
|
+
const ordered = orderRunRecords(records);
|
|
124
|
+
const filtered = query.state ? ordered.filter((r) => r.state === query.state) : ordered;
|
|
125
|
+
const start = query.cursor ? indexAfterCursor(filtered, query.cursor) : 0;
|
|
126
|
+
const page = filtered.slice(start, start + query.limit);
|
|
127
|
+
const hasMore = start + page.length < filtered.length;
|
|
128
|
+
const tail = page[page.length - 1];
|
|
129
|
+
return { page, hasMore, nextCursor: hasMore && tail ? encodeRunCursor(tail) : null };
|
|
130
|
+
}
|
|
131
|
+
/** Move an existing key to the most-recently-used position and read it. */
|
|
132
|
+
export function lruGet(map, key) {
|
|
133
|
+
const value = map.get(key);
|
|
134
|
+
if (value !== undefined) {
|
|
135
|
+
map.delete(key);
|
|
136
|
+
map.set(key, value);
|
|
137
|
+
}
|
|
138
|
+
return value;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Insert/refresh `key` at the MRU position, then evict least-recently-used keys
|
|
142
|
+
* until the map is within `cap`. Replaces the old wholesale `.clear()` guard:
|
|
143
|
+
* one stale entry drops at a time, so a large retained set never triggers a
|
|
144
|
+
* full-cache rehydration wave.
|
|
145
|
+
*/
|
|
146
|
+
export function lruSet(map, key, value, cap) {
|
|
147
|
+
map.delete(key);
|
|
148
|
+
map.set(key, value);
|
|
149
|
+
while (map.size > cap) {
|
|
150
|
+
const oldest = map.keys().next().value;
|
|
151
|
+
if (oldest === undefined)
|
|
152
|
+
break;
|
|
153
|
+
map.delete(oldest);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
//# sourceMappingURL=run-list.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-list.js","sourceRoot":"","sources":["../src/run-list.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-retry-routes.d.ts","sourceRoot":"","sources":["../src/run-retry-routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"run-retry-routes.d.ts","sourceRoot":"","sources":["../src/run-retry-routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAWjE,OAAO,KAAK,EACV,uBAAuB,EACvB,kBAAkB,EAClB,eAAe,EAChB,MAAM,oBAAoB,CAAC;AAI5B,KAAK,aAAa,GAAG,IAAI,CACvB,WAAW,CAAC,uBAAuB,CAAC,UAAU,CAAC,CAAC,EAC9C,kBAAkB,GAClB,qBAAqB,GACrB,cAAc,GACd,mBAAmB,GACnB,0BAA0B,CAC7B,CAAC;AAEF,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,kBAAkB,CAAC;IAC3B,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC;IACrD,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;IACzD,IAAI,CAAC,QAAQ,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI,CAAC;IACpE,YAAY,CAAC,QAAQ,EAAE,cAAc,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;CAC9D;AAED,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,oBAAoB,EACzB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,GAClB,OAAO,CAAC,OAAO,CAAC,CAYlB"}
|
package/dist/run-retry-routes.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { parse as parseYaml } from "yaml";
|
|
4
|
+
import { ControlRunAgainDraft, ControlRunRetryResponse, ControlRunStartRequest, TaskContract, } from "@claudexor/schema";
|
|
2
5
|
import { recordTurnEnqueueFailure } from "./thread-turn-routes.js";
|
|
3
6
|
import * as runStart from "./run-start.js";
|
|
4
7
|
export async function handleRunRetryRoute(ctx, method, path, req, res) {
|
|
@@ -27,8 +30,20 @@ async function exactRetry(ctx, id, req, res) {
|
|
|
27
30
|
idempotencyKey = runStart.requiredIdempotencyKey(req);
|
|
28
31
|
const parsed = ControlRunStartRequest.parse(await sourceParamsWithThreadAttachments(ctx, source));
|
|
29
32
|
const { turnId: _turnId, retryOf: _retryOf, ...original } = parsed;
|
|
33
|
+
// QA-035: Exact Retry replays the IMMUTABLE original request. The stored
|
|
34
|
+
// params omit any model/effort the caller left to settings, so re-reading
|
|
35
|
+
// current settings would silently change the route after a settings edit.
|
|
36
|
+
// Replay the values the engine FROZE into the source run's TaskContract
|
|
37
|
+
// (routing_models / routing_efforts) — a value the caller stated explicitly
|
|
38
|
+
// still wins.
|
|
39
|
+
const frozen = readFrozenRouting(source);
|
|
30
40
|
params = runStart.normalizeRunStart({
|
|
31
41
|
...original,
|
|
42
|
+
...(frozen.models ? { models: { ...frozen.models, ...(original.models ?? {}) } } : {}),
|
|
43
|
+
// QA-035 completeness: replay the FROZEN per-lane efforts map so a
|
|
44
|
+
// non-primary lane keeps its own effort (the old scalar collapse dropped
|
|
45
|
+
// it). Frozen entries merge UNDER anything the caller stated explicitly.
|
|
46
|
+
...(frozen.efforts ? { efforts: { ...frozen.efforts, ...(original.efforts ?? {}) } } : {}),
|
|
32
47
|
parentRunId: source.runId ?? source.id,
|
|
33
48
|
retryOf: source.runId ?? source.id,
|
|
34
49
|
});
|
|
@@ -102,6 +117,28 @@ async function runAgain(ctx, id, res) {
|
|
|
102
117
|
ctx.requestError(res, error);
|
|
103
118
|
}
|
|
104
119
|
}
|
|
120
|
+
/** QA-035: read the model/effort the engine froze into the source run's
|
|
121
|
+
* TaskContract. Exact Retry injects these as the immutable route so a settings
|
|
122
|
+
* change between runs cannot silently re-resolve the model or drop the effort.
|
|
123
|
+
* The efforts are replayed as the WHOLE per-lane map (not a single primary-lane
|
|
124
|
+
* scalar) so a non-primary lane keeps its own frozen effort. A missing/old/
|
|
125
|
+
* unreadable contract yields nothing — retry then behaves exactly as before. */
|
|
126
|
+
function readFrozenRouting(source) {
|
|
127
|
+
if (!source.runDir)
|
|
128
|
+
return {};
|
|
129
|
+
let contract;
|
|
130
|
+
try {
|
|
131
|
+
contract = TaskContract.parse(parseYaml(readFileSync(join(source.runDir, "context", "task.yaml"), "utf8")));
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
return {};
|
|
135
|
+
}
|
|
136
|
+
const models = Object.keys(contract.routing_models).length > 0 ? contract.routing_models : undefined;
|
|
137
|
+
const efforts = Object.keys(contract.routing_efforts).length > 0
|
|
138
|
+
? contract.routing_efforts
|
|
139
|
+
: undefined;
|
|
140
|
+
return { ...(models ? { models } : {}), ...(efforts ? { efforts } : {}) };
|
|
141
|
+
}
|
|
105
142
|
async function sourceParamsWithThreadAttachments(ctx, source) {
|
|
106
143
|
const params = source.params && typeof source.params === "object" && !Array.isArray(source.params)
|
|
107
144
|
? { ...source.params }
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-retry-routes.js","sourceRoot":"","sources":["../src/run-retry-routes.ts"],"names":[],"mappings":"AACA,OAAO,EACL,oBAAoB,EACpB,uBAAuB,EACvB,sBAAsB,
|
|
1
|
+
{"version":3,"file":"run-retry-routes.js","sourceRoot":"","sources":["../src/run-retry-routes.ts"],"names":[],"mappings":"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"}
|
package/dist/run-start.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
2
2
|
import { ControlRunStartRequest } from "@claudexor/schema";
|
|
3
|
-
import type { DaemonFacadeClient } from "./daemon-server.js";
|
|
3
|
+
import type { DaemonFacadeClient, DaemonRunRecord } from "./daemon-server.js";
|
|
4
4
|
export declare function validateAbsoluteRepoRoot(repoRoot: string): string | null;
|
|
5
5
|
export declare function normalizeRunStart(parsed: ControlRunStartRequest): ControlRunStartRequest;
|
|
6
6
|
/**
|
|
@@ -18,6 +18,10 @@ export interface RunCreateRouteContext {
|
|
|
18
18
|
validateResources?: (refs: NonNullable<ControlRunStartRequest["attachments"]>) => Promise<void>;
|
|
19
19
|
preflightRunRequirements?: (request: ControlRunStartRequest) => Promise<void>;
|
|
20
20
|
}
|
|
21
|
+
export declare function unboundRunStartResponse(rec: DaemonRunRecord, terminal: boolean): {
|
|
22
|
+
status: number;
|
|
23
|
+
body: Record<string, unknown>;
|
|
24
|
+
};
|
|
21
25
|
/** POST /v2/runs: validates, deduplicates, durably enqueues, then returns its handle.
|
|
22
26
|
*
|
|
23
27
|
* D10: POST /runs is the ONE-SHOT, THREAD-LESS run surface. A thread turn is
|
|
@@ -27,4 +31,13 @@ export interface RunCreateRouteContext {
|
|
|
27
31
|
* turn past the turn pipeline would skip continuity entirely. */
|
|
28
32
|
export declare function handleRunCreate(ctx: RunCreateRouteContext, req: IncomingMessage, res: ServerResponse): Promise<void>;
|
|
29
33
|
export declare function requiredIdempotencyKey(req: IncomingMessage): string;
|
|
34
|
+
/**
|
|
35
|
+
* An OPTIONAL Idempotency-Key: `undefined` when the client sent none, the
|
|
36
|
+
* validated value when present. Unlike `requiredIdempotencyKey` an absent header
|
|
37
|
+
* is NOT a 400 — it selects legacy non-idempotent behavior for operations whose
|
|
38
|
+
* key is optional (the current installed macOS app sends no key). A present but
|
|
39
|
+
* malformed key still fails loudly (a key the client believed it sent must not
|
|
40
|
+
* silently degrade to non-idempotent).
|
|
41
|
+
*/
|
|
42
|
+
export declare function optionalIdempotencyKey(req: IncomingMessage): string | undefined;
|
|
30
43
|
//# sourceMappingURL=run-start.d.ts.map
|
package/dist/run-start.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-start.d.ts","sourceRoot":"","sources":["../src/run-start.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAEjE,OAAO,
|
|
1
|
+
{"version":3,"file":"run-start.d.ts","sourceRoot":"","sources":["../src/run-start.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAEjE,OAAO,EAEL,sBAAsB,EAEvB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,KAAK,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAI9E,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAExE;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,sBAAsB,GAAG,sBAAsB,CA2DxF;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,OAAO,GAAG,sBAAsB,CAG7E;AAED,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,kBAAkB,CAAC;IAC3B,QAAQ,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACjD,YAAY,CAAC,GAAG,EAAE,cAAc,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;IACxD,IAAI,CAAC,GAAG,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI,CAAC;IAC/D,oBAAoB,CAAC,GAAG,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxE,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,WAAW,CAAC,sBAAsB,CAAC,aAAa,CAAC,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChG,wBAAwB,CAAC,EAAE,CAAC,OAAO,EAAE,sBAAsB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/E;AAED,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,eAAe,EACpB,QAAQ,EAAE,OAAO,GAChB;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,CAsBnD;AAED;;;;;;iEAMiE;AACjE,wBAAsB,eAAe,CACnC,GAAG,EAAE,qBAAqB,EAC1B,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,GAClB,OAAO,CAAC,IAAI,CAAC,CAoEf;AAED,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,eAAe,GAAG,MAAM,CAiBnE;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,eAAe,GAAG,MAAM,GAAG,SAAS,CAiB/E"}
|
package/dist/run-start.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { existsSync, lstatSync, mkdirSync } from "node:fs";
|
|
8
8
|
import { isAbsolute } from "node:path";
|
|
9
|
-
import { ControlRunStartRequest, runStartStrategyViolations } from "@claudexor/schema";
|
|
9
|
+
import { ControlQueuedRunInfo, ControlRunStartRequest, runStartStrategyViolations, } from "@claudexor/schema";
|
|
10
10
|
import { assertNoInlineSecretValues, noProjectRepoRoot } from "@claudexor/util";
|
|
11
11
|
const NO_PROJECT_ROOT = noProjectRepoRoot();
|
|
12
12
|
export function validateAbsoluteRepoRoot(repoRoot) {
|
|
@@ -71,6 +71,28 @@ export function normalizeRunStartRequest(raw) {
|
|
|
71
71
|
assertNoInlineSecretValues(raw);
|
|
72
72
|
return normalizeRunStart(ControlRunStartRequest.parse(raw ?? {}));
|
|
73
73
|
}
|
|
74
|
+
export function unboundRunStartResponse(rec, terminal) {
|
|
75
|
+
// errorStatus is served verbatim only inside the failure range; anything
|
|
76
|
+
// else (absent, or a non-4xx/5xx value from a defective writer) must not
|
|
77
|
+
// turn a terminal failure body into a 2xx/3xx response.
|
|
78
|
+
const errorStatus = typeof rec.errorStatus === "number" &&
|
|
79
|
+
Number.isInteger(rec.errorStatus) &&
|
|
80
|
+
rec.errorStatus >= 400 &&
|
|
81
|
+
rec.errorStatus <= 599
|
|
82
|
+
? rec.errorStatus
|
|
83
|
+
: 500;
|
|
84
|
+
return {
|
|
85
|
+
status: terminal ? errorStatus : 202,
|
|
86
|
+
body: {
|
|
87
|
+
...ControlQueuedRunInfo.parse({ jobId: rec.id, state: rec.state, error: rec.error }),
|
|
88
|
+
...(rec.errorCode ? { code: rec.errorCode } : {}),
|
|
89
|
+
// Only a TYPED refusal proves non-retryability; an untyped terminal
|
|
90
|
+
// (e.g. cancelled or interrupted before a run dir bound) makes no
|
|
91
|
+
// retryability claim, matching the pre-change body.
|
|
92
|
+
...(terminal && rec.errorCode ? { retryable: false } : {}),
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
}
|
|
74
96
|
/** POST /v2/runs: validates, deduplicates, durably enqueues, then returns its handle.
|
|
75
97
|
*
|
|
76
98
|
* D10: POST /runs is the ONE-SHOT, THREAD-LESS run surface. A thread turn is
|
|
@@ -167,4 +189,31 @@ export function requiredIdempotencyKey(req) {
|
|
|
167
189
|
}
|
|
168
190
|
return value;
|
|
169
191
|
}
|
|
192
|
+
/**
|
|
193
|
+
* An OPTIONAL Idempotency-Key: `undefined` when the client sent none, the
|
|
194
|
+
* validated value when present. Unlike `requiredIdempotencyKey` an absent header
|
|
195
|
+
* is NOT a 400 — it selects legacy non-idempotent behavior for operations whose
|
|
196
|
+
* key is optional (the current installed macOS app sends no key). A present but
|
|
197
|
+
* malformed key still fails loudly (a key the client believed it sent must not
|
|
198
|
+
* silently degrade to non-idempotent).
|
|
199
|
+
*/
|
|
200
|
+
export function optionalIdempotencyKey(req) {
|
|
201
|
+
const header = req.headers["idempotency-key"];
|
|
202
|
+
if (header === undefined)
|
|
203
|
+
return undefined;
|
|
204
|
+
if (Array.isArray(header) || typeof header !== "string" || !header.trim()) {
|
|
205
|
+
throw Object.assign(new Error("Idempotency-Key, when present, must be a non-empty value"), {
|
|
206
|
+
code: "invalid_idempotency_key",
|
|
207
|
+
status: 400,
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
const value = header.trim();
|
|
211
|
+
if (value.length > 256) {
|
|
212
|
+
throw Object.assign(new Error("Idempotency-Key must contain 1-256 characters"), {
|
|
213
|
+
code: "invalid_idempotency_key",
|
|
214
|
+
status: 400,
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
return value;
|
|
218
|
+
}
|
|
170
219
|
//# sourceMappingURL=run-start.js.map
|
package/dist/run-start.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-start.js","sourceRoot":"","sources":["../src/run-start.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAE3D,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,
|
|
1
|
+
{"version":3,"file":"run-start.js","sourceRoot":"","sources":["../src/run-start.ts"],"names":[],"mappings":"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"}
|
package/dist/run-timeline.d.ts
CHANGED
|
@@ -1,26 +1,67 @@
|
|
|
1
|
-
import { ControlTimelineEvent, ControlWebEvidence, type RunTelemetry, type TaskContract } from "@claudexor/schema";
|
|
1
|
+
import { ControlTimelineEvent, type ControlEvidenceIntegrity, ControlWebEvidence, type RunTelemetry, type TaskContract } from "@claudexor/schema";
|
|
2
2
|
export declare function eventsParseCountForTests(): number;
|
|
3
3
|
export declare function resetEventsParseCountForTests(): void;
|
|
4
4
|
/** Structural dependency: anything carrying an optional runDir works. */
|
|
5
5
|
export interface RunDirCarrier {
|
|
6
6
|
runDir?: string;
|
|
7
7
|
}
|
|
8
|
+
/**
|
|
9
|
+
* Typed record of what the single lenient events.jsonl parser had to skip.
|
|
10
|
+
* QA-074: a lenient reader that silently drops malformed/unreadable lines
|
|
11
|
+
* turns incomplete canonical evidence into an apparently clean partial set.
|
|
12
|
+
* This counts every non-intentional omission so the projections that already
|
|
13
|
+
* disclose intentional bounding (timeline truncation) can also disclose
|
|
14
|
+
* corruption, and distinguishes a legitimately-absent file (queued run) from a
|
|
15
|
+
* genuinely unreadable one.
|
|
16
|
+
*/
|
|
17
|
+
export interface RunEventsIntegrity {
|
|
18
|
+
/** File is absent (ENOENT) — a legitimate empty state for a queued/aborted-before-first-event run, NOT corruption. */
|
|
19
|
+
absent: boolean;
|
|
20
|
+
/** File exists but could not be read (permission/IO error, or a symlink/directory in place of the file). Evidence is UNAVAILABLE. */
|
|
21
|
+
unreadable: boolean;
|
|
22
|
+
/** Non-empty lines that failed JSON.parse and were dropped. */
|
|
23
|
+
malformedLines: number;
|
|
24
|
+
/** JSON values that parsed but were not plain objects (arrays/scalars/null) and were dropped. */
|
|
25
|
+
nonObjectLines: number;
|
|
26
|
+
/** The bounded-tail read intentionally dropped a torn first line (D15). Intentional bounding — NOT a corruption signal. */
|
|
27
|
+
tailTruncated: boolean;
|
|
28
|
+
}
|
|
29
|
+
export interface RunEventsRead {
|
|
30
|
+
events: Record<string, unknown>[];
|
|
31
|
+
integrity: RunEventsIntegrity;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Collapse a typed integrity record to the three-state evidence level the DTOs
|
|
35
|
+
* disclose. Intentional bounding (tailTruncated / absent-for-queued) is NOT an
|
|
36
|
+
* integrity problem, so it maps to `complete` — only genuine unreadable files
|
|
37
|
+
* and skipped corrupt lines degrade the level.
|
|
38
|
+
*/
|
|
39
|
+
export declare function evidenceLevel(i: RunEventsIntegrity): ControlEvidenceIntegrity;
|
|
40
|
+
/**
|
|
41
|
+
* The ONE lenient events.jsonl reader for Control projections. Returns the
|
|
42
|
+
* parsed objects AND a typed count of everything it skipped, so no caller can
|
|
43
|
+
* mistake a partial/empty set for complete evidence (QA-074). `readRunEvents`
|
|
44
|
+
* preserves the historical array-only shape for callers that do not disclose
|
|
45
|
+
* integrity.
|
|
46
|
+
*/
|
|
47
|
+
export declare function readRunEventsWithIntegrity(rec: RunDirCarrier): RunEventsRead;
|
|
8
48
|
export declare function readRunEvents(rec: RunDirCarrier): Record<string, unknown>[];
|
|
9
49
|
export declare function eventPayload(ev: Record<string, unknown>): Record<string, unknown>;
|
|
10
50
|
export declare function stringOrNull(value: unknown): string | null;
|
|
11
51
|
/** Project the orchestrator-owned telemetry artifact without reconstructing evidence. */
|
|
12
52
|
export declare function controlWebEvidence(telemetry: RunTelemetry | null, task: TaskContract | null): ControlWebEvidence;
|
|
13
|
-
export declare function timelineEvents(rec: RunDirCarrier, events?: Record<string, unknown>[]): ControlTimelineEvent[];
|
|
53
|
+
export declare function timelineEvents(rec: RunDirCarrier, events?: Record<string, unknown>[], integrity?: RunEventsIntegrity): ControlTimelineEvent[];
|
|
14
54
|
/** The LAST plan.progress event's typed items (the live plan checklist), or
|
|
15
55
|
* null when the run never emitted one. Last-wins by construction: plan tools
|
|
16
56
|
* re-emit the whole list on every revision. On RACES the candidates' lists
|
|
17
57
|
* interleave — prefer the WINNER's attempt (decision.yaml) so the Plan tab
|
|
18
58
|
* shows the shipped candidate's checklist, not whichever emitted last. */
|
|
19
|
-
export declare function latestPlanProgress(rec: RunDirCarrier, winnerAttemptId?: string | null, eventsSnapshot?: Record<string, unknown>[]): {
|
|
59
|
+
export declare function latestPlanProgress(rec: RunDirCarrier, winnerAttemptId?: string | null, eventsSnapshot?: Record<string, unknown>[], integrity?: RunEventsIntegrity): {
|
|
20
60
|
items: Array<{
|
|
21
61
|
id: string;
|
|
22
62
|
title: string;
|
|
23
63
|
status: "pending" | "in_progress" | "completed";
|
|
24
64
|
}>;
|
|
65
|
+
evidence: ControlEvidenceIntegrity;
|
|
25
66
|
} | null;
|
|
26
67
|
//# sourceMappingURL=run-timeline.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-timeline.d.ts","sourceRoot":"","sources":["../src/run-timeline.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"run-timeline.d.ts","sourceRoot":"","sources":["../src/run-timeline.ts"],"names":[],"mappings":"AAQA,OAAO,EACL,oBAAoB,EACpB,KAAK,wBAAwB,EAC7B,kBAAkB,EAElB,KAAK,YAAY,EACjB,KAAK,YAAY,EAClB,MAAM,mBAAmB,CAAC;AAsB3B,wBAAgB,wBAAwB,IAAI,MAAM,CAEjD;AACD,wBAAgB,6BAA6B,IAAI,IAAI,CAEpD;AAED,yEAAyE;AACzE,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,kBAAkB;IACjC,sHAAsH;IACtH,MAAM,EAAE,OAAO,CAAC;IAChB,qIAAqI;IACrI,UAAU,EAAE,OAAO,CAAC;IACpB,+DAA+D;IAC/D,cAAc,EAAE,MAAM,CAAC;IACvB,iGAAiG;IACjG,cAAc,EAAE,MAAM,CAAC;IACvB,2HAA2H;IAC3H,aAAa,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IAClC,SAAS,EAAE,kBAAkB,CAAC;CAC/B;AAUD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,kBAAkB,GAAG,wBAAwB,CAI7E;AAED;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,aAAa,GAAG,aAAa,CA2E5E;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAE3E;AAED,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAIjF;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAE1D;AAED,yFAAyF;AACzF,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,YAAY,GAAG,IAAI,EAC9B,IAAI,EAAE,YAAY,GAAG,IAAI,GACxB,kBAAkB,CAuBpB;AAoCD,wBAAgB,cAAc,CAC5B,GAAG,EAAE,aAAa,EAClB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EAClC,SAAS,CAAC,EAAE,kBAAkB,GAC7B,oBAAoB,EAAE,CA4ExB;AA+BD;;;;0EAI0E;AAC1E,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,aAAa,EAClB,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,EAC/B,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EAC1C,SAAS,CAAC,EAAE,kBAAkB,GAC7B;IACD,KAAK,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,SAAS,GAAG,aAAa,GAAG,WAAW,CAAA;KAAE,CAAC,CAAC;IAC7F,QAAQ,EAAE,wBAAwB,CAAC;CACpC,GAAG,IAAI,CAgDP"}
|