fix(ulw-loop): retry parent session after failed verification
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
import type { PluginInput } from "@opencode-ai/plugin"
|
||||
import { log } from "../../shared/logger"
|
||||
import { buildVerificationFailurePrompt } from "./continuation-prompt-builder"
|
||||
import { HOOK_NAME } from "./constants"
|
||||
import { injectContinuationPrompt } from "./continuation-prompt-injector"
|
||||
import type { RalphLoopState } from "./types"
|
||||
|
||||
type LoopStateController = {
|
||||
restartAfterFailedVerification: (
|
||||
sessionID: string,
|
||||
messageCountAtStart?: number,
|
||||
) => RalphLoopState | null
|
||||
}
|
||||
|
||||
function getMessageCountFromResponse(messagesResponse: unknown): number {
|
||||
if (Array.isArray(messagesResponse)) {
|
||||
return messagesResponse.length
|
||||
}
|
||||
|
||||
if (
|
||||
typeof messagesResponse === "object"
|
||||
&& messagesResponse !== null
|
||||
&& "data" in messagesResponse
|
||||
) {
|
||||
const data = (messagesResponse as { data?: unknown }).data
|
||||
return Array.isArray(data) ? data.length : 0
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
async function getSessionMessageCount(
|
||||
ctx: PluginInput,
|
||||
sessionID: string,
|
||||
directory: string,
|
||||
): Promise<number> {
|
||||
const messagesResponse = await ctx.client.session.messages({
|
||||
path: { id: sessionID },
|
||||
query: { directory },
|
||||
})
|
||||
|
||||
return getMessageCountFromResponse(messagesResponse)
|
||||
}
|
||||
|
||||
export async function handleFailedVerification(
|
||||
ctx: PluginInput,
|
||||
input: {
|
||||
state: RalphLoopState
|
||||
directory: string
|
||||
apiTimeoutMs: number
|
||||
loopState: LoopStateController
|
||||
},
|
||||
): Promise<boolean> {
|
||||
const { state, directory, apiTimeoutMs, loopState } = input
|
||||
const parentSessionID = state.session_id
|
||||
if (!parentSessionID) {
|
||||
return false
|
||||
}
|
||||
|
||||
let messageCountAtStart: number
|
||||
try {
|
||||
messageCountAtStart = await getSessionMessageCount(ctx, parentSessionID, directory)
|
||||
} catch (error) {
|
||||
log(`[${HOOK_NAME}] Failed to read parent session before verification retry`, {
|
||||
parentSessionID,
|
||||
error: String(error),
|
||||
})
|
||||
return false
|
||||
}
|
||||
|
||||
const resumedState = loopState.restartAfterFailedVerification(
|
||||
parentSessionID,
|
||||
messageCountAtStart,
|
||||
)
|
||||
if (!resumedState) {
|
||||
log(`[${HOOK_NAME}] Failed to restart loop after verification failure`, {
|
||||
parentSessionID,
|
||||
})
|
||||
return false
|
||||
}
|
||||
|
||||
await injectContinuationPrompt(ctx, {
|
||||
sessionID: parentSessionID,
|
||||
prompt: buildVerificationFailurePrompt(resumedState),
|
||||
directory,
|
||||
apiTimeoutMs,
|
||||
})
|
||||
|
||||
await ctx.client.tui?.showToast?.({
|
||||
body: {
|
||||
title: "ULTRAWORK LOOP",
|
||||
message: "Oracle verification failed. Continuing ULTRAWORK loop.",
|
||||
variant: "warning",
|
||||
duration: 5000,
|
||||
},
|
||||
}).catch(() => {})
|
||||
|
||||
return true
|
||||
}
|
||||
Reference in New Issue
Block a user