/** * Pure-function completion detector for the global poller. * * Determines whether a dispatched background task session has reached * a final state by inspecting the session status and message state. * * This module has NO side effects and NO SDK calls — it operates * exclusively on the structured snapshots provided by the caller. * * Detection strategy (aligned with oh-my-openagent): * - Primary signal: session status (idle = potentially done, busy/retry = working) * - Secondary signal: has assistant output + no tool parts on the last message * (any tool part — settled or in-flight — means the model issued tool calls * and the agentic loop must continue) * - Non-terminal finish detection: ANY finish reason matching /tool/i * ("tool_use" from Pi, "toolUse", "tool-calls", etc.) means the model * expects tool execution → not ready. Other finish values ("end_turn" for * Claude, "stop" for OpenAI, etc.) are NOT relied upon for terminality. */ import type { CompletionSignal, SessionMessageSnapshot, TaskEventState } from "../types.ts"; /** * Finish reasons that definitively indicate the model is still working * and will produce more output (tool execution pending). * * Verified vocabulary across adapters: "tool-calls" (opencode-style), * "tool_use" (Pi adapter — `stopReason` copied verbatim to `info.finish`), * and "toolUse" (alternate Pi casing). The detector matches these via * /tool/i to stay robust to further variants. */ export type NonTerminalFinishReason = "tool-calls" | "tool_use" | "toolUse"; /** * True if any tool part is in-flight (state `pending` or `running`). * * The last assistant message carrying an in-flight tool means the model has * produced a tool call that is still executing — the session is NOT idle and * must not be reported complete (or error-latched) until the tool settles. */ export declare function hasInflightToolPart(parts: Array<{ type: string; state?: string | { status?: string; }; }>): boolean; /** * True if any tool part is present on the message — settled OR in-flight. * * Mirrors the Pi adapter's `_isFinalTurn` rule: any tool part means this turn * issued tool calls, and the agentic loop is expected to continue with a new * turn for the model's follow-up. Declaring the task complete while a tool * result still sits on the last assistant message can latch a truncated * (tool-echo) result as final — the "settled-tool completion" bug. */ export declare function hasToolPart(parts: Array<{ type: string; state?: string | { status?: string; }; }>): boolean; /** * Evaluate whether a background task session has reached completion. * * The decision follows a fixed priority order: * 1. Tool-execution-in-progress guard — any tool part (settled or in-flight) * on the last assistant message → not ready. Evaluated first so a * transient error or a stale idle/terminal status never latches a terminal * result while the model's tool call is still unresolved (a settled tool * part likewise means the agentic loop must continue with a new turn). * 2. Session actively processing → not ready * 3. Session in terminal status (interrupted) → completed * 4. No assistant output → not ready * 5. Error detection on last assistant message * 6. finish matching /tool/i ("tool-calls" / "tool_use" / "toolUse") → not ready * 7. Stability gating (MIN_STABILITY_POLLS consecutive idle polls) * * @param messages Chronological message snapshots from the sub-agent session * @param sessionStatus Current session status (type field: "idle", "busy", "retry", etc.) * @param pollState Per-task polling metadata (stable idle count, etc.) * @returns A structured completion signal */ export declare function detectCompletion(messages: SessionMessageSnapshot[], sessionStatus: { type: string; } | undefined, pollState: TaskEventState, skipStabilityGating?: boolean): CompletionSignal; /** * Normalize an opaque error value into a human-readable message string. * * Handles the common shapes returned by the SDK's error types * (strings, Error instances, objects with `.message` or `.error` fields, * and arbitrary JSON-able values). * * @param error The raw error from `SessionMessageSnapshot.info.error` * @returns A non-empty error message string */ export declare function extractAssistantError(error: unknown): string; //# sourceMappingURL=completion-detector.d.ts.map