Files
oh-my-opencode/src/hooks/ralph-loop/iteration-continuation.ts
T
2026-05-12 13:14:07 +09:00

86 lines
2.6 KiB
TypeScript

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<ContinuationResult> {
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" }
}