import type { PluginInput } from "@opencode-ai/plugin" import type { RalphLoopState } from "./types" import { log } from "../../shared/logger" import { HOOK_NAME } from "./constants" import { buildContinuationPrompt } from "./continuation-prompt-builder" import { injectContinuationPrompt } from "./continuation-prompt-injector" import { createIterationSession, selectSessionInTui } from "./session-reset-strategy" type ContinuationOptions = { directory: string apiTimeoutMs: number previousSessionID: string loopState: { setSessionID: (sessionID: string) => RalphLoopState | null } } export type ContinuationResult = | { status: "dispatched" } | { status: "session_creation_rejected" } | { status: "dispatch_rejected"; error: unknown } export async function continueIteration( ctx: PluginInput, state: RalphLoopState, options: ContinuationOptions, ): Promise { const strategy = state.strategy ?? "continue" const continuationPrompt = buildContinuationPrompt(state) if (strategy === "reset") { const newSessionID = await createIterationSession( ctx, options.previousSessionID, options.directory, ) if (!newSessionID) { return { status: "session_creation_rejected" } } try { const promptResult = await injectContinuationPrompt(ctx, { sessionID: newSessionID, inheritFromSessionID: options.previousSessionID, prompt: continuationPrompt, directory: options.directory, apiTimeoutMs: options.apiTimeoutMs, }) if (promptResult.status === "rejected") { return { status: "dispatch_rejected", error: promptResult.error } } } catch (error: unknown) { return { status: "dispatch_rejected", error } } await selectSessionInTui(ctx.client, newSessionID) const boundState = options.loopState.setSessionID(newSessionID) if (!boundState) { log(`[${HOOK_NAME}] Failed to bind loop state to new session`, { previousSessionID: options.previousSessionID, newSessionID, }) return { status: "dispatched" } } return { status: "dispatched" } } try { const promptResult = await injectContinuationPrompt(ctx, { sessionID: options.previousSessionID, prompt: continuationPrompt, directory: options.directory, apiTimeoutMs: options.apiTimeoutMs, }) if (promptResult.status === "rejected") { return { status: "dispatch_rejected", error: promptResult.error } } } catch (error: unknown) { return { status: "dispatch_rejected", error } } return { status: "dispatched" } }