|
@@ -360,6 +360,64 @@ describe("OpenAI Responses route", () => {
|
|
|
}),
|
|
}),
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
|
|
+ it.effect("preserves structured tool errors for the model", () =>
|
|
|
|
|
+ Effect.gen(function* () {
|
|
|
|
|
+ const error = {
|
|
|
|
|
+ error: { type: "unknown", message: "Tool execution interrupted" },
|
|
|
|
|
+ content: [],
|
|
|
|
|
+ structured: {},
|
|
|
|
|
+ }
|
|
|
|
|
+ const prepared = yield* LLMClient.prepare<OpenAIResponses.OpenAIResponsesBody>(
|
|
|
|
|
+ LLM.request({
|
|
|
|
|
+ model,
|
|
|
|
|
+ messages: [
|
|
|
|
|
+ Message.assistant([ToolCallPart.make({ id: "call_1", name: "bash", input: { command: "sleep 10" } })]),
|
|
|
|
|
+ Message.tool({
|
|
|
|
|
+ id: "call_1",
|
|
|
|
|
+ name: "bash",
|
|
|
|
|
+ resultType: "error",
|
|
|
|
|
+ result: error,
|
|
|
|
|
+ }),
|
|
|
|
|
+ ],
|
|
|
|
|
+ }),
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ expect(expectToolOutput(prepared.body).output).toBe(ProviderShared.encodeJson(error))
|
|
|
|
|
+ }),
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ it.effect("keeps primitive tool errors as plain text", () =>
|
|
|
|
|
+ Effect.gen(function* () {
|
|
|
|
|
+ const prepared = yield* LLMClient.prepare<OpenAIResponses.OpenAIResponsesBody>(
|
|
|
|
|
+ LLM.request({
|
|
|
|
|
+ model,
|
|
|
|
|
+ messages: [
|
|
|
|
|
+ Message.assistant([ToolCallPart.make({ id: "call_1", name: "bash", input: {} })]),
|
|
|
|
|
+ Message.tool({ id: "call_1", name: "bash", resultType: "error", result: 503 }),
|
|
|
|
|
+ ],
|
|
|
|
|
+ }),
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ expect(expectToolOutput(prepared.body).output).toBe("503")
|
|
|
|
|
+ }),
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ it.effect("keeps non-JSON tool errors as plain text", () =>
|
|
|
|
|
+ Effect.gen(function* () {
|
|
|
|
|
+ const prepared = yield* LLMClient.prepare<OpenAIResponses.OpenAIResponsesBody>(
|
|
|
|
|
+ LLM.request({
|
|
|
|
|
+ model,
|
|
|
|
|
+ messages: [
|
|
|
|
|
+ Message.assistant([ToolCallPart.make({ id: "call_1", name: "bash", input: {} })]),
|
|
|
|
|
+ Message.tool({ id: "call_1", name: "bash", resultType: "error", result: new Error("boom") }),
|
|
|
|
|
+ ],
|
|
|
|
|
+ }),
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ expect(expectToolOutput(prepared.body).output).toBe("Error: boom")
|
|
|
|
|
+ }),
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
// Regression: screenshot/read tool results must stay structured so base64
|
|
// Regression: screenshot/read tool results must stay structured so base64
|
|
|
// image data is not JSON-stringified into `function_call_output.output`.
|
|
// image data is not JSON-stringified into `function_call_output.output`.
|
|
|
it.effect("lowers image tool-result content as structured input_image items", () =>
|
|
it.effect("lowers image tool-result content as structured input_image items", () =>
|