Skip to content

Commit fb9ca4f

Browse files
fix aiSDK providerMetadata wrapping (#115)
1 parent 49bfe25 commit fb9ca4f

File tree

5 files changed

+184
-63
lines changed

5 files changed

+184
-63
lines changed

.changeset/smart-mirrors-join.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@openai/agents-extensions': patch
3+
---
4+
5+
fix(aisdk): make providerData less opinionated and pass to content

docs/src/content/docs/extensions/ai-sdk.mdx

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,33 @@ of supported models that can be brought into the Agents SDK through this adapter
5151
## Example
5252

5353
<Code lang="typescript" code={aiSdkSetupExample} title="AI SDK Setup" />
54+
55+
## Passing provider metadata
56+
57+
If you need to send provider-specific options with a message, pass them through
58+
`providerMetadata`. The values are forwarded directly to the underlying AI SDK
59+
model. For example, the following `providerData` in the Agents SDK
60+
61+
```ts
62+
providerData: {
63+
anthropic: {
64+
cacheControl: {
65+
type: 'ephemeral';
66+
}
67+
}
68+
}
69+
```
70+
71+
would become
72+
73+
```ts
74+
providerMetadata: {
75+
anthropic: {
76+
cacheControl: {
77+
type: 'ephemeral';
78+
}
79+
}
80+
}
81+
```
82+
83+
when using the AI SDK integration.

docs/src/content/docs/ja/extensions/ai-sdk.mdx

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,29 @@ import aiSdkSetupExample from '../../../../../../examples/docs/extensions/ai-sdk
4848
##
4949

5050
<Code lang="typescript" code={aiSdkSetupExample} title="AI SDK Setup" />
51+
52+
## プロバイダーメタデータの渡し方
53+
54+
メッセージにプロバイダー固有のオプションを設定したい場合は、`providerMetadata` にその値を直接指定します。例えば Agents SDK で
55+
56+
```ts
57+
providerData: {
58+
anthropic: {
59+
cacheControl: {
60+
type: 'ephemeral';
61+
}
62+
}
63+
}
64+
```
65+
66+
と指定していた場合、AI SDK 連携では次のようになります。
67+
68+
```ts
69+
providerMetadata: {
70+
anthropic: {
71+
cacheControl: {
72+
type: 'ephemeral';
73+
}
74+
}
75+
}
76+
```

packages/agents-extensions/src/aiSdk.ts

Lines changed: 74 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,7 @@ export function itemsToLanguageV1Messages(
5151
role: 'system',
5252
content: content,
5353
providerMetadata: {
54-
[model.provider]: {
55-
...(providerData ?? {}),
56-
},
54+
...(providerData ?? {}),
5755
},
5856
});
5957
continue;
@@ -66,12 +64,25 @@ export function itemsToLanguageV1Messages(
6664
typeof content === 'string'
6765
? [{ type: 'text', text: content }]
6866
: content.map((c) => {
67+
const { providerData: contentProviderData } = c;
6968
if (c.type === 'input_text') {
70-
return { type: 'text', text: c.text };
69+
return {
70+
type: 'text',
71+
text: c.text,
72+
providerMetadata: {
73+
...(contentProviderData ?? {}),
74+
},
75+
};
7176
}
7277
if (c.type === 'input_image') {
7378
const url = new URL(c.image);
74-
return { type: 'image', image: url };
79+
return {
80+
type: 'image',
81+
image: url,
82+
providerMetadata: {
83+
...(contentProviderData ?? {}),
84+
},
85+
};
7586
}
7687
if (c.type === 'input_file') {
7788
if (typeof c.file !== 'string') {
@@ -82,14 +93,15 @@ export function itemsToLanguageV1Messages(
8293
file: c.file,
8394
mimeType: 'application/octet-stream',
8495
data: c.file,
96+
providerMetadata: {
97+
...(contentProviderData ?? {}),
98+
},
8599
};
86100
}
87101
throw new UserError(`Unknown content type: ${c.type}`);
88102
}),
89103
providerMetadata: {
90-
[model.provider]: {
91-
...(providerData ?? {}),
92-
},
104+
...(providerData ?? {}),
93105
},
94106
});
95107
continue;
@@ -106,19 +118,30 @@ export function itemsToLanguageV1Messages(
106118
content: content
107119
.filter((c) => c.type === 'input_text' || c.type === 'output_text')
108120
.map((c) => {
121+
const { providerData: contentProviderData } = c;
109122
if (c.type === 'output_text') {
110-
return { type: 'text', text: c.text };
123+
return {
124+
type: 'text',
125+
text: c.text,
126+
providerMetadata: {
127+
...(contentProviderData ?? {}),
128+
},
129+
};
111130
}
112131
if (c.type === 'input_text') {
113-
return { type: 'text', text: c.text };
132+
return {
133+
type: 'text',
134+
text: c.text,
135+
providerMetadata: {
136+
...(contentProviderData ?? {}),
137+
},
138+
};
114139
}
115140
const exhaustiveCheck = c satisfies never;
116141
throw new UserError(`Unknown content type: ${exhaustiveCheck}`);
117142
}),
118143
providerMetadata: {
119-
[model.provider]: {
120-
...(providerData ?? {}),
121-
},
144+
...(providerData ?? {}),
122145
},
123146
});
124147
continue;
@@ -132,9 +155,7 @@ export function itemsToLanguageV1Messages(
132155
role: 'assistant',
133156
content: [],
134157
providerMetadata: {
135-
[model.provider]: {
136-
...(item.providerData ?? {}),
137-
},
158+
...(item.providerData ?? {}),
138159
},
139160
};
140161
}
@@ -148,6 +169,9 @@ export function itemsToLanguageV1Messages(
148169
toolCallId: item.callId,
149170
toolName: item.name,
150171
args: JSON.parse(item.arguments),
172+
providerMetadata: {
173+
...(item.providerData ?? {}),
174+
},
151175
};
152176
currentAssistantMessage.content.push(content);
153177
}
@@ -162,14 +186,15 @@ export function itemsToLanguageV1Messages(
162186
toolCallId: item.callId,
163187
toolName: item.name,
164188
result: item.output,
189+
providerMetadata: {
190+
...(item.providerData ?? {}),
191+
},
165192
};
166193
messages.push({
167194
role: 'tool',
168195
content: [toolResult],
169196
providerMetadata: {
170-
[model.provider]: {
171-
...(item.providerData ?? {}),
172-
},
197+
...(item.providerData ?? {}),
173198
},
174199
});
175200
continue;
@@ -194,11 +219,15 @@ export function itemsToLanguageV1Messages(
194219
) {
195220
messages.push({
196221
role: 'assistant',
197-
content: [{ type: 'reasoning', text: item.content[0].text }],
198-
providerMetadata: {
199-
[model.provider]: {
200-
...(item.providerData ?? {}),
222+
content: [
223+
{
224+
type: 'reasoning',
225+
text: item.content[0].text,
226+
providerMetadata: { ...(item.providerData ?? {}) },
201227
},
228+
],
229+
providerMetadata: {
230+
...(item.providerData ?? {}),
202231
},
203232
});
204233
continue;
@@ -344,11 +373,6 @@ export class AiSdkModel implements Model {
344373
}
345374

346375
async getResponse(request: ModelRequest) {
347-
if (this.#logger.dontLogModelData) {
348-
this.#logger.debug('Request received');
349-
} else {
350-
this.#logger.debug('Request:', request);
351-
}
352376
return withGenerationSpan(async (span) => {
353377
try {
354378
span.spanData.model = this.#model.provider + ':' + this.#model.modelId;
@@ -396,7 +420,7 @@ export class AiSdkModel implements Model {
396420
const responseFormat: LanguageModelV1CallOptions['responseFormat'] =
397421
getResponseFormat(request.outputType);
398422

399-
const result = await this.#model.doGenerate({
423+
const aiSdkRequest: LanguageModelV1CallOptions = {
400424
inputFormat: 'messages',
401425
mode: {
402426
type: 'regular',
@@ -412,7 +436,15 @@ export class AiSdkModel implements Model {
412436
abortSignal: request.signal,
413437

414438
...(request.modelSettings.providerData ?? {}),
415-
});
439+
};
440+
441+
if (this.#logger.dontLogModelData) {
442+
this.#logger.debug('Request sent');
443+
} else {
444+
this.#logger.debug('Request:', aiSdkRequest);
445+
}
446+
447+
const result = await this.#model.doGenerate(aiSdkRequest);
416448

417449
const output: ModelResponse['output'] = [];
418450

@@ -423,9 +455,7 @@ export class AiSdkModel implements Model {
423455
name: toolCall.toolName,
424456
arguments: toolCall.args,
425457
status: 'completed',
426-
providerData: !result.text
427-
? result.providerMetadata?.[this.#model.provider]
428-
: undefined,
458+
providerData: !result.text ? result.providerMetadata : undefined,
429459
});
430460
});
431461

@@ -439,7 +469,7 @@ export class AiSdkModel implements Model {
439469
content: [{ type: 'output_text', text: result.text }],
440470
role: 'assistant',
441471
status: 'completed',
442-
providerData: result.providerMetadata?.[this.#model.provider],
472+
providerData: result.providerMetadata,
443473
});
444474
}
445475

@@ -509,11 +539,6 @@ export class AiSdkModel implements Model {
509539
async *getStreamedResponse(
510540
request: ModelRequest,
511541
): AsyncIterable<ResponseStreamEvent> {
512-
if (this.#logger.dontLogModelData) {
513-
this.#logger.debug('Request received (streamed)');
514-
} else {
515-
this.#logger.debug('Request (streamed):', request);
516-
}
517542
const span = request.tracing ? createGenerationSpan() : undefined;
518543
try {
519544
if (span) {
@@ -564,7 +589,7 @@ export class AiSdkModel implements Model {
564589
const responseFormat: LanguageModelV1CallOptions['responseFormat'] =
565590
getResponseFormat(request.outputType);
566591

567-
const { stream } = await this.#model.doStream({
592+
const aiSdkRequest: LanguageModelV1CallOptions = {
568593
inputFormat: 'messages',
569594
mode: {
570595
type: 'regular',
@@ -579,7 +604,15 @@ export class AiSdkModel implements Model {
579604
responseFormat,
580605
abortSignal: request.signal,
581606
...(request.modelSettings.providerData ?? {}),
582-
});
607+
};
608+
609+
if (this.#logger.dontLogModelData) {
610+
this.#logger.debug('Request received (streamed)');
611+
} else {
612+
this.#logger.debug('Request (streamed):', aiSdkRequest);
613+
}
614+
615+
const { stream } = await this.#model.doStream(aiSdkRequest);
583616

584617
let started = false;
585618
let responseId: string | undefined;

0 commit comments

Comments
 (0)