@cat-factory/kernel 0.214.1 → 0.216.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.
Files changed (44) hide show
  1. package/dist/domain/binary-generator-registry.d.ts +66 -0
  2. package/dist/domain/binary-generator-registry.d.ts.map +1 -0
  3. package/dist/domain/binary-generator-registry.js +89 -0
  4. package/dist/domain/binary-generator-registry.js.map +1 -0
  5. package/dist/domain/binary-generators.d.ts +97 -0
  6. package/dist/domain/binary-generators.d.ts.map +1 -0
  7. package/dist/domain/binary-generators.js +212 -0
  8. package/dist/domain/binary-generators.js.map +1 -0
  9. package/dist/domain/binary-output-paths.d.ts +25 -0
  10. package/dist/domain/binary-output-paths.d.ts.map +1 -0
  11. package/dist/domain/binary-output-paths.js +47 -0
  12. package/dist/domain/binary-output-paths.js.map +1 -0
  13. package/dist/domain/binary-outputs.d.ts +37 -18
  14. package/dist/domain/binary-outputs.d.ts.map +1 -1
  15. package/dist/domain/binary-outputs.js +97 -45
  16. package/dist/domain/binary-outputs.js.map +1 -1
  17. package/dist/index.d.ts +5 -1
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +16 -1
  20. package/dist/index.js.map +1 -1
  21. package/dist/ports/agent-executor.d.ts +13 -0
  22. package/dist/ports/agent-executor.d.ts.map +1 -1
  23. package/dist/ports/agent-executor.js.map +1 -1
  24. package/dist/ports/agent-runs.d.ts +22 -0
  25. package/dist/ports/agent-runs.d.ts.map +1 -1
  26. package/dist/ports/agent-tools.d.ts +36 -13
  27. package/dist/ports/agent-tools.d.ts.map +1 -1
  28. package/dist/ports/binary-generators.d.ts +49 -0
  29. package/dist/ports/binary-generators.d.ts.map +1 -0
  30. package/dist/ports/binary-generators.js +45 -0
  31. package/dist/ports/binary-generators.js.map +1 -0
  32. package/dist/ports/index.d.ts +3 -2
  33. package/dist/ports/index.d.ts.map +1 -1
  34. package/dist/ports/index.js +1 -0
  35. package/dist/ports/index.js.map +1 -1
  36. package/dist/ports/llm-trace-sink.d.ts +26 -5
  37. package/dist/ports/llm-trace-sink.d.ts.map +1 -1
  38. package/dist/ports/llm-trace-sink.js +52 -56
  39. package/dist/ports/llm-trace-sink.js.map +1 -1
  40. package/dist/ports/operational-metrics.d.ts +87 -0
  41. package/dist/ports/operational-metrics.d.ts.map +1 -0
  42. package/dist/ports/operational-metrics.js +67 -0
  43. package/dist/ports/operational-metrics.js.map +1 -0
  44. package/package.json +2 -2
@@ -0,0 +1,87 @@
1
+ /**
2
+ * The closed set of operational counters. A closed union rather than a free string, so
3
+ * adding a signal is a typecheck-visible decision (with a metric name and a documented
4
+ * meaning) instead of a name typo that reports zero forever.
5
+ */
6
+ export type OperationalCounter =
7
+ /** A stale run whose durable instance was lost and was re-created by a sweeper. */
8
+ 'sweep.run_redriven'
9
+ /** A stale run whose durable instance was terminal, so the sweeper settled it instead. */
10
+ | 'sweep.run_finalized'
11
+ /** A run failed `stalled`: re-driving never resurrected it past the hard deadline. */
12
+ | 'sweep.run_stalled'
13
+ /** A sweeper pass threw. Dimensioned by `sweep`, so one sick sweeper is identifiable. */
14
+ | 'sweep.failed'
15
+ /** A container job dispatch threw — the job never existed, so no poll can report it. */
16
+ | 'container.dispatch_failed'
17
+ /** A container job settled as evicted/crashed. Dimensioned by the eviction kind. */
18
+ | 'container.evicted'
19
+ /** An observability export was dropped (a trace sink, a metrics POST). */
20
+ | 'telemetry.export_dropped'
21
+ /** An outbound notification delivery failed after its retries. */
22
+ | 'notification.delivery_failed'
23
+ /** An app-cache read served from memory. Dimensioned by cache name. */
24
+ | 'cache.hit'
25
+ /** An app-cache read that had to run its loader. Dimensioned by cache name. */
26
+ | 'cache.miss';
27
+ /** The closed set of operational gauges — point-in-time readings, never accumulated. */
28
+ export type OperationalGauge =
29
+ /** Jobs waiting in a durable queue right now. Dimensioned by `queue`. */
30
+ 'queue.depth';
31
+ /**
32
+ * The split dimensions of one sample. Values MUST be bounded — a queue name, a cache name,
33
+ * an eviction kind — never a run/workspace/job id: every distinct value is its own metric
34
+ * time series in the operator's backend, so an unbounded dimension is a cardinality
35
+ * explosion that costs money and eventually gets the series dropped. The correlation ids
36
+ * belong on the LOG line (which is why every increment site also logs), not here.
37
+ */
38
+ export type OperationalDimensions = Readonly<Record<string, string>>;
39
+ /** One accumulated counter delta, ready to export. */
40
+ export interface OperationalCounterSample {
41
+ counter: OperationalCounter;
42
+ dimensions: OperationalDimensions;
43
+ /** The delta accumulated since the previous drain (always > 0 — empty keys aren't emitted). */
44
+ value: number;
45
+ }
46
+ /** One point-in-time gauge reading. */
47
+ export interface OperationalGaugeSample {
48
+ gauge: OperationalGauge;
49
+ dimensions: OperationalDimensions;
50
+ value: number;
51
+ }
52
+ /**
53
+ * Where operational events are counted. Injected the same way `Logger` is, so a domain
54
+ * service can count an event without knowing whether the deployment exports metrics at all.
55
+ */
56
+ export interface OperationalMetrics {
57
+ /**
58
+ * Add `value` (default 1) to `counter` under `dimensions`. Never throws, never awaits —
59
+ * a call site on a hot path (a cache read) pays a Map lookup and an add.
60
+ */
61
+ increment(counter: OperationalCounter, dimensions?: OperationalDimensions, value?: number): void;
62
+ }
63
+ /**
64
+ * An {@link OperationalMetrics} that accumulates in memory until drained. The accumulate/drain
65
+ * split is what makes delta export correct: whoever drains owns a set of deltas nobody else
66
+ * will report, so two processes (or two Worker isolates) can flush independently and the
67
+ * backend's sum is still right.
68
+ */
69
+ export interface OperationalMetricsCollector extends OperationalMetrics {
70
+ /**
71
+ * Take everything accumulated since the last call and RESET. Returns `[]` when nothing
72
+ * happened, which a caller should treat as "nothing to flush" — never as a reason to
73
+ * publish zeroes (an unflushed zero and a genuine zero are different facts, and only the
74
+ * absence of a data point states the first one honestly).
75
+ */
76
+ drain(): OperationalCounterSample[];
77
+ }
78
+ /** The disposition for a deployment that exports nothing: count into the void, cheaply. */
79
+ export declare const noopOperationalMetrics: OperationalMetrics;
80
+ /**
81
+ * Build an in-memory {@link OperationalMetricsCollector}. One per process (Node/local, drained
82
+ * by the platform-metrics sweep) or one per isolate (the Worker, drained at the end of each
83
+ * invocation — an isolate can be discarded at any moment, so anything it holds unflushed is
84
+ * simply lost).
85
+ */
86
+ export declare function createOperationalMetricsCollector(): OperationalMetricsCollector;
87
+ //# sourceMappingURL=operational-metrics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"operational-metrics.d.ts","sourceRoot":"","sources":["../../src/ports/operational-metrics.ts"],"names":[],"mappings":"AAoBA;;;;GAIG;AACH,MAAM,MAAM,kBAAkB;AAC5B,mFAAmF;AACjF,oBAAoB;AACtB,0FAA0F;GACxF,qBAAqB;AACvB,sFAAsF;GACpF,mBAAmB;AACrB,yFAAyF;GACvF,cAAc;AAChB,wFAAwF;GACtF,2BAA2B;AAC7B,oFAAoF;GAClF,mBAAmB;AACrB,0EAA0E;GACxE,0BAA0B;AAC5B,kEAAkE;GAChE,8BAA8B;AAChC,uEAAuE;GACrE,WAAW;AACb,+EAA+E;GAC7E,YAAY,CAAA;AAUhB,wFAAwF;AACxF,MAAM,MAAM,gBAAgB;AAC1B,yEAAyE;AACzE,aAAa,CAAA;AAEf;;;;;;GAMG;AACH,MAAM,MAAM,qBAAqB,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;AAEpE,sDAAsD;AACtD,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,kBAAkB,CAAA;IAC3B,UAAU,EAAE,qBAAqB,CAAA;IACjC,+FAA+F;IAC/F,KAAK,EAAE,MAAM,CAAA;CACd;AAED,uCAAuC;AACvC,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,gBAAgB,CAAA;IACvB,UAAU,EAAE,qBAAqB,CAAA;IACjC,KAAK,EAAE,MAAM,CAAA;CACd;AAED;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,SAAS,CAAC,OAAO,EAAE,kBAAkB,EAAE,UAAU,CAAC,EAAE,qBAAqB,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACjG;AAED;;;;;GAKG;AACH,MAAM,WAAW,2BAA4B,SAAQ,kBAAkB;IACrE;;;;;OAKG;IACH,KAAK,IAAI,wBAAwB,EAAE,CAAA;CACpC;AAED,2FAA2F;AAC3F,eAAO,MAAM,sBAAsB,EAAE,kBAA4C,CAAA;AAYjF;;;;;GAKG;AACH,wBAAgB,iCAAiC,IAAI,2BAA2B,CA8B/E"}
@@ -0,0 +1,67 @@
1
+ // The operational-metrics port: the counters and gauges that describe how the DEPLOYMENT is
2
+ // behaving, as opposed to how a run went.
3
+ //
4
+ // `PlatformMetricsRepository` already answers "how are the RUNS doing" by aggregating
5
+ // `agent_runs` per account. It structurally cannot answer the questions an operator asks
6
+ // during an incident — how often a container dispatch is failing, how many stale runs the
7
+ // sweeper is re-driving, whether the queue is draining, whether telemetry batches are being
8
+ // dropped — because none of those are rows in a table. They are EVENTS that happen and are
9
+ // gone. This port is where they are counted.
10
+ //
11
+ // Two shapes, because the two facts have different lifetimes:
12
+ // - a COUNTER is a delta accumulated since the last flush (evictions, re-drives, cache
13
+ // misses). Exported with delta temporality, so a partial flush from one process/isolate
14
+ // still sums correctly with every other one.
15
+ // - a GAUGE is read at export time from something that already knows the answer (queue
16
+ // depth). It is never accumulated here; the sweep probes for it.
17
+ //
18
+ // The whole surface is fire-and-forget and MUST NOT throw, for the same reason `Logger` must
19
+ // not: instrumentation that can fail turns observability into a new failure class.
20
+ /** The disposition for a deployment that exports nothing: count into the void, cheaply. */
21
+ export const noopOperationalMetrics = { increment: () => { } };
22
+ /**
23
+ * A dimension map's stable identity, so `{a:'1',b:'2'}` and `{b:'2',a:'1'}` accumulate onto
24
+ * the same counter rather than two. Keys are sorted; the separators are control characters
25
+ * that cannot appear in a metric dimension value.
26
+ */
27
+ function dimensionKey(dimensions) {
28
+ const keys = Object.keys(dimensions).sort();
29
+ return keys.map((k) => `${k}${dimensions[k]}`).join('');
30
+ }
31
+ /**
32
+ * Build an in-memory {@link OperationalMetricsCollector}. One per process (Node/local, drained
33
+ * by the platform-metrics sweep) or one per isolate (the Worker, drained at the end of each
34
+ * invocation — an isolate can be discarded at any moment, so anything it holds unflushed is
35
+ * simply lost).
36
+ */
37
+ export function createOperationalMetricsCollector() {
38
+ // Keyed by `counter` then by the dimension identity, so a drain can rebuild both halves
39
+ // without parsing the composite key back apart.
40
+ const counters = new Map();
41
+ return {
42
+ increment(counter, dimensions = {}, value = 1) {
43
+ let byDimensions = counters.get(counter);
44
+ if (!byDimensions) {
45
+ byDimensions = new Map();
46
+ counters.set(counter, byDimensions);
47
+ }
48
+ const key = dimensionKey(dimensions);
49
+ const existing = byDimensions.get(key);
50
+ if (existing)
51
+ existing.value += value;
52
+ else
53
+ byDimensions.set(key, { dims: dimensions, value });
54
+ },
55
+ drain() {
56
+ const samples = [];
57
+ for (const [counter, byDimensions] of counters) {
58
+ for (const { dims, value } of byDimensions.values()) {
59
+ samples.push({ counter, dimensions: dims, value });
60
+ }
61
+ }
62
+ counters.clear();
63
+ return samples;
64
+ },
65
+ };
66
+ }
67
+ //# sourceMappingURL=operational-metrics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"operational-metrics.js","sourceRoot":"","sources":["../../src/ports/operational-metrics.ts"],"names":[],"mappings":"AAAA,4FAA4F;AAC5F,0CAA0C;AAC1C,EAAE;AACF,sFAAsF;AACtF,yFAAyF;AACzF,0FAA0F;AAC1F,4FAA4F;AAC5F,2FAA2F;AAC3F,6CAA6C;AAC7C,EAAE;AACF,8DAA8D;AAC9D,yFAAyF;AACzF,4FAA4F;AAC5F,iDAAiD;AACjD,yFAAyF;AACzF,qEAAqE;AACrE,EAAE;AACF,6FAA6F;AAC7F,mFAAmF;AA8FnF,2FAA2F;AAC3F,MAAM,CAAC,MAAM,sBAAsB,GAAuB,EAAE,SAAS,EAAE,GAAG,EAAE,GAAE,CAAC,EAAE,CAAA;AAEjF;;;;GAIG;AACH,SAAS,YAAY,CAAC,UAAiC;IACrD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,IAAI,EAAE,CAAA;IAC3C,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;AAC3D,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iCAAiC;IAC/C,wFAAwF;IACxF,gDAAgD;IAChD,MAAM,QAAQ,GAAG,IAAI,GAAG,EAGrB,CAAA;IACH,OAAO;QACL,SAAS,CAAC,OAAO,EAAE,UAAU,GAAG,EAAE,EAAE,KAAK,GAAG,CAAC;YAC3C,IAAI,YAAY,GAAG,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;YACxC,IAAI,CAAC,YAAY,EAAE,CAAC;gBAClB,YAAY,GAAG,IAAI,GAAG,EAAE,CAAA;gBACxB,QAAQ,CAAC,GAAG,CAAC,OAAO,EAAE,YAAY,CAAC,CAAA;YACrC,CAAC;YACD,MAAM,GAAG,GAAG,YAAY,CAAC,UAAU,CAAC,CAAA;YACpC,MAAM,QAAQ,GAAG,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;YACtC,IAAI,QAAQ;gBAAE,QAAQ,CAAC,KAAK,IAAI,KAAK,CAAA;;gBAChC,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAA;QACzD,CAAC;QACD,KAAK;YACH,MAAM,OAAO,GAA+B,EAAE,CAAA;YAC9C,KAAK,MAAM,CAAC,OAAO,EAAE,YAAY,CAAC,IAAI,QAAQ,EAAE,CAAC;gBAC/C,KAAK,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,YAAY,CAAC,MAAM,EAAE,EAAE,CAAC;oBACpD,OAAO,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;gBACpD,CAAC;YACH,CAAC;YACD,QAAQ,CAAC,KAAK,EAAE,CAAA;YAChB,OAAO,OAAO,CAAA;QAChB,CAAC;KACF,CAAA;AACH,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cat-factory/kernel",
3
- "version": "0.214.1",
3
+ "version": "0.216.0",
4
4
  "description": "Shared vocabulary, pure logic, and port interfaces for the Agent Architecture Board.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -26,7 +26,7 @@
26
26
  "dependencies": {
27
27
  "ai": "^7.0.47",
28
28
  "yaml": "^2.9.0",
29
- "@cat-factory/contracts": "0.211.0"
29
+ "@cat-factory/contracts": "0.213.0"
30
30
  },
31
31
  "devDependencies": {
32
32
  "@vitest/coverage-v8": "^4.1.10",