import type { AgentSessionEvent } from "@earendil-works/pi-coding-agent"; import type { SubagentBackend, SubagentProgressNode, SubagentTelemetry, SubagentToolDetails, SubagentProfileName, SubagentUsage } from "../types.js"; export declare const MAX_ACTIVITY_LINES = 2; export declare const MAX_ACTIVITY_LINE_CHARS = 240; export declare const MAX_PROGRESS_METADATA_CHARS = 160; export declare const MAX_PROGRESS_RESULT_CHARS = 2000; export declare const MAX_PROGRESS_ERROR_CHARS = 1000; export declare const MAX_PROGRESS_UPDATE_JSON_CHARS = 16384; /** Cap for model-visible terminal envelope text, so a runaway child output cannot bloat the root context. */ export declare const MAX_MODEL_VISIBLE_TEXT_CHARS = 32000; export declare const PROGRESS_UPDATE_INTERVAL_MS = 250; export declare const PROGRESS_HEARTBEAT_INTERVAL_MS = 1000; export declare function boundedProgressText(text: string, maxChars: number): string; export declare function subagentDisplayDetails(source: SubagentToolDetails, includeDisplayText?: boolean): SubagentToolDetails; export declare function textResult(text: string, details: SubagentToolDetails, usage?: SubagentUsage): { content: [{ type: "text"; text: string; }]; details: SubagentToolDetails; usage?: SubagentUsage; }; export type SubagentToolResult = ReturnType; export declare function createProgressNode(label: string, profile: SubagentProfileName, status?: SubagentProgressNode["status"], backend?: SubagentBackend): SubagentProgressNode; export declare function updateProgressFromEvent(progress: SubagentProgressNode, event: AgentSessionEvent): void; export interface ProgressEmitterOptions { label: string; profile: SubagentProfileName; backend?: SubagentBackend; enabled: boolean; onProgress: ((result: SubagentToolResult) => void) | undefined; } export interface ProgressEmitter { readonly progress: SubagentProgressNode | undefined; addActivity(line: string): void; replaceLatestActivity(line: string): void; setUsage(usage: SubagentUsage, telemetry: SubagentTelemetry): void; emit(): void; emitSoon(): void; startHeartbeat(): void; stop(): void; } /** * Keeps backend progress throttling and heartbeat cadence consistent across Pi, * Codex, and Claude. Queue state remains owned by the caller because timeout and * concurrency accounting begin only after a slot is acquired. */ export declare function createProgressEmitter(options: ProgressEmitterOptions): ProgressEmitter; export declare function extractFinalAssistantText(messages: readonly unknown[]): string; /** * Detect a terminal model failure on the final assistant turn. * * pi-ai's stream contract does NOT throw or reject for request/model/runtime * failures (rate limits, quota exhaustion, provider 4xx/5xx, etc.). It encodes * them as a final AssistantMessage with stopReason "error" (or "aborted") and an * errorMessage, so `session.prompt()` resolves normally even when the turn never * produced a real completion. A caller that treats "prompt() resolved" as * success would mark such a run "done" with empty output and zero tokens. * * Returns the failure of the LAST assistant turn (the terminal one), or * undefined when that turn ended normally ("stop"/"length"/"toolUse"). */ export declare function getFinalAssistantFailure(messages: readonly unknown[]): { stopReason: "error" | "aborted"; errorMessage?: string; } | undefined; export declare function getSubagentUsage(session: { getSessionStats: () => { tokens: { input: number; output: number; cacheRead: number; cacheWrite: number; }; cost: number; }; messages?: readonly unknown[]; }): SubagentUsage;