fix(core): preserve the first terminal failure (#37705)

This commit is contained in:
Kit Langton 2026-07-19 00:00:23 -04:00 committed by GitHub
commit ba0bbdafaa
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 35 additions and 39 deletions

View file

@ -296,7 +296,6 @@ it.effect("emits malformed AI SDK tool input without executing it", () =>
id: "call_1",
name: "lookup",
raw,
message: "Invalid JSON input for aisdk tool call lookup",
})
expect(response.events.some(LLMEvent.is.toolInputEnd)).toBeTrue()
expect(response.events.some(LLMEvent.is.toolCall)).toBeFalse()

View file

@ -4180,7 +4180,6 @@ describe("SessionRunnerLLM", () => {
id: "call-malformed",
name: "echo",
raw,
message: "Invalid JSON input for test tool call echo",
}),
LLMEvent.stepFinish({ index: 0, reason: "tool-calls" }),
LLMEvent.finish({ reason: "tool-calls" }),
@ -4278,7 +4277,6 @@ describe("SessionRunnerLLM", () => {
id: "call-malformed",
name: "echo",
raw: '{"text":"partial',
message: "Invalid JSON input for test tool call echo",
}),
LLMEvent.stepFinish({ index: 0, reason: "tool-calls" }),
LLMEvent.finish({ reason: "tool-calls" }),
@ -4321,7 +4319,6 @@ describe("SessionRunnerLLM", () => {
id: "call-malformed",
name: "echo",
raw: '{"text":"partial',
message: "Invalid JSON input for test tool call echo",
}),
LLMEvent.stepFinish({ index: 0, reason: "tool-calls" }),
LLMEvent.finish({ reason: "tool-calls" }),
@ -4387,7 +4384,7 @@ describe("SessionRunnerLLM", () => {
}),
)
it.effect("replaces malformed input diagnosis with a later provider failure", () =>
it.effect("records a provider failure after malformed input", () =>
Effect.gen(function* () {
const session = yield* setup
yield* admit(session, "Fail after malformed input")
@ -4402,7 +4399,6 @@ describe("SessionRunnerLLM", () => {
id: "call-malformed",
name: "echo",
raw: '{"text":"partial',
message: "Invalid JSON input for test tool call echo",
}),
]).pipe(Stream.concat(Stream.fail(failure)))
@ -4432,7 +4428,6 @@ describe("SessionRunnerLLM", () => {
id,
name: "echo",
raw: '{"text":"partial',
message: "Invalid JSON input for test tool call echo",
}),
LLMEvent.stepFinish({ index: 0, reason: "tool-calls" }),
LLMEvent.finish({ reason: "tool-calls" }),
@ -4468,7 +4463,6 @@ describe("SessionRunnerLLM", () => {
id,
name: "echo",
raw: '{"text":"partial',
message: "Invalid JSON input for test tool call echo",
}),
LLMEvent.stepFinish({ index: 0, reason: "tool-calls" }),
LLMEvent.finish({ reason: "tool-calls" }),
@ -4575,6 +4569,24 @@ describe("SessionRunnerLLM", () => {
}),
)
it.effect("preserves the provider failure when tool output persistence also fails", () =>
Effect.gen(function* () {
const session = yield* setup
yield* admit(session, "Storage fails while provider fails")
response = [
LLMEvent.stepStart({ index: 0 }),
LLMEvent.toolCall({ id: "call-store-provider-error", name: "storefail", input: {} }),
LLMEvent.providerError({ message: "Provider unavailable" }),
]
expect(yield* session.resume(sessionID).pipe(Effect.exit)).toMatchObject({ _tag: "Failure" })
expect(requireAssistant(yield* session.context(sessionID))).toMatchObject({
error: { type: "provider.unknown", message: "Provider unavailable" },
})
}),
)
it.effect("durably fails a hosted tool left unresolved at normal provider EOF", () =>
Effect.gen(function* () {
const session = yield* setup