/** * The cheap-model side of job widgets: one toolless request to the `widget` * role (aliasing `smol`) with a forced `respond` call carrying the spec * schema, fed the job's brief and redacted output samples. */ import { type AgentTelemetryConfig } from "@oh-my-pi/pi-agent-core"; import type { Api, AssistantMessage, Model } from "@oh-my-pi/pi-ai"; import type { ModelRegistry } from "../config/model-registry.js"; import type { Settings } from "../config/settings.js"; import type { CostGateApi } from "../session/cost-gate.js"; import type { JobWidgetSourceSample } from "./runtime.js"; import { type JobWidgetSpec } from "./spec.js"; import type { JobWidgetBrief } from "./types.js"; /** What the author is asked to write a spec for. */ export interface JobWidgetAuthorRequest { jobId: string; brief: JobWidgetBrief; /** Per source: first and last lines, most active first; raw (the author redacts). */ sources: readonly JobWidgetSourceSample[]; /** Re-authoring: the spec in place and why it is being replaced (`no rule matched the last 200 lines`). */ previous?: { spec: JobWidgetSpec; reason: string; }; /** Retry: the rejected answer and what was wrong with it. */ rejected?: { answer: string; errors: string[]; }; } /** * Writes one candidate spec (unvalidated; the registry validates and retries * once). Resolves `undefined` when no model can write specs at all, which * stops further requests for the job. */ export type JobWidgetAuthor = (request: JobWidgetAuthorRequest, signal: AbortSignal) => Promise; /** * Text bound for the author model with secrets removed: the session's secret * obfuscator when it has secrets, then the built-in credential shapes * (`[GitHubToken redacted]`), which apply even with secret handling off. */ export declare function redactWidgetSample(text: string, obfuscate?: (text: string) => string): string; /** Template context of `job-widget-user.md`. */ interface PromptSource { id: string; label: string; size: string; lines: number; omitted: number; head: string[]; tail: string[]; } /** * Sample lines for the prompt: each line redacted and cut at 300 chars, the * first lines then the last per source, most active source first, ≤ 12 KB in * total with every source getting a fair share of what is left. The head and * the tail each keep at most three lines of one shape (a progress line * repeating with new numbers), so a busy source shows its distinct lines * rather than one line many times. Lines that would open or close the * prompt's code fence are left out. */ export declare function buildPromptSources(sources: readonly JobWidgetSourceSample[], redact: (text: string) => string): PromptSource[]; /** The `job-widget-user.md` prompt for a request. */ export declare function renderJobWidgetPrompt(request: JobWidgetAuthorRequest, redact: (text: string) => string): string; export interface ModelJobWidgetAuthorOptions { settings: Settings; modelRegistry: ModelRegistry; /** The root session id, for session-sticky credentials and telemetry. */ sessionId: () => string | undefined; telemetry?: () => AgentTelemetryConfig | undefined; /** The session's secret obfuscation, when secret handling is on. */ obfuscate?: () => ((text: string) => string) | undefined; /** Each completed request's assistant message, for usage accounting (purpose `job-widget`). */ onUsage?: (message: AssistantMessage) => void; /** The session tree's current cost gate: refuses the request at the cap and adds its cost. */ costGate?: () => CostGateApi | undefined; } /** * The `widget` role's model with a usable credential: the role (configured, * or resolved like `smol`), then the built-in `smol` defaults. Job captions * use it too. */ export declare function resolveWidgetModel(settings: Settings, registry: ModelRegistry, sessionId: string | undefined, signal: AbortSignal): Promise | undefined>; /** A {@link JobWidgetAuthor} backed by the `widget` model role. */ export declare function createModelJobWidgetAuthor(options: ModelJobWidgetAuthorOptions): JobWidgetAuthor; export {};