fix(prompt-gate): harden internal prompt dispatch
This commit is contained in:
@@ -1,7 +1,12 @@
|
||||
import { describe, expect, test } from "bun:test"
|
||||
import { afterEach, describe, expect, test } from "bun:test"
|
||||
import { releaseAllPromptAsyncReservationsForTesting } from "../shared/prompt-async-gate"
|
||||
import { injectContinuationPrompt } from "./continuation-prompt-injector"
|
||||
|
||||
describe("ralph-loop continuation prompt injector", () => {
|
||||
afterEach(() => {
|
||||
releaseAllPromptAsyncReservationsForTesting()
|
||||
})
|
||||
|
||||
test("#given promptAsync resolves SDK error #when injecting continuation prompt #then it returns rejection without throwing", async () => {
|
||||
// given
|
||||
const ctx = {
|
||||
@@ -59,6 +64,32 @@ describe("ralph-loop continuation prompt injector", () => {
|
||||
}
|
||||
})
|
||||
|
||||
test("#given promptAsync may have accepted before EOF #when injecting continuation prompt #then it returns dispatched", async () => {
|
||||
// given
|
||||
const ctx = {
|
||||
client: {
|
||||
session: {
|
||||
messages: async () => ({ data: [] }),
|
||||
promptAsync: async () => {
|
||||
throw new Error("JSON Parse error: Unexpected EOF")
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// when
|
||||
const result = await injectContinuationPrompt(ctx as never, {
|
||||
sessionID: "ses_ralph_eof",
|
||||
prompt: "continue",
|
||||
directory: "/tmp/test",
|
||||
apiTimeoutMs: 50,
|
||||
})
|
||||
|
||||
// then
|
||||
expect(result.status).toBe("dispatched")
|
||||
})
|
||||
|
||||
|
||||
test("#given inherited message agent has ZWSP prefix #when injecting continuation prompt #then promptAsync receives registered display agent", async () => {
|
||||
// given
|
||||
let promptBody: { agent?: string; noReply?: boolean } | undefined
|
||||
|
||||
@@ -5,6 +5,7 @@ import { getMessageDir } from "./message-storage-directory"
|
||||
import { withTimeout } from "./with-timeout"
|
||||
import {
|
||||
createInternalAgentContinuationTextPart,
|
||||
isAmbiguousPromptDispatchFailure,
|
||||
isRecord,
|
||||
normalizeSDKResponse,
|
||||
resolveInheritedPromptTools,
|
||||
@@ -145,6 +146,7 @@ export async function injectContinuationPrompt(
|
||||
sessionID: options.sessionID,
|
||||
source: "ralph-loop",
|
||||
settleMs: options.idleSettleMs,
|
||||
queueBehavior: "defer",
|
||||
input: {
|
||||
path: { id: options.sessionID },
|
||||
body: {
|
||||
@@ -158,8 +160,14 @@ export async function injectContinuationPrompt(
|
||||
},
|
||||
})
|
||||
if (promptResult.status === "failed") {
|
||||
if (isAmbiguousPromptDispatchFailure(promptResult.error)) {
|
||||
return { status: "dispatched" }
|
||||
}
|
||||
throw promptResult.error
|
||||
}
|
||||
if (promptResult.status === "queued") {
|
||||
return { status: "deferred", reason: "reserved" }
|
||||
}
|
||||
if (promptResult.status === "active" || promptResult.status === "reserved") {
|
||||
return { status: "deferred", reason: promptResult.status }
|
||||
}
|
||||
@@ -171,6 +179,9 @@ export async function injectContinuationPrompt(
|
||||
}
|
||||
response = promptResult.response
|
||||
} catch (error) {
|
||||
if (isAmbiguousPromptDispatchFailure(error)) {
|
||||
return { status: "dispatched" }
|
||||
}
|
||||
const promptError = error instanceof Error
|
||||
? error
|
||||
: createPromptAsyncError("promptAsync rejected", error)
|
||||
|
||||
Reference in New Issue
Block a user