fix(runtime-events): honor OpenCode progress shapes
This commit is contained in:
@@ -31,6 +31,7 @@ describe("createEventHandler - model fallback", () => {
|
||||
const createHandler = (args?: {
|
||||
hooks?: any
|
||||
pluginConfig?: any
|
||||
abort?: (input: { path: { id: string } }) => Promise<unknown>
|
||||
promptAsync?: (input: { path: { id: string } }) => Promise<unknown>
|
||||
}) => {
|
||||
setupConnectedProviderCacheMocks()
|
||||
@@ -41,6 +42,9 @@ describe("createEventHandler - model fallback", () => {
|
||||
const sessionClient = {
|
||||
abort: async ({ path }: { path: { id: string } }) => {
|
||||
abortCalls.push(path.id)
|
||||
if (args?.abort) {
|
||||
return args.abort({ path })
|
||||
}
|
||||
return {}
|
||||
},
|
||||
prompt: async ({ path }: { path: { id: string } }) => {
|
||||
@@ -305,6 +309,58 @@ describe("createEventHandler - model fallback", () => {
|
||||
expect(abortCalls).toEqual([sessionID])
|
||||
})
|
||||
|
||||
test("#given abort fails before model-fallback continuation #when fallback handles assistant error #then it does not inject another prompt", async () => {
|
||||
//#given
|
||||
const sessionID = "ses_model_fallback_abort_failure"
|
||||
setMainSession(sessionID)
|
||||
let pendingFallbackArms = 0
|
||||
const modelFallback = unsafeTestValue({
|
||||
setSessionFallbackChain: () => {},
|
||||
setPendingModelFallback: () => {
|
||||
pendingFallbackArms += 1
|
||||
return true
|
||||
},
|
||||
})
|
||||
const { handler, abortCalls, promptAsyncCalls } = createHandler({
|
||||
hooks: { modelFallback },
|
||||
abort: async () => {
|
||||
throw new Error("abort transport failed")
|
||||
},
|
||||
promptAsync: async () => ({}),
|
||||
})
|
||||
const assistantError = {
|
||||
name: "APIError",
|
||||
data: {
|
||||
message:
|
||||
"Bad Gateway: {\"error\":{\"message\":\"unknown provider for model claude-opus-4-7-thinking\"}}",
|
||||
isRetryable: true,
|
||||
},
|
||||
}
|
||||
|
||||
//#when
|
||||
await handler({
|
||||
event: {
|
||||
type: "message.updated",
|
||||
properties: {
|
||||
info: {
|
||||
id: "msg_err_abort_failure",
|
||||
sessionID,
|
||||
role: "assistant",
|
||||
error: assistantError,
|
||||
modelID: "claude-opus-4-7-thinking",
|
||||
providerID: "anthropic",
|
||||
agent: "Sisyphus - Ultraworker",
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
//#then
|
||||
expect(pendingFallbackArms).toBe(1)
|
||||
expect(abortCalls).toEqual([sessionID])
|
||||
expect(promptAsyncCalls).toEqual([])
|
||||
})
|
||||
|
||||
test("does not collapse fallback continuations for different providers with the same model id", async () => {
|
||||
//#given
|
||||
const sessionID = "ses_model_fallback_same_model_different_provider"
|
||||
|
||||
+7
-3
@@ -474,9 +474,12 @@ export function createEventHandler(args: {
|
||||
modelFallbackContinuationsInFlight.add(sessionID);
|
||||
let dispatched = false;
|
||||
try {
|
||||
await pluginContext.client.session.abort({ path: { id: sessionID } }).catch((error) => {
|
||||
try {
|
||||
await pluginContext.client.session.abort({ path: { id: sessionID } });
|
||||
} catch (error) {
|
||||
log("[event] model-fallback abort failed", { sessionID, source, error });
|
||||
});
|
||||
return;
|
||||
}
|
||||
releasePromptAsyncReservation(sessionID, `model-fallback-abort:${source}`, {
|
||||
reservedBy: [`model-fallback:${source}`, `model-fallback:${source}:sync`],
|
||||
reservedByPrefix: "model-fallback:",
|
||||
@@ -755,7 +758,8 @@ export function createEventHandler(args: {
|
||||
const sessionID = resolveMessageEventSessionID(props);
|
||||
const agent = info?.agent as string | undefined;
|
||||
const role = info?.role as string | undefined;
|
||||
if (sessionID && info?.finish === true) {
|
||||
const finish = info?.finish;
|
||||
if (sessionID && ((typeof finish === "string" && finish.length > 0) || finish === true)) {
|
||||
invalidateContextWindowUsageCache(pluginContext as PluginInput, sessionID);
|
||||
}
|
||||
if (sessionID && role === "user") {
|
||||
|
||||
Reference in New Issue
Block a user