import { type SessionManager } from "@caupulican/pi-agent-core/session"; import type { AgentMessage, AgentRunawayStopInfo } from "@caupulican/pi-agent-core/types"; import type { AssistantMessage } from "@caupulican/pi-ai"; import { type GoalContinuationLoopOptions, type GoalContinuationLoopResult, type GoalContinuationOnceOptions, type GoalContinuationOnceResult, type PromptOptions } from "../agent-session-contracts.ts"; import type { LaneRecord } from "../autonomy/lane-tracker.ts"; import type { BackgroundToolTaskRef } from "../background-tool-task-controller.ts"; import type { TaskRuntimeProjection } from "../orchestration/task-runtime.ts"; import { type GoalStateRevision } from "./goal-lifecycle.ts"; import { type GoalRuntimeSnapshot, type GoalRuntimeSnapshotSettings } from "./goal-runtime-snapshot.ts"; import { type GoalState } from "./goal-state.ts"; import { type ExplicitGoalStartAuthority } from "./natural-language-goal.ts"; export interface GoalSessionControllerDeps { getSessionManager(): SessionManager; getModelProvider(): string | undefined; getLaneRecords(): readonly LaneRecord[]; getTaskRuntimeSnapshot(): TaskRuntimeProjection | undefined; getBackgroundToolTasks(): readonly BackgroundToolTaskRef[]; synchronizeGoalState(state: GoalState): void; scheduleGoalAutoContinueFromIdle(): void; prompt(text: string, options?: PromptOptions): Promise; emitWarning(message: string): void; } export type ChatGoalAdmission = { status: "not_explicit"; } | { status: "started"; state: GoalState; } | { status: "unfinished_goal_exists"; state: GoalState; }; declare const goalExecutionLeaseMarker: unique symbol; /** Identity-bound attribution for one goal-owned foreground execution. */ export interface GoalExecutionLease { readonly goalId?: string; readonly [goalExecutionLeaseMarker]: true; } /** * Owns durable goal state, exact continuation accounting, and the raw continuation loop. The * AgentSession facade supplies process collaborators but no longer implements goal lifecycle rules. */ export declare class GoalSessionController { private readonly deps; private readonly loop; private executionLease; private startAuthority; private readonly queuedOwnerChatGoals; private queuedOwnerChatExecutionLease; constructor(deps: GoalSessionControllerDeps); private getContinuationTurnOutcome; saveState(state: GoalState, expected?: GoalStateRevision): string; clearState(state: GoalState, now: string): string; getState(): GoalState | undefined; /** * A bounded runaway/provider-turn guard stops one autonomous run, not the owner's durable intent. * Resume that narrow class immediately or during restoration while preserving deliberate blocks, * terminal tool failures, pauses, and quota/budget stops. */ resumeSystemBlockedGoal(now?: string): string | undefined; /** * Promote high-confidence natural-language persistence into the same durable state written by the * goal tool. This is intentionally narrower than task detection: ordinary work never starts a * goal, and an unfinished goal is never replaced implicitly. */ admitOwnerChatGoal(text: string, messages: readonly { role: string; content?: unknown; }[]): ChatGoalAdmission; startOwnerChatGoal(text: string, messages: readonly { role: string; content?: unknown; }[]): string | undefined; queueOwnerChatGoal(message: AgentMessage, text: string, authority: ExplicitGoalStartAuthority): void; activateQueuedOwnerChatGoal(message: AgentMessage, messages: readonly { role: string; content?: unknown; }[]): void; endQueuedOwnerChatGoalExecution(): void; admitExplicitChatGoal(text: string, now?: string, priorUserText?: string): ChatGoalAdmission; /** Attribute turn/wall-clock telemetry without inferring progress (public/manual accounting seam). */ recordContinuationTelemetry(pass: { turns: number; wallClockMs: number; }): void; /** Attribute one host-driven pass and derive stall state from the authoritative revision. */ private recordContinuationPass; private persistContinuationPass; /** Begin one foreground execution whose provider usage belongs to the specified active goal. */ beginExecution(goalId: string | undefined, options?: { adoptNewGoal?: boolean; provisionalTokenBudget?: number; }): GoalExecutionLease | undefined; endExecution(lease: GoalExecutionLease | undefined): void; /** Goal identity authoritatively owned by the current foreground execution, if one was adopted. */ getExecutionGoalId(): string | undefined; /** Charge one observed assistant response exactly once, including routed responses buffered from persistence. */ recordExecutionUsage(message: AssistantMessage): void; private chargeExecutionUsage; markProtocolFailureBlocked(errorMessage: string): boolean; setStartAuthority(authority: ExplicitGoalStartAuthority | undefined): void; authorizeStartFromTool(_input: { tokenBudget?: number; }): number | null; /** * True once the currently held execution lease's goal has crossed into `budget_limited` — set * synchronously by `chargeExecutionUsage` as soon as a just-charged response crosses the ceiling. * Wired to the agent's `shouldStopAfterTurn` hook so a mid-turn budget stop ends the loop * gracefully BEFORE the next provider request is even planned, instead of only being caught by * `admitProviderRequest`'s throw — which still exists as the backstop for a fresh turn or an * external admission starting against an already budget_limited goal, but would otherwise also * fire for a request this same lease was already mid-flight for, surfacing a synthetic error * message where a clean turn end belongs. */ hasExecutionLeaseCrossedBudgetLimit(): boolean; /** Reserve only remaining output capacity; actual provider usage is charged on response. */ admitProviderRequest(): number | undefined; private resolveExecutionState; private flushPendingExecutionUsage; markToolUnavailable(): void; recoverFromHarnessGuard(info: AgentRunawayStopInfo): boolean; markTerminalToolFailureBlocked(toolName: string): boolean; getRuntimeSnapshot(settings: GoalRuntimeSnapshotSettings): GoalRuntimeSnapshot; continueOnce(options: GoalContinuationOnceOptions): Promise; continueLoop(options: GoalContinuationLoopOptions): Promise; restoreAfterResume(): boolean; private recordContinuationFailure; private markBudgetLimited; private stopActiveGoal; } export {}; //# sourceMappingURL=goal-session-controller.d.ts.map