@vincemakes/kiso-runtime 0.1.38 → 0.2.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/agent.d.ts CHANGED
@@ -62,6 +62,7 @@ export interface AgentDefinition {
62
62
  * loop's policy chain. */
63
63
  readonly extensions?: readonly KisoExtension[];
64
64
  }
65
+ /** @deprecated the canonical name is `Agent` (root export, 1.1.0); this alias is removed in the next major. */
65
66
  export declare class AgentRuntime {
66
67
  #private;
67
68
  constructor(definition: AgentDefinition);
package/dist/agent.js CHANGED
@@ -13,6 +13,7 @@
13
13
  */
14
14
  import { EventLog, ToolRegistry } from "@vincemakes/kiso-core";
15
15
  import { AgentSession } from "./session.js";
16
+ /** @deprecated the canonical name is `Agent` (root export, 1.1.0); this alias is removed in the next major. */
16
17
  export class AgentRuntime {
17
18
  #definition;
18
19
  #registry;
@@ -54,6 +55,7 @@ export class AgentRuntime {
54
55
  const adapter = await this.#adapterPromise;
55
56
  const config = {
56
57
  model: this.#definition.model,
58
+ ...(this.#definition.provider !== undefined ? { provider: this.#definition.provider } : {}),
57
59
  ...(this.#definition.systemPrompt !== undefined ? { systemPrompt: this.#definition.systemPrompt } : {}),
58
60
  registry: this.#registry,
59
61
  ...(this.#definition.permissionPolicy !== undefined || this.#definition.hooks !== undefined
package/dist/index.d.ts CHANGED
@@ -1,11 +1,32 @@
1
- export * from "./agent.js";
2
- export * from "./session.js";
3
- export * from "./run.js";
4
- export * from "./recovery.js";
5
- export * from "./compose.js";
6
- export * from "./summarize.js";
7
- export * from "./store.js";
8
- export * from "./lock-adapter.js";
9
- export * from "./ledger.js";
10
- export * from "./extensions.js";
11
- export * from "./trust.js";
1
+ /**
2
+ * The SDK surface — the curated root manifest (S1, 2026-08-12).
3
+ *
4
+ * Every name here is a review-approved contract: adding or removing one
5
+ * WITHOUT the ritual (the review's sign-off + a public-surface.json
6
+ * refresh) turns the public-surface gate red. See docs/sdk.md for the
7
+ * contract, the aliases, and what deliberately lives behind the
8
+ * first-party door.
9
+ *
10
+ * What is NOT here is not the SDK. The recovery / compose / summarize /
11
+ * lock-adapter machinery and buildAdapter live behind "./internal"
12
+ * (unstable, first-party only — see internal.ts).
13
+ *
14
+ * Canonical names: Agent = AgentRuntime, Session = AgentSession. The old
15
+ * names are deprecated aliases, removed in the next major (additive,
16
+ * ADR-0051 Amendment 1 — release rounds move the cli minor).
17
+ */
18
+ export { AgentRuntime, AgentRuntime as Agent, createAgent } from "./agent.js";
19
+ export type { AgentDefinition, PermissionPolicy, PermissionRule } from "./agent.js";
20
+ export { AgentSession, AgentSession as Session } from "./session.js";
21
+ export { PoisonedSessionError, ResumeBlockedError } from "./session.js";
22
+ export type { ApprovalRequest, CompactInfo, SessionConfig, SummarizeResult } from "./session.js";
23
+ export { Run } from "./run.js";
24
+ export { SessionStore, StaleWriterError, StoreCorruptionError } from "./store.js";
25
+ export type { Event, SessionMeta, StoreRecord } from "./store.js";
26
+ export { disposeExtensions, loadExtensions, loadProjectExtensions } from "./extensions.js";
27
+ export type { KisoExtension } from "./extensions.js";
28
+ export { executionForCallId, executionLedger } from "./ledger.js";
29
+ export type { ExecutionRecord, ExecutionStatus } from "./ledger.js";
30
+ export { kisoHome, projectArtifacts, recordTrust, trustFor } from "./trust.js";
31
+ export type { ProjectArtifact, ProjectArtifacts, TrustDecision, TrustRecord } from "./trust.js";
32
+ export { canonicalizeUsage } from "./usage/canonical.js";
package/dist/index.js CHANGED
@@ -1,11 +1,41 @@
1
- export * from "./agent.js";
2
- export * from "./session.js";
3
- export * from "./run.js";
4
- export * from "./recovery.js";
5
- export * from "./compose.js";
6
- export * from "./summarize.js";
7
- export * from "./store.js";
8
- export * from "./lock-adapter.js";
9
- export * from "./ledger.js";
10
- export * from "./extensions.js";
11
- export * from "./trust.js";
1
+ /**
2
+ * The SDK surface — the curated root manifest (S1, 2026-08-12).
3
+ *
4
+ * Every name here is a review-approved contract: adding or removing one
5
+ * WITHOUT the ritual (the review's sign-off + a public-surface.json
6
+ * refresh) turns the public-surface gate red. See docs/sdk.md for the
7
+ * contract, the aliases, and what deliberately lives behind the
8
+ * first-party door.
9
+ *
10
+ * What is NOT here is not the SDK. The recovery / compose / summarize /
11
+ * lock-adapter machinery and buildAdapter live behind "./internal"
12
+ * (unstable, first-party only — see internal.ts).
13
+ *
14
+ * Canonical names: Agent = AgentRuntime, Session = AgentSession. The old
15
+ * names are deprecated aliases, removed in the next major (additive,
16
+ * ADR-0051 Amendment 1 — release rounds move the cli minor).
17
+ */
18
+ // agent
19
+ export { AgentRuntime, AgentRuntime as Agent, createAgent } from "./agent.js";
20
+ // session
21
+ export { AgentSession, AgentSession as Session } from "./session.js";
22
+ export { PoisonedSessionError, ResumeBlockedError } from "./session.js";
23
+ // run
24
+ export { Run } from "./run.js";
25
+ // store
26
+ export { SessionStore, StaleWriterError, StoreCorruptionError } from "./store.js";
27
+ // extensions
28
+ export { disposeExtensions, loadExtensions, loadProjectExtensions } from "./extensions.js";
29
+ // ledger
30
+ export { executionForCallId, executionLedger } from "./ledger.js";
31
+ // trust
32
+ export { kisoHome, projectArtifacts, recordTrust, trustFor } from "./trust.js";
33
+ // usage — the canonical accounting schema (E2/1.3.0, R4b-1 ruling:
34
+ // additive minor, one function; the signature is frozen the moment this
35
+ // line lands — changing it is a MAJOR ritual). R5b-④a set the final
36
+ // shape at freeze time: the trailing `table?: PricingTable` injection
37
+ // slot defaults to the builtin v1 table, so the R5a-1-commercial table
38
+ // rides day one without ever widening this signature. Raw stays
39
+ // provider observation; canonicalizeUsage derives at the accounting
40
+ // boundary (R4 Case B — the frozen usage union does not move).
41
+ export { canonicalizeUsage } from "./usage/canonical.js";
@@ -0,0 +1,25 @@
1
+ /**
2
+ * The FIRST-PARTY door — NOT part of the public SDK contract (S1,
3
+ * 2026-08-12, adjudicated).
4
+ *
5
+ * Unstable: anything here can move or vanish in any release without a
6
+ * major bump. External consumers must import the curated root
7
+ * (index.ts); this file exists for the in-repo consumers (apps/cli,
8
+ * extensions, tests) that need machinery the SDK deliberately does not
9
+ * expose — the recovery / compose / summarize / lock-adapter internals
10
+ * and buildAdapter.
11
+ *
12
+ * This is today's pre-S1 index.ts verbatim: removing the door would be a
13
+ * breaking change for the first-party consumers mid-migration.
14
+ */
15
+ export * from "./agent.js";
16
+ export * from "./session.js";
17
+ export * from "./run.js";
18
+ export * from "./recovery.js";
19
+ export * from "./compose.js";
20
+ export * from "./summarize.js";
21
+ export * from "./store.js";
22
+ export * from "./lock-adapter.js";
23
+ export * from "./ledger.js";
24
+ export * from "./extensions.js";
25
+ export * from "./trust.js";
@@ -0,0 +1,25 @@
1
+ /**
2
+ * The FIRST-PARTY door — NOT part of the public SDK contract (S1,
3
+ * 2026-08-12, adjudicated).
4
+ *
5
+ * Unstable: anything here can move or vanish in any release without a
6
+ * major bump. External consumers must import the curated root
7
+ * (index.ts); this file exists for the in-repo consumers (apps/cli,
8
+ * extensions, tests) that need machinery the SDK deliberately does not
9
+ * expose — the recovery / compose / summarize / lock-adapter internals
10
+ * and buildAdapter.
11
+ *
12
+ * This is today's pre-S1 index.ts verbatim: removing the door would be a
13
+ * breaking change for the first-party consumers mid-migration.
14
+ */
15
+ export * from "./agent.js";
16
+ export * from "./session.js";
17
+ export * from "./run.js";
18
+ export * from "./recovery.js";
19
+ export * from "./compose.js";
20
+ export * from "./summarize.js";
21
+ export * from "./store.js";
22
+ export * from "./lock-adapter.js";
23
+ export * from "./ledger.js";
24
+ export * from "./extensions.js";
25
+ export * from "./trust.js";
@@ -61,6 +61,7 @@
61
61
  * pauses plus SIGSTOP/SIGCONT, and locate the freeze points via
62
62
  * ready-marker files (ADR-0050 §test affordances).
63
63
  */
64
+ import { execFileSync } from "node:child_process";
64
65
  import { closeSync, fsyncSync, linkSync, openSync, readFileSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
65
66
  import { randomUUID } from "node:crypto";
66
67
  import { join } from "node:path";
@@ -78,14 +79,58 @@ export class LockUnavailableError extends Error {
78
79
  this.name = "LockUnavailableError";
79
80
  }
80
81
  }
82
+ /**
83
+ * ADR-0050 Amendment 1 (Finding R-I-1): the liveness probe is
84
+ * state-aware. A dead holder can linger in the process table after a
85
+ * kill — the exiting state (STAT E on macOS: the kill landing while a
86
+ * pty syscall is blocked, the dead session's terminal left open) or an
87
+ * un-reaped zombie (STAT Z). POSIX reports BOTH alive to kill(pid, 0)
88
+ * (they exist until reaped), so the takeover refused a holder that can
89
+ * never execute another session write. Both states are probed and
90
+ * judged DEAD. A probe failure (unreadable state) maintains the
91
+ * pre-amendment behavior — alive, the fail-safe refusal (prefer a false
92
+ * refusal over a double-write). Live-process semantics and the PID-reuse
93
+ * rules do not move: a live foreign writer is still refused.
94
+ *
95
+ * ADR-0050 Amendment 2 (Finding R-I-p-3): the state letters are matched
96
+ * ANYWHERE in the state string, not as the first character. The
97
+ * exit-path linger's ps output is "?E" — the first character is the
98
+ * no-controlling-terminal marker "?", with the E sitting AFTER it — so
99
+ * first-character matching judged the finding's own documented shape
100
+ * alive. The ps state alphabet (macOS + Linux) has no flag letters
101
+ * "E"/"Z": an occurrence anywhere is the process-state code, and the
102
+ * holder is dead.
103
+ */
81
104
  function isAlive(pid) {
82
105
  try {
83
106
  process.kill(pid, 0);
84
- return true;
85
107
  }
86
108
  catch (err) {
87
109
  return err.code === "EPERM";
88
110
  }
111
+ const state = processState(pid);
112
+ // A null state (probe failure) keeps the pre-amendment behavior —
113
+ // judged alive, the fail-safe refusal.
114
+ return state === null || (!state.includes("E") && !state.includes("Z"));
115
+ }
116
+ /**
117
+ * The process state via `ps -o state= -p <pid>` (macOS/Linux) — the
118
+ * whole state string (a multi-char string like "Ss+" or "?E" is a
119
+ * combined flag set; the E/Z process-state codes may sit after the "?"
120
+ * no-tty marker or other flag letters, so the matching in isAlive scans
121
+ * the whole string). An empty or unreadable state — the process
122
+ * vanished between the kill and the probe, or ps itself failed —
123
+ * returns null; isAlive's fail-safe branch then judges the holder alive
124
+ * (the pre-amendment behavior).
125
+ */
126
+ function processState(pid) {
127
+ try {
128
+ const state = execFileSync("ps", ["-o", "state=", "-p", String(pid)], { encoding: "utf8" }).trim();
129
+ return state.length > 0 ? state : null;
130
+ }
131
+ catch {
132
+ return null;
133
+ }
89
134
  }
90
135
  /**
91
136
  * Read a lock file's holder identity (round 4 formats, unchanged — the
package/dist/run.js CHANGED
@@ -8,6 +8,8 @@ import { ABORTED, MergedSignal, abortable, openRunId } from "./recovery.js";
8
8
  import { deriveRecoveryPlan, invocationSeqOf } from "./recovery-plan.js";
9
9
  import { composeApprovalChain, composeSystemPrompt, composeToolTable, microcompactFor } from "./compose.js";
10
10
  import { truncationGuard } from "./truncation-guard.js";
11
+ import { RequestTracer, traceGuard } from "./trace/guard.js";
12
+ import { runtimeVersion } from "./trace/writer.js";
11
13
  import { ResumeBlockedError } from "./session.js";
12
14
  /**
13
15
  * A single turn. Async-iterable, so `for await (const ev of session.run(x))`
@@ -47,6 +49,7 @@ export class Run {
47
49
  // The WHOLE body is one try/finally: a consumer that abandons the
48
50
  // run at ANY yield (even the user_input one) must release the
49
51
  // session's single-run slot and its approval resolvers.
52
+ let tracer = null;
50
53
  try {
51
54
  // round 4: health is re-checked when the iterator ACTUALLY starts —
52
55
  // a run constructed before the session was poisoned must fail
@@ -54,6 +57,20 @@ export class Run {
54
57
  this.#session.ensureHealthy();
55
58
  this.#session.beginRun(this);
56
59
  const log = this.#session.log;
60
+ // E1 (1.2.0): the request tracer — the observation ledger. It
61
+ // sits at the adapter boundary; the model-visible byte stream is
62
+ // untouched (I6, trace-bytes.test.ts). Soft-fail: a degraded
63
+ // writer costs one stderr line and the run goes on.
64
+ tracer = new RequestTracer({
65
+ root: this.#store.root,
66
+ sessionId: this.#session.id,
67
+ runId: this.runId,
68
+ provider: this.#config.provider ?? "adapter",
69
+ model: this.#config.model,
70
+ adapterVersion: runtimeVersion(),
71
+ log: log.all,
72
+ });
73
+ tracer.init();
57
74
  const signal = this.#externalSignal ? new MergedSignal(this.#abort.signal, this.#externalSignal) : this.#abort.signal;
58
75
  // E2: the session's own microcompact wins; otherwise the FIRST
59
76
  // extension providing a compaction config supplies it.
@@ -75,7 +92,7 @@ export class Run {
75
92
  const loopConfig = () => ({
76
93
  // 0.1.40 (R-C item 3): the truncation guard gates the model
77
94
  // stream — a truncated turn's tool batch never executes.
78
- adapter: truncationGuard(this.#adapter),
95
+ adapter: traceGuard(tracer, truncationGuard(this.#adapter)), // tracer assigned above, before loopConfig
79
96
  model: this.#config.model,
80
97
  sessionId: this.#session.id, // P3: tools see their session (ToolContext.sessionId)
81
98
  ...(systemPrompt !== undefined ? { systemPrompt } : {}),
@@ -230,6 +247,9 @@ export class Run {
230
247
  for (const executionId of this.#uncertaintyIds) {
231
248
  this.#session.dropUncertaintyResolver(executionId);
232
249
  }
250
+ // E1: the run's ledger story — the run_end lands synchronously
251
+ // (a killed run leaves no run_end, and the next init marks it).
252
+ tracer?.finishRun();
233
253
  this.#session.endRun(this);
234
254
  }
235
255
  }
package/dist/session.d.ts CHANGED
@@ -71,6 +71,7 @@ export interface CompactInfo {
71
71
  /** The covered content's estimated tokens (the chars/4 proxy). */
72
72
  readonly tokens: number;
73
73
  }
74
+ /** @deprecated the canonical name is `Session` (root export, 1.1.0); this alias is removed in the next major. */
74
75
  export declare class AgentSession {
75
76
  #private;
76
77
  readonly id: string;
@@ -97,6 +98,11 @@ export declare class AgentSession {
97
98
  * turns (dispatch's /model), never mid-run.
98
99
  */
99
100
  setAdapter(adapter: Adapter): void;
101
+ /** E2: the adapter identity ("anthropic" | "openai-compat") — the route
102
+ * key the canonical consumer (CLI usage, the trace block) keys on. The
103
+ * per-run tracer reads the SAME #config.provider; one source, one
104
+ * route — the CLI and the trace can never disagree. */
105
+ get provider(): "anthropic" | "openai-compat" | undefined;
100
106
  /** Run one user turn. Iterate to consume; `run.abort()` cancels. */
101
107
  run(input: string, options?: {
102
108
  signal?: AbortSignalLike;
@@ -178,6 +184,9 @@ export declare class AgentSession {
178
184
  }
179
185
  export interface SessionConfig {
180
186
  readonly model: string;
187
+ /** E1: the adapter identity ("anthropic" | "openai-compat") — trace
188
+ * provenance, additive (S1 surface untouched: type-only, optional). */
189
+ readonly provider?: "anthropic" | "openai-compat";
181
190
  readonly systemPrompt?: string;
182
191
  readonly tools?: readonly Tool<any>[];
183
192
  readonly registry: import("@vincemakes/kiso-core").ToolRegistry;
package/dist/session.js CHANGED
@@ -54,6 +54,7 @@ export class ResumeBlockedError extends Error {
54
54
  this.uncertain = uncertain;
55
55
  }
56
56
  }
57
+ /** @deprecated the canonical name is `Session` (root export, 1.1.0); this alias is removed in the next major. */
57
58
  export class AgentSession {
58
59
  id;
59
60
  log;
@@ -154,6 +155,13 @@ export class AgentSession {
154
155
  setAdapter(adapter) {
155
156
  this.#adapter = adapter;
156
157
  }
158
+ /** E2: the adapter identity ("anthropic" | "openai-compat") — the route
159
+ * key the canonical consumer (CLI usage, the trace block) keys on. The
160
+ * per-run tracer reads the SAME #config.provider; one source, one
161
+ * route — the CLI and the trace can never disagree. */
162
+ get provider() {
163
+ return this.#config.provider;
164
+ }
157
165
  /** Run one user turn. Iterate to consume; `run.abort()` cancels. */
158
166
  run(input, options) {
159
167
  this.ensureHealthy();
@@ -0,0 +1,35 @@
1
+ /**
2
+ * E1 (1.2.0) — slice 4, the cache-break derivation (proposal §4, ruling
3
+ * R4b: per-segment hashes + prefix fingerprint; the BREAK COUNT is an
4
+ * analysis-side derivation, never a recorded field).
5
+ *
6
+ * The cacheable prefix is every segment that is NOT the current turn —
7
+ * freshness "fresh" is the boundary (manifest.ts). `cacheableHashes`
8
+ * pairs the manifest segments 1:1 with the per-segment hashes and
9
+ * drops the fresh tail, so the fingerprint and the break derivation
10
+ * share one boundary by construction: a current-turn change alone
11
+ * never moves the fingerprint and never counts a break.
12
+ *
13
+ * `prefixBreak` compares two adjacent requests' cacheable prefixes:
14
+ * the first differing segment is the break, at its (0-based) depth;
15
+ * a prefix that merely GREW (a new turn joined) breaks at the old
16
+ * length. Unchanged prefixes → null (0 breaks). This is what
17
+ * bench/trace-report.mjs and the bench render per-request (slice 5).
18
+ */
19
+ import type { TraceSegment } from "./record.js";
20
+ /** The cacheable-prefix hashes: segments[i] ↔ hashes[i], dropping every
21
+ * freshness "fresh" segment (the current turn). */
22
+ export declare function cacheableHashes(segments: readonly TraceSegment[], hashes: readonly string[]): string[];
23
+ export interface PrefixBreak {
24
+ /** 0-based segment index within the cacheable prefix where the
25
+ * prefix first diverges (depth 0 = the system prompt). */
26
+ readonly depth: number;
27
+ }
28
+ /** R4b: compare two adjacent requests' cacheable prefixes. null = the
29
+ * prefix is unchanged (0 breaks). A prefix that grew breaks at the old
30
+ * length — the new segment is where caching can no longer attach. */
31
+ export declare function prefixBreak(prev: readonly string[], next: readonly string[]): PrefixBreak | null;
32
+ /** Per-request breaks across a run's request sequence: request k's
33
+ * break is relative to request k−1; the first request has no
34
+ * predecessor (null). */
35
+ export declare function deriveBreaks(requests: readonly (readonly string[])[]): (PrefixBreak | null)[];
@@ -0,0 +1,51 @@
1
+ /**
2
+ * E1 (1.2.0) — slice 4, the cache-break derivation (proposal §4, ruling
3
+ * R4b: per-segment hashes + prefix fingerprint; the BREAK COUNT is an
4
+ * analysis-side derivation, never a recorded field).
5
+ *
6
+ * The cacheable prefix is every segment that is NOT the current turn —
7
+ * freshness "fresh" is the boundary (manifest.ts). `cacheableHashes`
8
+ * pairs the manifest segments 1:1 with the per-segment hashes and
9
+ * drops the fresh tail, so the fingerprint and the break derivation
10
+ * share one boundary by construction: a current-turn change alone
11
+ * never moves the fingerprint and never counts a break.
12
+ *
13
+ * `prefixBreak` compares two adjacent requests' cacheable prefixes:
14
+ * the first differing segment is the break, at its (0-based) depth;
15
+ * a prefix that merely GREW (a new turn joined) breaks at the old
16
+ * length. Unchanged prefixes → null (0 breaks). This is what
17
+ * bench/trace-report.mjs and the bench render per-request (slice 5).
18
+ */
19
+ /** The cacheable-prefix hashes: segments[i] ↔ hashes[i], dropping every
20
+ * freshness "fresh" segment (the current turn). */
21
+ export function cacheableHashes(segments, hashes) {
22
+ const out = [];
23
+ for (let i = 0; i < segments.length; i++) {
24
+ if (segments[i].freshness !== "fresh")
25
+ out.push(hashes[i]);
26
+ }
27
+ return out;
28
+ }
29
+ /** R4b: compare two adjacent requests' cacheable prefixes. null = the
30
+ * prefix is unchanged (0 breaks). A prefix that grew breaks at the old
31
+ * length — the new segment is where caching can no longer attach. */
32
+ export function prefixBreak(prev, next) {
33
+ const shared = Math.min(prev.length, next.length);
34
+ for (let i = 0; i < shared; i++) {
35
+ if (prev[i] !== next[i])
36
+ return { depth: i };
37
+ }
38
+ if (prev.length !== next.length)
39
+ return { depth: shared };
40
+ return null;
41
+ }
42
+ /** Per-request breaks across a run's request sequence: request k's
43
+ * break is relative to request k−1; the first request has no
44
+ * predecessor (null). */
45
+ export function deriveBreaks(requests) {
46
+ const out = [];
47
+ for (let k = 0; k < requests.length; k++) {
48
+ out.push(k === 0 ? null : prefixBreak(requests[k - 1], requests[k]));
49
+ }
50
+ return out;
51
+ }
@@ -0,0 +1,46 @@
1
+ /**
2
+ * E1 (1.2.0) — slice 3, the request tracer (the guard).
3
+ *
4
+ * One TraceRecord per adapter call, settled when the stream ends. The
5
+ * guard lives AT the adapter boundary (run.ts wires
6
+ * truncationGuard(traceGuard(tracer, adapter))): the kernel, the log,
7
+ * and the model-visible byte stream are untouched (I6 — pinned by
8
+ * trace-bytes.test.ts). retryAttempt counts prior calls in this run
9
+ * with an identical contextHash — the loop re-streams the SAME messages
10
+ * array on retry (loop.ts), so an identical hash is exactly "same
11
+ * request, retried" (§1.4).
12
+ *
13
+ * Soft-fail: any failure in trace assembly (never expected — hashes and
14
+ * the manifest cannot throw today) marks the request ABSENT rather than
15
+ * breaking the stream; the writer's own degradation covers I/O.
16
+ *
17
+ * Usage is provider-raw, never normalized (E2's job): openai-compat
18
+ * reports input TOTAL (fresh = input − cacheRead); anthropic's
19
+ * input_tokens is ALREADY fresh-only (the trace records it as-is).
20
+ * A request that settles with NO usage data records the quartet as
21
+ * zeros with cacheWrite null — "0 = unknown", documented at record.ts;
22
+ * the honest nullable quartet is a schema bump, deferred.
23
+ */
24
+ import type { Adapter, AdapterEvent, Event, StreamOptions } from "@vincemakes/kiso-core";
25
+ export interface RequestTracerDeps {
26
+ root: string;
27
+ sessionId: string;
28
+ runId: string;
29
+ provider: string;
30
+ model: string;
31
+ /** The adapter contract's implementation version (the runtime's own),
32
+ * resolved once at tracer init; null on failure (soft-fail). */
33
+ adapterVersion?: string | null;
34
+ /** The session log — the manifest's seqRange pointers derive from it. */
35
+ log: readonly Event[];
36
+ }
37
+ export declare class RequestTracer {
38
+ #private;
39
+ constructor(deps: RequestTracerDeps);
40
+ init(): void;
41
+ wrap(options: StreamOptions, upstream: AsyncIterable<AdapterEvent>): AsyncIterable<AdapterEvent>;
42
+ /** Clean-settle marking for the whole run. */
43
+ finishRun(): void;
44
+ }
45
+ /** Wrap the adapter so every stream() call settles a trace record. */
46
+ export declare function traceGuard(tracer: RequestTracer, adapter: Adapter): Adapter;