import type { BaseMessage } from '@langchain/core/messages'; /** * The non-message parts of a `wrapModelCall` request that also shape a turn: the tool * definitions, the system prompt, and the model params. Captured alongside the message * history so the `/debug` panel can show the full picture of what was sent to the model. * * SECURITY: these are assembled from an explicit allowlist at the capture site * (see {@link extractDebugRequestExtras}); the raw model instance (which can carry an * `apiKey`) is never passed through here. */ export interface DebugRequestExtras { /** The composed system prompt string sent to the model for this call. */ systemPrompt?: string; /** The tool definitions made available for this call (name + description + JSON schema). */ tools?: DebugToolDef[]; /** Scalar model params (model id, temperature, …) — a key-free allowlist. */ modelParams?: Record; /** The tool-choice configuration for this call, if any. */ toolChoice?: unknown; } /** A single tool's debug-renderable definition. */ export interface DebugToolDef { name: string; description?: string; /** The tool's JSON-schema parameters, when resolvable. */ schema?: unknown; } /** * GS2-56 — the always-on snapshot of the LAST model request, kept on * {@link @gaunt-sloth/core!core/GthAbstractAgent.GthAbstractAgent | GthAbstractAgent} independent of any * {@link DebugCapture} sink. It is the SAME data the sink reports (the as-sent, post-summarization * `request.messages` plus the {@link DebugRequestExtras}), captured unconditionally at each model * call so `/debug-dump` can render the full model input even when the TUI `/debug` panel was never * opened and on non-TUI surfaces. Reuses {@link DebugRequestExtras} rather than forking a parallel * capture shape; `WriteDebugDumpInput.modelRequest` is this same type, so the caller threads * `agent.lastModelRequest` straight through with no reshaping. */ export interface LastModelRequest { /** The request extras (system prompt, tool defs with schema, model params, tool-choice). */ extras?: DebugRequestExtras; /** The exact messages sent to the model for the last call (post-summarization / middleware). */ messages?: BaseMessage[]; } /** * Debug-capture sink for the TUI's `/debug` panel. * * A {@link DebugCapture} is an OPT-IN callback the TUI sets on a live agent after `init` * (on the shared {@link @gaunt-sloth/core!core/GthAbstractAgent.GthAbstractAgent | GthAbstractAgent} base, so * every backend supports it). When present, the agent's `wrapModelCall` * middleware reports, per model call: * * - `request` — `request.messages: BaseMessage[]`, the real history sent to the model at * call time (post-summarization / post-middleware), plus the {@link DebugRequestExtras} * (tools, system prompt, model params) that also shape the turn. This is exactly what the * model saw. * - `response` — the resolved `AIMessage` returned by the handler, captured as a whole * (resolved message, not per-chunk frames; keeps the streaming core untouched). * * The sink is read lazily inside the middleware (per call), so when no TUI debug panel is * attached the middleware is a transparent pass-through and the normal path pays nothing. */ export interface DebugCapture { /** The full message history sent to the model for this call, plus the request extras. */ onRequest?(messages: BaseMessage[], extras?: DebugRequestExtras): void; /** The resolved model response for this call (an `AIMessage`). */ onResponse?(response: unknown): void; } /** * Assemble the non-message request parts ({@link DebugRequestExtras}) for the `/debug` * panel from a `wrapModelCall` request, defensively and key-free. Never throws (the caller * already guards, but a debug sink must never break a run) and never dumps the raw model. * Lives in core, beside the capture type itself, so every backend feeds the panel the same shape. */ export declare function extractDebugRequestExtras(request: unknown): DebugRequestExtras | undefined;