// src/layer/adapters/types.ts
//
// Contract for tool-result adapters used by the (Wave-3+) tool-result
// compression pipeline.
//
// Load-bearing rules every adapter implementation MUST honor:
//   Rule A — frozen bytes: once a toolCallId has been compressed and sent
//            upstream, every subsequent request MUST emit byte-identical
//            content for that toolCallId. (Wave 3 enforces via a per-session
//            Map; adapter authors only need to keep compress() deterministic
//            so the cached bytes stay reproducible if needed.)
//   Rule B — latest-turn only: adapters run ONLY on tool_results in the
//            LATEST user message (Wave 3 uses provider.extractLastTurnToolResults).
//            Prior turns are never touched.
//   Determinism: NO Date.now(), NO Math.random(), NO iteration over Maps/Sets
//            whose insertion order is not controlled. Same input bytes MUST
//            yield byte-identical output. Wave 5 ships a probe that enforces.
//
// Sigil namespace (ASCII-colon prefixes, deliberately disjoint from the
// §§-prefixed sigil family rewritten by OutputRewriteLayer):
//   :bash: :mcp: :git: :json: :grep: :find: :ls:
// The Wave-1 sigil-namespace probe asserts that OutputRewriteLayer leaves
// these prefixes untouched. If any new adapter introduces a new ASCII-colon
// sigil, extend that probe before shipping.

import type { ToolResult } from "../../provider/canonical.ts";

export interface CompressedResult {
  /** What the model sees in the rewritten tool_result content. */
  preview: string;
  /** Sections to insert into the per-session KbStore (keyed by toolCallId). */
  kbEntries: { section: string; content: string }[];
  /** raw.length - preview.length, for SavingEvent telemetry. */
  bytesSaved: number;
  /** Optional structured metadata for reporting. Must be deterministic. */
  meta?: Record<string, unknown>;
  /** Optional sigil if the adapter emits one (e.g. read-dedupe). */
  sigil?: string;
}

export interface ToolResultAdapter {
  readonly id: string;
  /** Conservative match — false positive = corrupted model view. */
  match(r: ToolResult): boolean;
  /** Deterministic compression. Same input bytes -> same output bytes. */
  compress(r: ToolResult): CompressedResult;
}

export interface AdapterDispatchResult {
  readonly adapterId: string;
  readonly compressed: CompressedResult;
  readonly raw: string;
}
