import type { AgentEndEvent, BeforeAgentStartEvent, ContextEvent, ExtensionAPI, ExtensionContext, ExtensionEvent, ExtensionHandler, InputEvent, InputEventResult, SessionBeforeCompactEvent, SessionCompactEvent, SessionShutdownEvent, SessionStartEvent, SessionTreeEvent, TurnEndEvent, TurnStartEvent, } from "@earendil-works/pi-coding-agent"; import type { GoalRuntimeState } from "./goal-runtime-state.js"; import type { GoalStateController } from "./goal-state-controller.js"; import type { AssistantErrorMessage } from "./recovery.js"; export type ContextEventResult = { messages?: ContextEvent["messages"] }; export type MessageStartEvent = Extract; export type ToolExecutionEndEvent = Extract; export interface GoalRuntimeEventHandlers { onInput: ExtensionHandler; onContext: ExtensionHandler; onSessionStart: ExtensionHandler; onSessionTree: ExtensionHandler; onBeforeAgentStart: ExtensionHandler; onMessageStart: ExtensionHandler; onTurnStart: ExtensionHandler; onToolExecutionEnd: ExtensionHandler; onTurnEnd: ExtensionHandler; onAgentEnd: ExtensionHandler; onSessionBeforeCompact: ExtensionHandler; onSessionCompact: ExtensionHandler; onSessionShutdown: ExtensionHandler; } export interface GoalRuntimeStatusPort { refreshUi: (ctx: ExtensionContext) => void; stopStatusRefresh: () => void; } export interface GoalRuntimeContinuationPort { bindPassthroughContinuationInputToTurn: (turnIndex: number) => void; clearContinuationState: () => void; clearContinuationStateFor: (goalId: string) => void; clearContinuationTimer: () => void; clearPassthroughContinuationInput: () => void; continuationGoalIdFromRuntimePrompt: (prompt: string) => string | null; markContinuationQueued: (goalId: string) => void; maybeContinue: (ctx: ExtensionContext) => void; maybeContinueAfterCurrentEvent: (ctx: ExtensionContext) => void; notePassthroughContinuationInput: (input: string) => void; } export interface GoalAccountingPort { accountProgress: ( ctx: ExtensionContext, includeActiveElapsed: boolean, completedTurnTokens: number, forceFlush?: boolean, ) => void; beginAccounting: () => void; } export interface RecoveryRuntimePort { finishSuccessfulAssistantTurn: ( message: TurnEndEvent["message"], ctx: ExtensionContext, options: { continueGoal: boolean }, ) => void; handlePersistentAssistantError: (message: AssistantErrorMessage, ctx: ExtensionContext) => void; handleSilentContextOverflow: (ctx: ExtensionContext) => void; onSessionCompact: () => void; onUserInput: () => void; } export interface StaleQueuedWorkEffectContext { status: GoalRuntimeStatusPort; clearActiveAccounting: () => void; } export interface GoalRuntimeInputContextHandlerContext extends StaleQueuedWorkEffectContext { runtimeState: Pick; stateController: Pick< GoalStateController, "getGoal" | "isCurrentActiveGoalId" | "persistHostOverflowUserReset" >; continuation: GoalRuntimeContinuationPort; recoveryRuntime: Pick; resetErrorRecovery: () => void; } export interface GoalRuntimeTurnHandlerContext extends StaleQueuedWorkEffectContext { runtimeState: Pick; stateController: Pick< GoalStateController, "beginOverflowRecovery" | "flushGoalPersistence" | "maybeFlushRuntimePersistence" | "pauseForAbort" >; continuation: Pick; goalAccounting: GoalAccountingPort; recoveryRuntime: Pick; } export interface GoalRuntimeAgentHandlerContext extends StaleQueuedWorkEffectContext { runtimeState: Pick; stateController: Pick; continuation: Pick< GoalRuntimeContinuationPort, "clearPassthroughContinuationInput" | "maybeContinue" >; goalAccounting: Pick; recoveryRuntime: Pick< RecoveryRuntimePort, "handlePersistentAssistantError" | "handleSilentContextOverflow" >; resetErrorRecovery: () => void; } export interface GoalRuntimeSessionHandlerContext extends StaleQueuedWorkEffectContext { pi: Pick; runtimeState: Pick; stateController: Pick< GoalStateController, "applyGoalTransition" | "flushGoalPersistence" | "getGoal" | "reloadFromSession" | "resumePausedGoal" >; continuation: Pick< GoalRuntimeContinuationPort, "clearContinuationTimer" | "clearPassthroughContinuationInput" | "maybeContinue" | "maybeContinueAfterCurrentEvent" >; goalAccounting: GoalAccountingPort; recoveryRuntime: Pick; resetErrorRecovery: () => void; } export interface GoalRuntimeOverflowRecoveryContext { stateController: Pick; recoveryRuntime: Pick< RecoveryRuntimePort, "handlePersistentAssistantError" | "handleSilentContextOverflow" >; } export interface GoalRuntimeEventContext { pi: ExtensionAPI; runtimeState: GoalRuntimeState; stateController: GoalStateController; continuation: GoalRuntimeContinuationPort; goalAccounting: GoalAccountingPort; recoveryRuntime: RecoveryRuntimePort; status: GoalRuntimeStatusPort; clearActiveAccounting: () => void; resetErrorRecovery: () => void; } export type QueuedGoalWorkMessage = { role: string; customType?: string; details?: unknown; content?: unknown; }; export type QueuedGoalWorkMessageIdResolver = (message: QueuedGoalWorkMessage) => string | null;