-
Notifications
You must be signed in to change notification settings - Fork 0
Enable Codex structured output in Rig Codex adapter #283
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -466,6 +466,7 @@ export type AgentOptions = { | |
|
|
||
| export type AgentAskOptions = { | ||
| signal?: AbortSignal; | ||
| outputSchema?: JsonSchemaObject; | ||
| }; | ||
|
|
||
| export interface Agent { | ||
|
|
@@ -1906,7 +1907,10 @@ export function agent(spec: AgentSpec<any, any>): AgentFn<any, any> { | |
| await runAgentAddons(runtime.addons, context, async () => { | ||
| lastResponse = await runtimeAgent.ask( | ||
| context.prompt, | ||
| context.signal ? { signal: context.signal } : undefined, | ||
| { | ||
| ...(context.signal ? { signal: context.signal } : {}), | ||
| outputSchema: toJsonSchema(context.outputSchema), | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [/codebase-design] 💡 ContextThe Copilot engine (line 564 in rig.ts) discards |
||
| }, | ||
| ); | ||
| context.response = lastResponse; | ||
| debugAgentResponse({ agent: normalizedSpec.name, turn, response: lastResponse }); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -69,6 +69,29 @@ it("uses Codex defaults when optional configuration is absent", async () => { | |
| expect(mocks.startThread).toHaveBeenCalledWith({ model: "gpt-5-codex" }); | ||
| }); | ||
|
|
||
| it("forwards output schemas to Codex and stringifies structured responses", async () => { | ||
| const runtimeAgent = await codexEngine()({ model: "gpt-5-codex" }); | ||
| const outputSchema = { | ||
| type: "object", | ||
| properties: { | ||
| summary: { type: "string" }, | ||
| }, | ||
| required: ["summary"], | ||
| additionalProperties: false, | ||
| } as const; | ||
| mocks.run.mockResolvedValueOnce({ finalResponse: { summary: "done" } }); | ||
|
|
||
| await expect(runtimeAgent.ask("summarize", { outputSchema })).resolves.toBe(JSON.stringify({ summary: "done" })); | ||
|
|
||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [/tdd] The test only covers the structured-object path. Add a test confirming that a plain string 💡 Suggested testit('returns string finalResponse unchanged when outputSchema is set', async () => {
const runtimeAgent = await codexEngine()({ model: 'gpt-5-codex' });
mocks.run.mockResolvedValueOnce({ finalResponse: '{"summary":"done"}' });
await expect(
runtimeAgent.ask('summarize', { outputSchema: { type: 'object' } })
).resolves.toBe('{"summary":"done"}');
}); |
||
| expect(mocks.run).toHaveBeenCalledWith( | ||
| "summarize", | ||
| expect.objectContaining({ | ||
| signal: expect.any(AbortSignal), | ||
| outputSchema, | ||
| }), | ||
| ); | ||
| }); | ||
|
|
||
| it("rejects non-string system messages", () => { | ||
| const factory = codexEngine(); | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[/tdd] Missing edge case:
finalResponsecould benull—JSON.stringify(null)returns"null", which propagates silently as a valid response but will fail downstream schema validation.💡 Suggested test + guard
Consider throwing if
finalResponseis nullish when anoutputSchemawas requested, or explicitly document thatnullstringifies to"null".