Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions packages/agent/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,14 @@
"example:structured": "tsx examples/06-structured-output.ts"
},
"dependencies": {
"@ai-sdk/provider": "4.0.33",
"@ai-sdk/provider": "4.0.34",
"ws": "^8.22.0"
},
"devDependencies": {
"@ai-sdk/react": "4.0.156",
"@ai-sdk/react": "4.0.157",
"@types/node": "^26.6.5",
"@types/ws": "^8.18.2",
"ai": "^7.0.152",
"ai": "^7.0.153",
"tsup": "^9.0.0",
"tsx": "^4.23.15",
"typescript": "npm:@typescript/typescript6@^6.0.2",
Expand Down
8 changes: 4 additions & 4 deletions packages/effect/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,18 +56,18 @@
"example:sandbox": "tsx examples/03-sandbox.ts"
},
"dependencies": {
"@ai-sdk/provider": "4.0.33",
"@ai-sdk/provider": "4.0.34",
Comment thread
ThomasK33 marked this conversation as resolved.
"@coder/ai-sdk-agent": "workspace:^",
"@coder/ai-sdk-provider": "workspace:^",
"@coder/ai-sdk-sandbox": "workspace:^"
},
"devDependencies": {
"@ai-sdk/harness": "^1.0.163",
"@ai-sdk/provider-utils": "^5.0.67",
"@ai-sdk/harness": "^1.0.164",
"@ai-sdk/provider-utils": "^5.0.68",
"@arethetypeswrong/cli": "^0.18.5",
"@types/node": "^26.6.3",
"@vitest/coverage-v8": "^5.0.5",
"ai": "^7.0.152",
"ai": "^7.0.153",
"effect": "4.0.6",
"publint": "^0.3.25",
"tsup": "^9.0.0",
Expand Down
12 changes: 12 additions & 0 deletions packages/effect/src/language-model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
* equivalent (custom parts, reasoning files, tool approval requests,
* URL/reference/text file payloads) are dropped, and so are tool approval
* parts in the prompt (`effect/ai` resolves and strips them before the call).
* In JSON mode, a `generateText` result's `structuredOutputText` replaces its
* text parts, because `effect/ai` parses the joined text parts as the answer.
*
* Provider-executed tool calls and results for tools that are not in the
* call's toolkit (e.g. Coder Agents' server-side tools) cannot be decoded by
Expand Down Expand Up @@ -238,10 +240,20 @@ const generateText = (
if (result.response !== undefined) {
parts.push(responseMetadataPart(result.response));
}
// `effect/ai` parses the joined text parts as the JSON answer. A
// provider's `structuredOutputText` (e.g. OpenAI Responses drafts
// followed by a final answer) replaces them. An empty string is an
// explicit selection and must not fall back to the text parts.
const structured =
options.responseFormat.type === "json" ? result.structuredOutputText : undefined;
for (const content of result.content) {
if (serverTools.absorb(content)) continue;
if (structured !== undefined && content.type === "text") continue;
parts.push(...contentToParts(content));
}
if (structured !== undefined) {
parts.push({ type: "text", text: structured });
}
parts.push(finishPart(result.finishReason, result.usage, serverTools));
return parts;
},
Expand Down
31 changes: 31 additions & 0 deletions packages/effect/test/language-model.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,37 @@ describe("generateObject", () => {
expect(first.content).toContain(`"city"`);
}
});

it("decodes structuredOutputText instead of the joined text parts", async () => {
// @ai-sdk/provider 4.0.34: OpenAI Responses can return a JSON draft and
// a final answer; `structuredOutputText` selects the final one.
const model = fakeModel({
doGenerate: async () => ({
content: [
{ type: "text", text: `{"city":"Bonn","temperature":9}` },
{ type: "text", text: `{"city":"Berlin","temperature":21}` },
],
structuredOutputText: `{"city":"Berlin","temperature":21}`,
finishReason: { unified: "stop", raw: undefined },
usage: USAGE,
warnings: [],
}),
});

const Weather = Schema.Struct({ city: Schema.String, temperature: Schema.Finite });
const [object, text] = await Effect.runPromise(
Effect.flatMap(service(model), (m) =>
Effect.all([
m.generateObject({ prompt: "weather in berlin", schema: Weather }),
m.generateText({ prompt: "weather in berlin" }),
]),
),
);

expect(object.value).toEqual({ city: "Berlin", temperature: 21 });
// Plain text calls keep every text part.
expect(text.text).toBe(`{"city":"Bonn","temperature":9}{"city":"Berlin","temperature":21}`);
});
});

describe("streamText", () => {
Expand Down
8 changes: 4 additions & 4 deletions packages/provider/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,15 @@
"example:anthropic": "tsx examples/03-anthropic.ts"
},
"dependencies": {
"@ai-sdk/anthropic": "^4.0.87",
"@ai-sdk/openai-compatible": "^3.0.77",
"@ai-sdk/provider": "4.0.33"
"@ai-sdk/anthropic": "^4.0.88",
"@ai-sdk/openai-compatible": "^3.0.78",
"@ai-sdk/provider": "4.0.34"
},
"devDependencies": {
"@arethetypeswrong/cli": "^0.18.5",
"@types/node": "^26.6.5",
"@vitest/coverage-v8": "^5.0.5",
"ai": "^7.0.152",
"ai": "^7.0.153",
"publint": "^0.3.25",
"tsup": "^9.0.0",
"tsx": "^4.23.15",
Expand Down
4 changes: 2 additions & 2 deletions packages/release-please-ai/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
"release": "tsx src/cli.ts"
},
"dependencies": {
"@ai-sdk/anthropic": "^4.0.87",
"ai": "^7.0.152",
"@ai-sdk/anthropic": "^4.0.88",
"ai": "^7.0.153",
"release-please": "~17.11.2",
"zod": "4.6.7"
},
Expand Down
8 changes: 4 additions & 4 deletions packages/sandbox/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,10 @@
"yaml": "^2.9.1"
},
"devDependencies": {
"@ai-sdk/harness": "^1.0.163",
"@ai-sdk/harness-claude-code": "^1.0.167",
"@ai-sdk/provider-utils": "^5.0.67",
"@ai-sdk/tui": "^1.0.153",
"@ai-sdk/harness": "^1.0.164",
"@ai-sdk/harness-claude-code": "^1.0.168",
"@ai-sdk/provider-utils": "^5.0.68",
"@ai-sdk/tui": "^1.0.154",
"@arethetypeswrong/cli": "^0.18.5",
"@types/node": "^26.6.5",
"@types/ws": "^8.18.2",
Expand Down
Loading
Loading