@zelari/core 2.9.2 → 2.11.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/context/ContextPolicy.d.ts +48 -0
- package/dist/context/ContextPolicy.d.ts.map +1 -0
- package/dist/context/ContextPolicy.js +71 -0
- package/dist/context/ContextPolicy.js.map +1 -0
- package/dist/context/ContextProjector.d.ts +44 -0
- package/dist/context/ContextProjector.d.ts.map +1 -0
- package/dist/context/ContextProjector.js +156 -0
- package/dist/context/ContextProjector.js.map +1 -0
- package/dist/context/index.d.ts +11 -0
- package/dist/context/index.d.ts.map +1 -0
- package/dist/context/index.js +11 -0
- package/dist/context/index.js.map +1 -0
- package/dist/context/parentContext.d.ts +39 -0
- package/dist/context/parentContext.d.ts.map +1 -0
- package/dist/context/parentContext.js +67 -0
- package/dist/context/parentContext.js.map +1 -0
- package/dist/core/AgentHarness.d.ts +38 -0
- package/dist/core/AgentHarness.d.ts.map +1 -1
- package/dist/core/AgentHarness.js +142 -0
- package/dist/core/AgentHarness.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/runtime/controls/RuntimeControlQueue.d.ts +35 -0
- package/dist/runtime/controls/RuntimeControlQueue.d.ts.map +1 -0
- package/dist/runtime/controls/RuntimeControlQueue.js +54 -0
- package/dist/runtime/controls/RuntimeControlQueue.js.map +1 -0
- package/dist/runtime/controls/SteeringObserver.d.ts +24 -0
- package/dist/runtime/controls/SteeringObserver.d.ts.map +1 -0
- package/dist/runtime/controls/SteeringObserver.js +46 -0
- package/dist/runtime/controls/SteeringObserver.js.map +1 -0
- package/dist/runtime/controls/index.d.ts +4 -0
- package/dist/runtime/controls/index.d.ts.map +1 -0
- package/dist/runtime/controls/index.js +4 -0
- package/dist/runtime/controls/index.js.map +1 -0
- package/dist/runtime/controls/types.d.ts +43 -0
- package/dist/runtime/controls/types.d.ts.map +1 -0
- package/dist/runtime/controls/types.js +18 -0
- package/dist/runtime/controls/types.js.map +1 -0
- package/dist/runtime/guards/DuplicateSearchGuard.d.ts +41 -0
- package/dist/runtime/guards/DuplicateSearchGuard.d.ts.map +1 -0
- package/dist/runtime/guards/DuplicateSearchGuard.js +150 -0
- package/dist/runtime/guards/DuplicateSearchGuard.js.map +1 -0
- package/dist/runtime/guards/FailureSignatureGuard.d.ts +34 -0
- package/dist/runtime/guards/FailureSignatureGuard.d.ts.map +1 -0
- package/dist/runtime/guards/FailureSignatureGuard.js +143 -0
- package/dist/runtime/guards/FailureSignatureGuard.js.map +1 -0
- package/dist/runtime/guards/NoProgressGuard.d.ts +23 -0
- package/dist/runtime/guards/NoProgressGuard.d.ts.map +1 -0
- package/dist/runtime/guards/NoProgressGuard.js +84 -0
- package/dist/runtime/guards/NoProgressGuard.js.map +1 -0
- package/dist/runtime/guards/ReasoningWatchdog.d.ts +48 -0
- package/dist/runtime/guards/ReasoningWatchdog.d.ts.map +1 -0
- package/dist/runtime/guards/ReasoningWatchdog.js +135 -0
- package/dist/runtime/guards/ReasoningWatchdog.js.map +1 -0
- package/dist/runtime/guards/RepetitionGuard.d.ts +22 -0
- package/dist/runtime/guards/RepetitionGuard.d.ts.map +1 -0
- package/dist/runtime/guards/RepetitionGuard.js +56 -0
- package/dist/runtime/guards/RepetitionGuard.js.map +1 -0
- package/dist/runtime/guards/index.d.ts +6 -0
- package/dist/runtime/guards/index.d.ts.map +1 -0
- package/dist/runtime/guards/index.js +6 -0
- package/dist/runtime/guards/index.js.map +1 -0
- package/dist/runtime/index.d.ts +4 -0
- package/dist/runtime/index.d.ts.map +1 -1
- package/dist/runtime/index.js +4 -0
- package/dist/runtime/index.js.map +1 -1
- package/dist/runtime/observers/MetricsObserver.d.ts +42 -0
- package/dist/runtime/observers/MetricsObserver.d.ts.map +1 -0
- package/dist/runtime/observers/MetricsObserver.js +110 -0
- package/dist/runtime/observers/MetricsObserver.js.map +1 -0
- package/dist/runtime/observers/ObserverBus.d.ts +49 -0
- package/dist/runtime/observers/ObserverBus.d.ts.map +1 -0
- package/dist/runtime/observers/ObserverBus.js +160 -0
- package/dist/runtime/observers/ObserverBus.js.map +1 -0
- package/dist/runtime/observers/TraceObserver.d.ts +36 -0
- package/dist/runtime/observers/TraceObserver.d.ts.map +1 -0
- package/dist/runtime/observers/TraceObserver.js +78 -0
- package/dist/runtime/observers/TraceObserver.js.map +1 -0
- package/dist/runtime/observers/composeObservers.d.ts +10 -0
- package/dist/runtime/observers/composeObservers.d.ts.map +1 -0
- package/dist/runtime/observers/composeObservers.js +30 -0
- package/dist/runtime/observers/composeObservers.js.map +1 -0
- package/dist/runtime/observers/index.d.ts +7 -0
- package/dist/runtime/observers/index.d.ts.map +1 -0
- package/dist/runtime/observers/index.js +7 -0
- package/dist/runtime/observers/index.js.map +1 -0
- package/dist/runtime/observers/resolve.d.ts +3 -0
- package/dist/runtime/observers/resolve.d.ts.map +1 -0
- package/dist/runtime/observers/resolve.js +30 -0
- package/dist/runtime/observers/resolve.js.map +1 -0
- package/dist/runtime/observers/types.d.ts +113 -0
- package/dist/runtime/observers/types.d.ts.map +1 -0
- package/dist/runtime/observers/types.js +13 -0
- package/dist/runtime/observers/types.js.map +1 -0
- package/dist/runtime/recorder/Redactor.d.ts +19 -0
- package/dist/runtime/recorder/Redactor.d.ts.map +1 -0
- package/dist/runtime/recorder/Redactor.js +78 -0
- package/dist/runtime/recorder/Redactor.js.map +1 -0
- package/dist/runtime/recorder/RunRecorder.d.ts +73 -0
- package/dist/runtime/recorder/RunRecorder.d.ts.map +1 -0
- package/dist/runtime/recorder/RunRecorder.js +137 -0
- package/dist/runtime/recorder/RunRecorder.js.map +1 -0
- package/dist/runtime/recorder/index.d.ts +8 -0
- package/dist/runtime/recorder/index.d.ts.map +1 -0
- package/dist/runtime/recorder/index.js +8 -0
- package/dist/runtime/recorder/index.js.map +1 -0
- package/dist/runtime/recorder/recorderObserver.d.ts +4 -0
- package/dist/runtime/recorder/recorderObserver.d.ts.map +1 -0
- package/dist/runtime/recorder/recorderObserver.js +63 -0
- package/dist/runtime/recorder/recorderObserver.js.map +1 -0
- package/dist/runtime/recorder/retention.d.ts +15 -0
- package/dist/runtime/recorder/retention.d.ts.map +1 -0
- package/dist/runtime/recorder/retention.js +105 -0
- package/dist/runtime/recorder/retention.js.map +1 -0
- package/dist/session/taskContract.d.ts +2 -2
- package/dist/shared/events.d.ts +40 -2
- package/dist/shared/events.d.ts.map +1 -1
- package/dist/shared/events.js.map +1 -1
- package/package.json +5 -1
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Centralized redaction for run-recorder payloads (Frontier PHASE 5, §99).
|
|
3
|
+
*
|
|
4
|
+
* Every writer funnels through `redactRuntimePayload()`; no individual
|
|
5
|
+
* recorder path is allowed to serialize secrets on its own. Best-effort by
|
|
6
|
+
* nature (regex-based), but the single choke point keeps patterns auditable.
|
|
7
|
+
*/
|
|
8
|
+
export const REDACTED = '[REDACTED]';
|
|
9
|
+
/** Object keys whose values are always redacted regardless of content. */
|
|
10
|
+
const SECRET_KEY_RE = /(pass(word|wd)?|secret|token|api[-_]?key|auth(orization)?|credential|private[-_]?key|access[-_]?key)/i;
|
|
11
|
+
const VALUE_PATTERNS = [
|
|
12
|
+
// "Authorization: <credential>" (with optional bearer/Basic scheme prefix) — whole value.
|
|
13
|
+
// Value class excludes [ ] so the [REDACTED] marker can never be re-matched.
|
|
14
|
+
{
|
|
15
|
+
re: /\b(authorization\s*[:=]\s*)(?:bearer|basic|token)\s+[^\s,;"'}\]\[]+/gi,
|
|
16
|
+
replacement: '$1[REDACTED]',
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
re: /\b(authorization\s*[:=]\s*)[^\s,;"'}\]\[]+/gi,
|
|
20
|
+
replacement: '$1[REDACTED]',
|
|
21
|
+
},
|
|
22
|
+
// Bare bearer schemes anywhere ("bearer <token>", any casing)
|
|
23
|
+
{ re: /\bbearer\s+[A-Za-z0-9\-._~+/]+=*/gi, replacement: 'bearer [REDACTED]' },
|
|
24
|
+
// OpenAI-style keys (sk-, sk-proj-)
|
|
25
|
+
{ re: /\bsk-(proj-)?[A-Za-z0-9_-]{8,}\b/g, replacement: 'sk-[REDACTED]' },
|
|
26
|
+
// GitHub tokens
|
|
27
|
+
{
|
|
28
|
+
re: /\b(ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9]{20,}\b/g,
|
|
29
|
+
replacement: '[REDACTED]',
|
|
30
|
+
},
|
|
31
|
+
{ re: /\bgithub_pat_[A-Za-z0-9_]{20,}\b/g, replacement: '[REDACTED]' },
|
|
32
|
+
// Slack
|
|
33
|
+
{ re: /\bxox[baprs]-[A-Za-z0-9-]{10,}\b/g, replacement: '[REDACTED]' },
|
|
34
|
+
// AWS access keys
|
|
35
|
+
{ re: /\bAKIA[0-9A-Z]{16}\b/g, replacement: '[REDACTED]' },
|
|
36
|
+
// Google OAuth
|
|
37
|
+
{ re: /\bya29\.[A-Za-z0-9\-_.]+/g, replacement: '[REDACTED]' },
|
|
38
|
+
// Secret-looking assignments, UPPER_SNAKE or lower: FOO_PASSWORD=x, password: x
|
|
39
|
+
{
|
|
40
|
+
re: /\b([A-Za-z0-9_]*(?:password|passwd|secret|token|api[_-]?key|apikey|access[_-]?key|private[_-]?key)[A-Za-z0-9_]*)\s*[:=]\s*("[^"]*"|'[^']*'|[^\s,;}&\]]+)/gi,
|
|
41
|
+
replacement: '$1=[REDACTED]',
|
|
42
|
+
},
|
|
43
|
+
];
|
|
44
|
+
/** Redact secret-looking substrings from free text. */
|
|
45
|
+
export function redactString(input) {
|
|
46
|
+
let out = input;
|
|
47
|
+
for (const { re, replacement } of VALUE_PATTERNS) {
|
|
48
|
+
out = out.replace(re, replacement);
|
|
49
|
+
}
|
|
50
|
+
return out;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Recursively redact a payload before it is persisted by the recorder.
|
|
54
|
+
* - secret-ish object keys → whole value replaced
|
|
55
|
+
* - strings → pattern scrub
|
|
56
|
+
* - arrays/objects → walked
|
|
57
|
+
* - primitives → passed through
|
|
58
|
+
*/
|
|
59
|
+
export function redactRuntimePayload(value) {
|
|
60
|
+
if (value === null || value === undefined)
|
|
61
|
+
return value;
|
|
62
|
+
if (typeof value === 'string')
|
|
63
|
+
return redactString(value);
|
|
64
|
+
if (typeof value === 'number' || typeof value === 'boolean')
|
|
65
|
+
return value;
|
|
66
|
+
if (Array.isArray(value))
|
|
67
|
+
return value.map((item) => redactRuntimePayload(item));
|
|
68
|
+
if (typeof value === 'object') {
|
|
69
|
+
const out = {};
|
|
70
|
+
for (const [key, val] of Object.entries(value)) {
|
|
71
|
+
out[key] = SECRET_KEY_RE.test(key) ? REDACTED : redactRuntimePayload(val);
|
|
72
|
+
}
|
|
73
|
+
return out;
|
|
74
|
+
}
|
|
75
|
+
// Functions / symbols / bigints: nothing useful to persist.
|
|
76
|
+
return REDACTED;
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=Redactor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Redactor.js","sourceRoot":"","sources":["../../../src/runtime/recorder/Redactor.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,CAAC,MAAM,QAAQ,GAAG,YAAY,CAAC;AAErC,0EAA0E;AAC1E,MAAM,aAAa,GACjB,uGAAuG,CAAC;AAE1G,MAAM,cAAc,GAA+C;IACjE,0FAA0F;IAC1F,6EAA6E;IAC7E;QACE,EAAE,EAAE,uEAAuE;QAC3E,WAAW,EAAE,cAAc;KAC5B;IACD;QACE,EAAE,EAAE,8CAA8C;QAClD,WAAW,EAAE,cAAc;KAC5B;IACD,8DAA8D;IAC9D,EAAE,EAAE,EAAE,oCAAoC,EAAE,WAAW,EAAE,mBAAmB,EAAE;IAC9E,oCAAoC;IACpC,EAAE,EAAE,EAAE,mCAAmC,EAAE,WAAW,EAAE,eAAe,EAAE;IACzE,gBAAgB;IAChB;QACE,EAAE,EAAE,6CAA6C;QACjD,WAAW,EAAE,YAAY;KAC1B;IACD,EAAE,EAAE,EAAE,mCAAmC,EAAE,WAAW,EAAE,YAAY,EAAE;IACtE,QAAQ;IACR,EAAE,EAAE,EAAE,mCAAmC,EAAE,WAAW,EAAE,YAAY,EAAE;IACtE,kBAAkB;IAClB,EAAE,EAAE,EAAE,uBAAuB,EAAE,WAAW,EAAE,YAAY,EAAE;IAC1D,eAAe;IACf,EAAE,EAAE,EAAE,2BAA2B,EAAE,WAAW,EAAE,YAAY,EAAE;IAC9D,gFAAgF;IAChF;QACE,EAAE,EAAE,4JAA4J;QAChK,WAAW,EAAE,eAAe;KAC7B;CACF,CAAC;AAEF,uDAAuD;AACvD,MAAM,UAAU,YAAY,CAAC,KAAa;IACxC,IAAI,GAAG,GAAG,KAAK,CAAC;IAChB,KAAK,MAAM,EAAE,EAAE,EAAE,WAAW,EAAE,IAAI,cAAc,EAAE,CAAC;QACjD,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,EAAE,EAAE,WAAW,CAAC,CAAC;IACrC,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,oBAAoB,CAAC,KAAc;IACjD,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IACxD,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,YAAY,CAAC,KAAK,CAAC,CAAC;IAC1D,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IAC1E,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,oBAAoB,CAAC,IAAI,CAAC,CAAC,CAAC;IACjF,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,GAAG,GAA4B,EAAE,CAAC;QACxC,KAAK,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAgC,CAAC,EAAE,CAAC;YAC1E,GAAG,CAAC,GAAG,CAAC,GAAG,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC;QAC5E,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IACD,4DAA4D;IAC5D,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
export interface RunRecorderOptions {
|
|
2
|
+
/** Root directory that contains one folder per run. */
|
|
3
|
+
runsDir: string;
|
|
4
|
+
runId?: string;
|
|
5
|
+
sessionId?: string;
|
|
6
|
+
mode?: string;
|
|
7
|
+
phase?: string;
|
|
8
|
+
cwd?: string;
|
|
9
|
+
models?: Record<string, string>;
|
|
10
|
+
now?: () => number;
|
|
11
|
+
}
|
|
12
|
+
export interface RunManifest {
|
|
13
|
+
version: 1;
|
|
14
|
+
runId: string;
|
|
15
|
+
sessionId?: string;
|
|
16
|
+
mode: string;
|
|
17
|
+
phase: string;
|
|
18
|
+
startedAt: number;
|
|
19
|
+
endedAt?: number;
|
|
20
|
+
status: 'running' | 'completed' | 'failed' | 'cancelled';
|
|
21
|
+
cwd: string;
|
|
22
|
+
models: Record<string, string>;
|
|
23
|
+
}
|
|
24
|
+
/** Metrics the recorder itself can count truthfully at finalize time. */
|
|
25
|
+
export interface RunMetricsFile {
|
|
26
|
+
durationMs: number;
|
|
27
|
+
modelCalls: number;
|
|
28
|
+
toolCalls: number;
|
|
29
|
+
toolFailures: number;
|
|
30
|
+
turns: number;
|
|
31
|
+
}
|
|
32
|
+
export type RunFinalStatus = 'completed' | 'failed' | 'cancelled';
|
|
33
|
+
/** Generate a stable-enough run id: `run_<time36>_<hex>`. */
|
|
34
|
+
export declare function newRunId(now?: () => number): string;
|
|
35
|
+
/** Env flag for the run flight recorder (Frontier PHASE 5 rollout). */
|
|
36
|
+
export declare function runRecordEnabled(): boolean;
|
|
37
|
+
export declare class RunRecorder {
|
|
38
|
+
readonly runId: string;
|
|
39
|
+
readonly runDir: string;
|
|
40
|
+
private readonly opts;
|
|
41
|
+
private readonly now;
|
|
42
|
+
private chain;
|
|
43
|
+
private startedAt;
|
|
44
|
+
private started;
|
|
45
|
+
private finalized;
|
|
46
|
+
private readonly models;
|
|
47
|
+
private readonly counters;
|
|
48
|
+
constructor(options: RunRecorderOptions);
|
|
49
|
+
/** Create the run dir and write the initial manifest. Idempotent. */
|
|
50
|
+
start(): void;
|
|
51
|
+
/** Append one redacted event to trace.jsonl. */
|
|
52
|
+
record(event: Record<string, unknown>): void;
|
|
53
|
+
/** Append one redacted event to the per-agent stream. */
|
|
54
|
+
recordAgent(agentId: string, event: Record<string, unknown>): void;
|
|
55
|
+
/** Track which model served which role, for the final manifest. */
|
|
56
|
+
noteModel(role: string, model: string | undefined): void;
|
|
57
|
+
bumpModelCall(): void;
|
|
58
|
+
bumpToolCall(): void;
|
|
59
|
+
bumpToolFailure(): void;
|
|
60
|
+
bumpTurn(): void;
|
|
61
|
+
getMetrics(): RunMetricsFile;
|
|
62
|
+
/** Write final manifest + metrics.json. Idempotent. */
|
|
63
|
+
finalize(status: RunFinalStatus): void;
|
|
64
|
+
/** Await pending writes (tests / graceful shutdown). */
|
|
65
|
+
flush(): Promise<void>;
|
|
66
|
+
private buildManifest;
|
|
67
|
+
/**
|
|
68
|
+
* Serial best-effort write queue: preserves trace ordering and swallows
|
|
69
|
+
* IO errors (§102 — recorder failure must not block the run).
|
|
70
|
+
*/
|
|
71
|
+
private enqueue;
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=RunRecorder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RunRecorder.d.ts","sourceRoot":"","sources":["../../../src/runtime/recorder/RunRecorder.ts"],"names":[],"mappings":"AAkBA,MAAM,WAAW,kBAAkB;IACjC,uDAAuD;IACvD,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,CAAC,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,SAAS,GAAG,WAAW,GAAG,QAAQ,GAAG,WAAW,CAAC;IACzD,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC;AAED,yEAAyE;AACzE,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,cAAc,GAAG,WAAW,GAAG,QAAQ,GAAG,WAAW,CAAC;AAElE,6DAA6D;AAC7D,wBAAgB,QAAQ,CAAC,GAAG,GAAE,MAAM,MAAiB,GAAG,MAAM,CAE7D;AAED,uEAAuE;AACvE,wBAAgB,gBAAgB,IAAI,OAAO,CAG1C;AAOD,qBAAa,WAAW;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAExB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAqB;IAC1C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;IACnC,OAAO,CAAC,KAAK,CAAoC;IACjD,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAyB;IAChD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA8D;gBAE3E,OAAO,EAAE,kBAAkB;IAQvC,qEAAqE;IACrE,KAAK,IAAI,IAAI;IAWb,gDAAgD;IAChD,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAK5C,yDAAyD;IACzD,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAOlE,mEAAmE;IACnE,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI;IAIxD,aAAa,IAAI,IAAI;IAIrB,YAAY,IAAI,IAAI;IAIpB,eAAe,IAAI,IAAI;IAIvB,QAAQ,IAAI,IAAI;IAIhB,UAAU,IAAI,cAAc;IAO5B,uDAAuD;IACvD,QAAQ,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI;IAWtC,wDAAwD;IAClD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAI5B,OAAO,CAAC,aAAa;IAerB;;;OAGG;IACH,OAAO,CAAC,OAAO;CAKhB"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Run Flight Recorder (Frontier PHASE 5, §67-§71).
|
|
3
|
+
*
|
|
4
|
+
* Persists a per-run directory under `.zelari/runs/<run-id>/`:
|
|
5
|
+
*
|
|
6
|
+
* manifest.json run metadata (no secrets — payloads pass Redactor)
|
|
7
|
+
* trace.jsonl ordered runtime events
|
|
8
|
+
* agents/*.jsonl per-agent event streams
|
|
9
|
+
* metrics.json counters snapshot, written at finalize
|
|
10
|
+
*
|
|
11
|
+
* All IO is best-effort (§102): every write is enqueued on a serial chain
|
|
12
|
+
* whose errors are swallowed, so a recorder failure never blocks the run.
|
|
13
|
+
*/
|
|
14
|
+
import { appendFile, mkdir, writeFile } from 'node:fs/promises';
|
|
15
|
+
import { join } from 'node:path';
|
|
16
|
+
import { randomBytes } from 'node:crypto';
|
|
17
|
+
import { redactRuntimePayload } from './Redactor.js';
|
|
18
|
+
/** Generate a stable-enough run id: `run_<time36>_<hex>`. */
|
|
19
|
+
export function newRunId(now = Date.now) {
|
|
20
|
+
return `run_${now().toString(36)}_${randomBytes(4).toString('hex')}`;
|
|
21
|
+
}
|
|
22
|
+
/** Env flag for the run flight recorder (Frontier PHASE 5 rollout). */
|
|
23
|
+
export function runRecordEnabled() {
|
|
24
|
+
const raw = process.env.ZELARI_RUN_RECORD?.trim().toLowerCase();
|
|
25
|
+
return raw === '1' || raw === 'true' || raw === 'on';
|
|
26
|
+
}
|
|
27
|
+
function sanitizeAgentId(agentId) {
|
|
28
|
+
const safe = agentId.replace(/[^a-zA-Z0-9._-]/g, '-').slice(0, 64);
|
|
29
|
+
return safe.length > 0 ? safe : 'agent';
|
|
30
|
+
}
|
|
31
|
+
export class RunRecorder {
|
|
32
|
+
runId;
|
|
33
|
+
runDir;
|
|
34
|
+
opts;
|
|
35
|
+
now;
|
|
36
|
+
chain = Promise.resolve();
|
|
37
|
+
startedAt = 0;
|
|
38
|
+
started = false;
|
|
39
|
+
finalized = false;
|
|
40
|
+
models;
|
|
41
|
+
counters = { modelCalls: 0, toolCalls: 0, toolFailures: 0, turns: 0 };
|
|
42
|
+
constructor(options) {
|
|
43
|
+
this.opts = options;
|
|
44
|
+
this.now = options.now ?? Date.now;
|
|
45
|
+
this.runId = options.runId ?? newRunId(this.now);
|
|
46
|
+
this.runDir = join(options.runsDir, this.runId);
|
|
47
|
+
this.models = { ...(options.models ?? {}) };
|
|
48
|
+
}
|
|
49
|
+
/** Create the run dir and write the initial manifest. Idempotent. */
|
|
50
|
+
start() {
|
|
51
|
+
if (this.started)
|
|
52
|
+
return;
|
|
53
|
+
this.started = true;
|
|
54
|
+
this.startedAt = this.now();
|
|
55
|
+
this.enqueue(async () => {
|
|
56
|
+
await mkdir(this.runDir, { recursive: true });
|
|
57
|
+
await mkdir(join(this.runDir, 'agents'), { recursive: true });
|
|
58
|
+
await writeFile(join(this.runDir, 'manifest.json'), JSON.stringify(this.buildManifest('running'), null, 2));
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
/** Append one redacted event to trace.jsonl. */
|
|
62
|
+
record(event) {
|
|
63
|
+
if (!this.started)
|
|
64
|
+
this.start();
|
|
65
|
+
this.enqueue(() => appendFile(join(this.runDir, 'trace.jsonl'), `${JSON.stringify(redactRuntimePayload(event))}\n`));
|
|
66
|
+
}
|
|
67
|
+
/** Append one redacted event to the per-agent stream. */
|
|
68
|
+
recordAgent(agentId, event) {
|
|
69
|
+
if (!this.started)
|
|
70
|
+
this.start();
|
|
71
|
+
this.enqueue(() => appendFile(join(this.runDir, 'agents', `${sanitizeAgentId(agentId)}.jsonl`), `${JSON.stringify(redactRuntimePayload(event))}\n`));
|
|
72
|
+
}
|
|
73
|
+
/** Track which model served which role, for the final manifest. */
|
|
74
|
+
noteModel(role, model) {
|
|
75
|
+
if (role && model)
|
|
76
|
+
this.models[role] = model;
|
|
77
|
+
}
|
|
78
|
+
bumpModelCall() {
|
|
79
|
+
this.counters.modelCalls += 1;
|
|
80
|
+
}
|
|
81
|
+
bumpToolCall() {
|
|
82
|
+
this.counters.toolCalls += 1;
|
|
83
|
+
}
|
|
84
|
+
bumpToolFailure() {
|
|
85
|
+
this.counters.toolFailures += 1;
|
|
86
|
+
}
|
|
87
|
+
bumpTurn() {
|
|
88
|
+
this.counters.turns += 1;
|
|
89
|
+
}
|
|
90
|
+
getMetrics() {
|
|
91
|
+
return {
|
|
92
|
+
durationMs: this.finalized || this.startedAt > 0 ? Math.max(0, this.now() - this.startedAt) : 0,
|
|
93
|
+
...this.counters,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
/** Write final manifest + metrics.json. Idempotent. */
|
|
97
|
+
finalize(status) {
|
|
98
|
+
if (this.finalized)
|
|
99
|
+
return;
|
|
100
|
+
if (!this.started)
|
|
101
|
+
this.start();
|
|
102
|
+
this.finalized = true;
|
|
103
|
+
const endedAt = this.now();
|
|
104
|
+
this.enqueue(async () => {
|
|
105
|
+
await writeFile(join(this.runDir, 'manifest.json'), JSON.stringify(this.buildManifest(status, endedAt), null, 2));
|
|
106
|
+
await writeFile(join(this.runDir, 'metrics.json'), JSON.stringify(this.getMetrics(), null, 2));
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
/** Await pending writes (tests / graceful shutdown). */
|
|
110
|
+
async flush() {
|
|
111
|
+
await this.chain;
|
|
112
|
+
}
|
|
113
|
+
buildManifest(status, endedAt) {
|
|
114
|
+
return {
|
|
115
|
+
version: 1,
|
|
116
|
+
runId: this.runId,
|
|
117
|
+
sessionId: this.opts.sessionId,
|
|
118
|
+
mode: this.opts.mode ?? 'kraken',
|
|
119
|
+
phase: this.opts.phase ?? 'build',
|
|
120
|
+
startedAt: this.startedAt,
|
|
121
|
+
...(endedAt !== undefined ? { endedAt } : {}),
|
|
122
|
+
status,
|
|
123
|
+
cwd: this.opts.cwd ?? process.cwd(),
|
|
124
|
+
models: this.models,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Serial best-effort write queue: preserves trace ordering and swallows
|
|
129
|
+
* IO errors (§102 — recorder failure must not block the run).
|
|
130
|
+
*/
|
|
131
|
+
enqueue(write) {
|
|
132
|
+
this.chain = this.chain.then(write).catch(() => {
|
|
133
|
+
/* best-effort: drop failed write, keep the chain alive */
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
//# sourceMappingURL=RunRecorder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RunRecorder.js","sourceRoot":"","sources":["../../../src/runtime/recorder/RunRecorder.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/runtime/recorder/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,gBAAgB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/runtime/recorder/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,gBAAgB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recorderObserver.d.ts","sourceRoot":"","sources":["../../../src/runtime/recorder/recorderObserver.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,aAAa,EASd,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAmB/C,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,WAAW,GAAG,aAAa,CAoD3E"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bridge that turns observer events into RunRecorder writes
|
|
3
|
+
* (Frontier PHASE 5). Never intervenes: every hook returns CONTINUE.
|
|
4
|
+
* Model deltas are deliberately not traced (noise; §70 event list).
|
|
5
|
+
*/
|
|
6
|
+
import { CONTINUE } from '../observers/types.js';
|
|
7
|
+
function base(event) {
|
|
8
|
+
return {
|
|
9
|
+
id: event.id,
|
|
10
|
+
ts: event.ts,
|
|
11
|
+
turn: event.turn,
|
|
12
|
+
agentId: event.identity.agentId,
|
|
13
|
+
role: event.identity.role,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
export function createRecorderObserver(recorder) {
|
|
17
|
+
return {
|
|
18
|
+
onRunStart(event) {
|
|
19
|
+
recorder.noteModel(event.identity.role, event.identity.model);
|
|
20
|
+
recorder.start();
|
|
21
|
+
recorder.record({ type: 'run_start', ...base(event) });
|
|
22
|
+
return CONTINUE;
|
|
23
|
+
},
|
|
24
|
+
onModelAttempt(event) {
|
|
25
|
+
recorder.bumpModelCall();
|
|
26
|
+
recorder.record({ type: 'model_attempt', ...base(event) });
|
|
27
|
+
return CONTINUE;
|
|
28
|
+
},
|
|
29
|
+
onModelResponse(event) {
|
|
30
|
+
recorder.record({ type: 'model_response', ...base(event) });
|
|
31
|
+
return CONTINUE;
|
|
32
|
+
},
|
|
33
|
+
onToolCall(event) {
|
|
34
|
+
recorder.bumpToolCall();
|
|
35
|
+
recorder.record({ type: 'tool_call', ...base(event), toolCallId: event.toolCallId, tool: event.toolName });
|
|
36
|
+
return CONTINUE;
|
|
37
|
+
},
|
|
38
|
+
onToolResult(event) {
|
|
39
|
+
if (!event.ok)
|
|
40
|
+
recorder.bumpToolFailure();
|
|
41
|
+
const line = { type: 'tool_result', ...base(event), toolCallId: event.toolCallId, tool: event.toolName, ok: event.ok };
|
|
42
|
+
recorder.record(line);
|
|
43
|
+
recorder.recordAgent(event.identity.agentId, line);
|
|
44
|
+
return CONTINUE;
|
|
45
|
+
},
|
|
46
|
+
onTurnEnd(event) {
|
|
47
|
+
recorder.bumpTurn();
|
|
48
|
+
recorder.record({ type: 'turn_end', ...base(event) });
|
|
49
|
+
return CONTINUE;
|
|
50
|
+
},
|
|
51
|
+
onRunEnd(event) {
|
|
52
|
+
recorder.record({ type: 'run_end', ...base(event), reason: event.reason });
|
|
53
|
+
recorder.finalize(event.reason === 'completed' ? 'completed' : event.reason === 'cancelled' ? 'cancelled' : 'failed');
|
|
54
|
+
return CONTINUE;
|
|
55
|
+
},
|
|
56
|
+
onCancelled(event) {
|
|
57
|
+
recorder.record({ type: 'run_cancelled', ...base(event), reason: event.reason });
|
|
58
|
+
recorder.finalize('cancelled');
|
|
59
|
+
return CONTINUE;
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=recorderObserver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recorderObserver.js","sourceRoot":"","sources":["../../../src/runtime/recorder/recorderObserver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface RunRetentionOptions {
|
|
2
|
+
maxAgeDays?: number;
|
|
3
|
+
maxTotalBytes?: number;
|
|
4
|
+
now?: () => number;
|
|
5
|
+
}
|
|
6
|
+
export interface RetentionResult {
|
|
7
|
+
deleted: string[];
|
|
8
|
+
freedBytes: number;
|
|
9
|
+
kept: number;
|
|
10
|
+
}
|
|
11
|
+
export declare const DEFAULT_RUN_RETENTION_DAYS = 30;
|
|
12
|
+
export declare const DEFAULT_RUN_RETENTION_MAX_MB = 2048;
|
|
13
|
+
export declare function runRetentionFromEnv(): Required<Pick<RunRetentionOptions, 'maxAgeDays' | 'maxTotalBytes'>>;
|
|
14
|
+
export declare function enforceRunRetention(runsDir: string, options?: RunRetentionOptions): Promise<RetentionResult>;
|
|
15
|
+
//# sourceMappingURL=retention.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retention.d.ts","sourceRoot":"","sources":["../../../src/runtime/recorder/retention.ts"],"names":[],"mappings":"AAcA,MAAM,WAAW,mBAAmB;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,eAAO,MAAM,0BAA0B,KAAK,CAAC;AAC7C,eAAO,MAAM,4BAA4B,OAAO,CAAC;AAEjD,wBAAgB,mBAAmB,IAAI,QAAQ,CAAC,IAAI,CAAC,mBAAmB,EAAE,YAAY,GAAG,eAAe,CAAC,CAAC,CAQzG;AAiCD,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,eAAe,CAAC,CA6D1B"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Run retention (Frontier PHASE 5, §77): keep `.zelari/runs` bounded.
|
|
3
|
+
*
|
|
4
|
+
* - never deletes a run whose manifest is missing `endedAt`/final status
|
|
5
|
+
* (active or unknown runs are conservatively kept)
|
|
6
|
+
* - deletes completed runs older than `maxAgeDays`
|
|
7
|
+
* - then deletes oldest completed runs until total size fits `maxTotalBytes`
|
|
8
|
+
*
|
|
9
|
+
* Env: ZELARI_RUN_RETENTION_DAYS (default 30),
|
|
10
|
+
* ZELARI_RUN_RETENTION_MAX_MB (default 2048).
|
|
11
|
+
*/
|
|
12
|
+
import { readdir, readFile, rm, stat } from 'node:fs/promises';
|
|
13
|
+
import { join } from 'node:path';
|
|
14
|
+
export const DEFAULT_RUN_RETENTION_DAYS = 30;
|
|
15
|
+
export const DEFAULT_RUN_RETENTION_MAX_MB = 2048;
|
|
16
|
+
export function runRetentionFromEnv() {
|
|
17
|
+
const parseDays = Number(process.env.ZELARI_RUN_RETENTION_DAYS);
|
|
18
|
+
const parseMb = Number(process.env.ZELARI_RUN_RETENTION_MAX_MB);
|
|
19
|
+
return {
|
|
20
|
+
maxAgeDays: Number.isFinite(parseDays) && parseDays > 0 ? parseDays : DEFAULT_RUN_RETENTION_DAYS,
|
|
21
|
+
maxTotalBytes: Number.isFinite(parseMb) && parseMb > 0 ? Math.round(parseMb * 1024 * 1024) : DEFAULT_RUN_RETENTION_MAX_MB * 1024 * 1024,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
async function dirSize(path) {
|
|
25
|
+
let total = 0;
|
|
26
|
+
let entries;
|
|
27
|
+
try {
|
|
28
|
+
entries = await readdir(path, { withFileTypes: true });
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return 0;
|
|
32
|
+
}
|
|
33
|
+
for (const entry of entries) {
|
|
34
|
+
const child = join(path, entry.name);
|
|
35
|
+
if (entry.isDirectory())
|
|
36
|
+
total += await dirSize(child);
|
|
37
|
+
else {
|
|
38
|
+
try {
|
|
39
|
+
total += (await stat(child)).size;
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
/* vanished mid-walk */
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return total;
|
|
47
|
+
}
|
|
48
|
+
export async function enforceRunRetention(runsDir, options = {}) {
|
|
49
|
+
const now = options.now ?? Date.now;
|
|
50
|
+
const maxAgeDays = options.maxAgeDays ?? DEFAULT_RUN_RETENTION_DAYS;
|
|
51
|
+
const maxTotalBytes = options.maxTotalBytes ?? DEFAULT_RUN_RETENTION_MAX_MB * 1024 * 1024;
|
|
52
|
+
const result = { deleted: [], freedBytes: 0, kept: 0 };
|
|
53
|
+
let entries;
|
|
54
|
+
try {
|
|
55
|
+
entries = await readdir(runsDir, { withFileTypes: true });
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return result; // no runs dir yet → nothing to do
|
|
59
|
+
}
|
|
60
|
+
const infos = [];
|
|
61
|
+
for (const entry of entries) {
|
|
62
|
+
if (!entry.isDirectory())
|
|
63
|
+
continue;
|
|
64
|
+
const path = join(runsDir, entry.name);
|
|
65
|
+
let startedAt = 0;
|
|
66
|
+
let endedAt;
|
|
67
|
+
let completed = false;
|
|
68
|
+
try {
|
|
69
|
+
const manifest = JSON.parse(await readFile(join(path, 'manifest.json'), 'utf8'));
|
|
70
|
+
startedAt = manifest.startedAt ?? 0;
|
|
71
|
+
endedAt = manifest.endedAt;
|
|
72
|
+
// §77: only finalized runs are deletable; 'running' / unknown stay.
|
|
73
|
+
completed = Boolean(endedAt) && manifest.status !== 'running';
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
completed = false; // unreadable manifest → conservative keep
|
|
77
|
+
}
|
|
78
|
+
infos.push({ name: entry.name, path, startedAt, endedAt, completed, bytes: await dirSize(path) });
|
|
79
|
+
}
|
|
80
|
+
const remove = async (info) => {
|
|
81
|
+
await rm(info.path, { recursive: true, force: true });
|
|
82
|
+
result.deleted.push(info.name);
|
|
83
|
+
result.freedBytes += info.bytes;
|
|
84
|
+
};
|
|
85
|
+
// Pass 1: age-based eviction (oldest first).
|
|
86
|
+
const ageCutoffMs = maxAgeDays * 24 * 60 * 60 * 1000;
|
|
87
|
+
const expired = infos
|
|
88
|
+
.filter((info) => info.completed && info.startedAt > 0 && now() - info.startedAt > ageCutoffMs)
|
|
89
|
+
.sort((a, b) => a.startedAt - b.startedAt);
|
|
90
|
+
for (const info of expired)
|
|
91
|
+
await remove(info);
|
|
92
|
+
// Pass 2: size-budget eviction over what is left (oldest completed first).
|
|
93
|
+
const survivors = infos.filter((info) => !result.deleted.includes(info.name));
|
|
94
|
+
let totalBytes = survivors.reduce((sum, info) => sum + info.bytes, 0);
|
|
95
|
+
const byOldest = survivors.filter((info) => info.completed).sort((a, b) => a.startedAt - b.startedAt);
|
|
96
|
+
for (const info of byOldest) {
|
|
97
|
+
if (totalBytes <= maxTotalBytes)
|
|
98
|
+
break;
|
|
99
|
+
totalBytes -= info.bytes;
|
|
100
|
+
await remove(info);
|
|
101
|
+
}
|
|
102
|
+
result.kept = infos.filter((info) => !result.deleted.includes(info.name)).length;
|
|
103
|
+
return result;
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=retention.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retention.js","sourceRoot":"","sources":["../../../src/runtime/recorder/retention.ts"],"names":[],"mappings":"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"}
|
|
@@ -29,9 +29,9 @@ export declare const TaskCriterionSchema: z.ZodObject<{
|
|
|
29
29
|
required: z.ZodBoolean;
|
|
30
30
|
verificationHint: z.ZodOptional<z.ZodObject<{
|
|
31
31
|
kind: z.ZodEnum<{
|
|
32
|
+
tool: "tool";
|
|
32
33
|
command: "command";
|
|
33
34
|
manual: "manual";
|
|
34
|
-
tool: "tool";
|
|
35
35
|
semantic: "semantic";
|
|
36
36
|
}>;
|
|
37
37
|
value: z.ZodOptional<z.ZodString>;
|
|
@@ -60,9 +60,9 @@ export declare const TaskContractSchema: z.ZodObject<{
|
|
|
60
60
|
required: z.ZodBoolean;
|
|
61
61
|
verificationHint: z.ZodOptional<z.ZodObject<{
|
|
62
62
|
kind: z.ZodEnum<{
|
|
63
|
+
tool: "tool";
|
|
63
64
|
command: "command";
|
|
64
65
|
manual: "manual";
|
|
65
|
-
tool: "tool";
|
|
66
66
|
semantic: "semantic";
|
|
67
67
|
}>;
|
|
68
68
|
value: z.ZodOptional<z.ZodString>;
|
package/dist/shared/events.d.ts
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* @see docs/plans/2026-06-28-zelari-code.md (Task 11.1)
|
|
11
11
|
*/
|
|
12
12
|
/** Discriminator for every {@link BrainEvent} variant. */
|
|
13
|
-
export type BrainEventType = 'agent_start' | 'agent_end' | 'message_start' | 'message_end' | 'message_delta' | 'thinking_delta' | 'tool_execution_start' | 'tool_execution_update' | 'tool_execution_end' | 'queue_update' | 'session_compacted' | 'error' | 'member_cost' | 'council_mode' | 'task_update' | 'task_snapshot' | 'context_metrics' | 'kraken_progress' | 'kraken_metrics';
|
|
13
|
+
export type BrainEventType = 'agent_start' | 'agent_end' | 'agent_spawned' | 'agent_status' | 'agent_tool' | 'agent_ended' | 'message_start' | 'message_end' | 'message_delta' | 'thinking_delta' | 'tool_execution_start' | 'tool_execution_update' | 'tool_execution_end' | 'queue_update' | 'session_compacted' | 'error' | 'member_cost' | 'council_mode' | 'task_update' | 'task_snapshot' | 'context_metrics' | 'kraken_progress' | 'kraken_metrics';
|
|
14
14
|
/** Fields shared by every event. */
|
|
15
15
|
export interface BrainEventBase {
|
|
16
16
|
/** Type discriminator. */
|
|
@@ -51,6 +51,44 @@ export interface BrainAgentEndEvent extends BrainEventBase {
|
|
|
51
51
|
memberId?: string;
|
|
52
52
|
memberName?: string;
|
|
53
53
|
}
|
|
54
|
+
/** Role of a Kraken tentacle as spawned via the `task` tool. */
|
|
55
|
+
export type TentacleAgentRole = 'explore' | 'general' | 'verify' | 'fix' | 'planner';
|
|
56
|
+
/** A Kraken tentacle has been spawned by the lead (via the `task` tool). */
|
|
57
|
+
export interface BrainAgentSpawnedEvent extends BrainEventBase {
|
|
58
|
+
type: 'agent_spawned';
|
|
59
|
+
agentId: string;
|
|
60
|
+
role: TentacleAgentRole;
|
|
61
|
+
title?: string;
|
|
62
|
+
model?: string;
|
|
63
|
+
provider?: string;
|
|
64
|
+
scope?: string[];
|
|
65
|
+
worktree?: string;
|
|
66
|
+
}
|
|
67
|
+
/** Coarse lifecycle status of a tentacle, for live activity UIs. */
|
|
68
|
+
export interface BrainAgentStatusEvent extends BrainEventBase {
|
|
69
|
+
type: 'agent_status';
|
|
70
|
+
agentId: string;
|
|
71
|
+
status: 'queued' | 'running' | 'waiting' | 'completed' | 'failed' | 'cancelled';
|
|
72
|
+
message?: string;
|
|
73
|
+
}
|
|
74
|
+
/** A tool execution inside a tentacle (start/end, with duration on end). */
|
|
75
|
+
export interface BrainAgentToolEvent extends BrainEventBase {
|
|
76
|
+
type: 'agent_tool';
|
|
77
|
+
agentId: string;
|
|
78
|
+
toolCallId: string;
|
|
79
|
+
tool: string;
|
|
80
|
+
status: 'started' | 'completed' | 'failed';
|
|
81
|
+
summary?: string;
|
|
82
|
+
durationMs?: number;
|
|
83
|
+
}
|
|
84
|
+
/** A tentacle finished (ok, error, cancelled or timeout). */
|
|
85
|
+
export interface BrainAgentEndedEvent extends BrainEventBase {
|
|
86
|
+
type: 'agent_ended';
|
|
87
|
+
agentId: string;
|
|
88
|
+
reason: string;
|
|
89
|
+
ok: boolean;
|
|
90
|
+
durationMs: number;
|
|
91
|
+
}
|
|
54
92
|
/**
|
|
55
93
|
* An assistant message has begun streaming.
|
|
56
94
|
*
|
|
@@ -346,7 +384,7 @@ export interface BrainKrakenMetricsEvent extends BrainEventBase {
|
|
|
346
384
|
metrics: KrakenMetricsPayload;
|
|
347
385
|
}
|
|
348
386
|
/** Discriminated union of every event the brain can emit. */
|
|
349
|
-
export type BrainEvent = BrainAgentStartEvent | BrainAgentEndEvent | BrainMessageStartEvent | BrainMessageDeltaEvent | BrainMessageEndEvent | BrainThinkingDeltaEvent | BrainToolExecutionStartEvent | BrainToolExecutionUpdateEvent | BrainToolExecutionEndEvent | BrainQueueUpdateEvent | BrainSessionCompactedEvent | BrainErrorEvent | BrainMemberCostEvent | BrainCouncilModeEvent | BrainTaskUpdateEvent | BrainTaskSnapshotEvent | BrainContextMetricsEvent | BrainKrakenProgressEvent | BrainKrakenMetricsEvent;
|
|
387
|
+
export type BrainEvent = BrainAgentStartEvent | BrainAgentEndEvent | BrainAgentSpawnedEvent | BrainAgentStatusEvent | BrainAgentToolEvent | BrainAgentEndedEvent | BrainMessageStartEvent | BrainMessageDeltaEvent | BrainMessageEndEvent | BrainThinkingDeltaEvent | BrainToolExecutionStartEvent | BrainToolExecutionUpdateEvent | BrainToolExecutionEndEvent | BrainQueueUpdateEvent | BrainSessionCompactedEvent | BrainErrorEvent | BrainMemberCostEvent | BrainCouncilModeEvent | BrainTaskUpdateEvent | BrainTaskSnapshotEvent | BrainContextMetricsEvent | BrainKrakenProgressEvent | BrainKrakenMetricsEvent;
|
|
350
388
|
/**
|
|
351
389
|
* Map from a {@link BrainEventType} discriminator to its concrete event type.
|
|
352
390
|
* Lets callers say `BrainEventOf<'agent_start'>` instead of repeating the
|