fix(ai): accept null Responses function call namespace (#55631)

Co-authored-by: kksingh000 <kkandsingh000@gmail.com>
This commit is contained in:
Aiden Cline
2026-10-15 02:13:14 -05:00
committed by GitHub
Unverified
parent ae8d59f8b5
commit b47c6802da
2 changed files with 25 additions and 2 deletions
+4 -2
View File
@@ -334,14 +334,14 @@ export const StreamItem = Schema.StructWithRest(
id: Schema.optional(Schema.String),
call_id: Schema.optional(Schema.String),
name: Schema.optional(Schema.String),
namespace: Schema.optional(Schema.String),
namespace: optionalNull(Schema.String),
arguments: Schema.optional(Schema.String),
encrypted_content: optionalNull(Schema.String),
}),
[Schema.Record(Schema.String, Schema.Unknown)],
)
export type StreamItem = Schema.Schema.Type<typeof StreamItem>
export type OutputItem = StreamItem & { readonly id: string }
export type OutputItem = StreamItem & { readonly id: string; readonly namespace?: string }
// Responses-compatible providers put error details at the top level, under `error`, or under
// `response.error`, and gateways reshape them freely: strings, numeric codes, extra fields. Those
@@ -946,6 +946,8 @@ const resolveItem = (
index: number | undefined,
): OutputItem => ({
...item,
// Some gateways serialize an absent namespace as null.
namespace: item.namespace ?? undefined,
id:
item.id ??
(index === undefined ? undefined : state.outputItems[index]) ??
@@ -644,6 +644,27 @@ describe("Open Responses-compatible route", () => {
}),
)
it.effect("treats a null function call namespace as absent", () =>
Effect.gen(function* () {
const item = { type: "function_call", id: "fc_1", call_id: "call_1", name: "lookup", namespace: null }
const response = yield* LLMClient.generate(request).pipe(
Effect.provide(
fixedResponse(
sseEvents(
{ type: "response.output_item.added", output_index: 0, item: { ...item, arguments: "" } },
{ type: "response.function_call_arguments.done", item_id: "fc_1", output_index: 0, arguments: "{}" },
{ type: "response.output_item.done", output_index: 0, item: { ...item, arguments: "{}" } },
{ type: "response.completed", response: { id: "resp_1", output: [{ ...item, arguments: "{}" }] } },
),
),
),
)
expect(response.toolCalls).toEqual([expect.objectContaining({ id: "call_1", name: "lookup", input: {} })])
expect(response.toolCalls[0]?.namespace).toBeUndefined()
}),
)
it.effect("rejects missing, null, and non-string event IDs even with a registered output index", () =>
Effect.gen(function* () {
yield* Effect.forEach(