@cat-factory/server 0.290.1 → 0.292.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.
@@ -0,0 +1,88 @@
1
+ // How a container job is IDENTIFIED and ADDRESSED: the id the harness keys it by, the ref the
2
+ // transport routes it by, and the image variant that decides which container both mean.
3
+ //
4
+ // Extracted from `ContainerAgentExecutor` because the three answer one question ("which job, in
5
+ // which container") and the executor is at its size budget. They are pure functions of the run
6
+ // context or the job handle, which is what lets the dispatch site and the poll site derive the
7
+ // same answer with nothing carried between them: the poll runs in another process after a
8
+ // durable replay and rebuilds the handle from the persisted step alone.
9
+ /**
10
+ * The harness job id for one dispatch: the run (execution) id, the agent kind, and — past the
11
+ * first job of that kind in the run — the `dispatchEpoch`. A run executes a sequence of steps that
12
+ * all share the one per-run container, so each job needs an id that is UNIQUE WITHIN THE RUN: the
13
+ * harness keys its per-kind job registries by it, and two jobs sharing an id alias there (the bug
14
+ * where an `architect` /explore poll read back the `spec-writer`'s /spec result). The run itself is
15
+ * addressed separately by the execution id (the {@link RunnerJobRef.runId}).
16
+ *
17
+ * The epoch is what makes that uniqueness total, because the engine dispatches one kind more than
18
+ * once per run in two ways: a step RE-dispatched (a Tester re-test after a fixer round, a gate's
19
+ * helper retry, a companion's rework round, an eviction recovery) and the same helper kind
20
+ * escalated off DIFFERENT steps (`fixer` serves four gates). The harness re-attaches to an EXISTING
21
+ * job id rather than re-running (replay idempotency), and a container-reusing transport — a warm
22
+ * local pool, a self-hosted runner pool — keeps that registry alive across rounds, since reclaiming
23
+ * a pooled member does NOT destroy it. So a reused id replays a completed job: the Tester that
24
+ * appeared to "pass regardless" and never re-tested, an eviction recovery landing back on the job
25
+ * whose runner just died. `dispatchEpochFor` counts the run's prior dispatches of the kind, so the
26
+ * id names the n-th job of that kind and the run's first keeps the unsuffixed shape.
27
+ */
28
+ export function stepJobId(executionId, agentKind, dispatchEpoch = 0) {
29
+ const base = `${executionId}-${agentKind}`;
30
+ return dispatchEpoch > 0 ? `${base}-${dispatchEpoch}` : base;
31
+ }
32
+ /** The provider slug from a handle's `provider:model` string (fallback when the handle omits `provider`). */
33
+ export function providerOf(model) {
34
+ if (!model)
35
+ return 'unknown';
36
+ const colon = model.indexOf(':');
37
+ return colon > 0 ? model.slice(0, colon) : model;
38
+ }
39
+ /**
40
+ * The executor image a kind's steps run on, as the kind DECLARED it on its registration
41
+ * (`ui` selects the heavier Playwright + browser image; absent means the default one, so the
42
+ * browser never bloats every other kind's cold start).
43
+ *
44
+ * Read at the dispatch site AND at the poll/stop site rather than persisted on the handle,
45
+ * because a per-run container backend puts a differently-imaged step in its OWN container and
46
+ * every later call has to address that one. Both sites already hold the agent kind, so the
47
+ * variant is a pure function of state the step carries, and a handle minted before this existed
48
+ * resolves to exactly what it ran on.
49
+ */
50
+ export function imageVariantFor(agentKind, registry) {
51
+ return agentKind ? registry.agentStep(agentKind)?.image : undefined;
52
+ }
53
+ /**
54
+ * Every container a RUN holds, as image variants: `undefined` (the ordinary one, always — it is
55
+ * where the run's default-image steps ran) plus one per NON-DEFAULT image any of the dispatched
56
+ * kinds declared.
57
+ *
58
+ * This is what makes a run-level reclaim total. A per-run container backend hosts a whole run in
59
+ * ONE container UNLESS a step declared a different image, and then there are two; addressing
60
+ * only the ordinary one leaves a browser container running until its maximum lifetime elapses.
61
+ * Deriving the set from the kinds the run DISPATCHED (rather than reclaiming every variant this
62
+ * build knows) keeps the reclaim to containers that exist: `idFromName` answers a stub for a
63
+ * container that never ran, so a blanket sweep would instantiate one per unused variant and
64
+ * report the kill as a success.
65
+ */
66
+ export function runImageVariants(agentKinds, registry) {
67
+ const variants = new Set([undefined]);
68
+ for (const kind of agentKinds) {
69
+ const image = imageVariantFor(kind, registry);
70
+ if (image && image !== 'default')
71
+ variants.add(image);
72
+ }
73
+ return [...variants];
74
+ }
75
+ /**
76
+ * The {@link RunnerJobRef} a job handle addresses: the run (for the per-run container)
77
+ * plus the per-step job id. Falls back to the job id as the run id for a handle minted
78
+ * before run ids were carried (or a single-job flow where the two coincide).
79
+ */
80
+ export function refForHandle(handle, registry) {
81
+ const image = imageVariantFor(handle.agentKind, registry);
82
+ return {
83
+ runId: handle.runId ?? handle.jobId,
84
+ jobId: handle.jobId,
85
+ ...(image ? { image } : {}),
86
+ };
87
+ }
88
+ //# sourceMappingURL=containerJobAddressing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"containerJobAddressing.js","sourceRoot":"","sources":["../../src/agents/containerJobAddressing.ts"],"names":[],"mappings":"AAGA,8FAA8F;AAC9F,wFAAwF;AACxF,EAAE;AACF,gGAAgG;AAChG,+FAA+F;AAC/F,+FAA+F;AAC/F,0FAA0F;AAC1F,wEAAwE;AAExE;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,SAAS,CAAC,WAAmB,EAAE,SAAiB,EAAE,aAAa,GAAG,CAAC;IACjF,MAAM,IAAI,GAAG,GAAG,WAAW,IAAI,SAAS,EAAE,CAAA;IAC1C,OAAO,aAAa,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,aAAa,EAAE,CAAC,CAAC,CAAC,IAAI,CAAA;AAC9D,CAAC;AAED,6GAA6G;AAC7G,MAAM,UAAU,UAAU,CAAC,KAAyB;IAClD,IAAI,CAAC,KAAK;QAAE,OAAO,SAAS,CAAA;IAC5B,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IAChC,OAAO,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAA;AAClD,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,eAAe,CAC7B,SAA6B,EAC7B,QAA2B;IAE3B,OAAO,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,SAAS,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,SAAS,CAAA;AACrE,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,gBAAgB,CAC9B,UAA6B,EAC7B,QAA2B;IAE3B,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAiC,CAAC,SAAS,CAAC,CAAC,CAAA;IACrE,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;QAC9B,MAAM,KAAK,GAAG,eAAe,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAA;QAC7C,IAAI,KAAK,IAAI,KAAK,KAAK,SAAS;YAAE,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;IACvD,CAAC;IACD,OAAO,CAAC,GAAG,QAAQ,CAAC,CAAA;AACtB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,MAAsB,EAAE,QAA2B;IAC9E,MAAM,KAAK,GAAG,eAAe,CAAC,MAAM,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAA;IACzD,OAAO;QACL,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK;QACnC,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC5B,CAAA;AACH,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cat-factory/server",
3
- "version": "0.290.1",
3
+ "version": "0.292.0",
4
4
  "description": "Runtime-neutral HTTP layer for the Agent Architecture Board: the Hono controllers, middleware (auth/authz/CORS/error), request helpers and the gateway seams shared by every deployment facade (Cloudflare Worker, Node service).",
5
5
  "repository": {
6
6
  "type": "git",
@@ -31,13 +31,13 @@
31
31
  "jose": "^6.2.8",
32
32
  "pino": "^10.3.1",
33
33
  "valibot": "^1.4.2",
34
- "@cat-factory/agents": "0.133.1",
34
+ "@cat-factory/agents": "0.133.3",
35
35
  "@cat-factory/contracts": "0.317.0",
36
- "@cat-factory/kernel": "0.305.0",
37
- "@cat-factory/integrations": "0.164.1",
36
+ "@cat-factory/integrations": "0.165.1",
38
37
  "@cat-factory/mcp-server": "0.41.0",
39
- "@cat-factory/orchestration": "0.276.0",
40
- "@cat-factory/spend": "0.15.99"
38
+ "@cat-factory/orchestration": "0.277.0",
39
+ "@cat-factory/spend": "0.15.101",
40
+ "@cat-factory/kernel": "0.307.0"
41
41
  },
42
42
  "devDependencies": {
43
43
  "@types/node": "^26.2.0",