SPB Git

Repository Public

transcript.ts 2.3 KB 63 lines typescript

1/**2 * The provider-native transcript of a run, rebuilt on every claim.3 *4 * Replay rule (CONTRACT §5): the transcript is a pure function of journaled step RESULTS. The logic5 * re-runs from the top; each `ctx.step` returns its recorded result and the same appends are made in6 * the same order, so nothing else is state. Every value appended here comes from a step result (i.e.7 * went through the kernel's canonical JSON round-trip), from the run contract, or from constants.8 *9 * The transcript itself is never written to a step request (it would make the journal quadratic). A10 * model_call step carries a rolling digest instead: h0 = sha256(canonical(first entries)),11 * h(n) = sha256(h(n-1) + canonical(entries appended since)). The kernel's request-hash check therefore12 * still detects any divergence of the rebuilt transcript.13 */14import { canonicalJson } from '@aos/kernel';15import type { ProviderAdapter } from '@aos/providers';16import type { ToolResult } from '@aos/shared';17import { sha256Hex } from '@aos/tools';1819export class Transcript {20  private items: unknown[];21  private digest = '';2223  constructor(24    private readonly adapter: ProviderAdapter,25    firstUserMessage: string,26  ) {27    this.items = [];28    this.set(adapter.initTranscript(firstUserMessage));29  }3031  private set(next: unknown[]): void {32    const added = next.slice(this.items.length);33    this.items = next;34    if (added.length > 0) this.digest = sha256Hex(this.digest + canonicalJson(added));35  }3637  /** Native entries, to hand to `adapter.call`. Treat as read-only. */38  get entries(): unknown[] {39    return this.items;40  }41  get sha256(): string {42    return this.digest;43  }44  get length(): number {45    return this.items.length;46  }4748  assistant(native: unknown): void {49    this.set(this.adapter.appendAssistant(this.items, native));50  }51  toolResults(results: ToolResult[]): void {52    if (results.length > 0) this.set(this.adapter.appendToolResults(this.items, results));53  }54  /** Steering message from the owner. */55  owner(text: string): void {56    this.set(this.adapter.appendUser(this.items, `Message from the owner:\n${text}`));57  }58  /** Operator-authority note from the runtime (budget, context, stall, nudges). */59  note(text: string): void {60    this.set(this.adapter.appendOperatorNote(this.items, text));61  }62}63
Files main
Menu

Theme