Skip to content

Commit 7fcef85

Browse files
committed
Add all currently available properties to the openai conversion
1 parent 20c708c commit 7fcef85

File tree

3 files changed

+59
-41
lines changed

3 files changed

+59
-41
lines changed

packages/agents-openai/src/openaiResponsesModel.ts

Lines changed: 40 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,10 @@ import {
3333
ImageGenerationStatus,
3434
WebSearchStatus,
3535
} from './tools';
36-
import { camelToSnakeCase, snakeToCamelCase } from './utils/providerData';
36+
import {
37+
camelOrSnakeToSnakeCase,
38+
snakeToCamelCase,
39+
} from './utils/providerData';
3740
import { ProviderData } from '@openai/agents-core/types';
3841

3942
type ToolChoice = ToolChoiceOptions | ToolChoiceTypes | ToolChoiceFunction;
@@ -242,7 +245,7 @@ function getInputMessageContent(
242245
return {
243246
type: 'input_text',
244247
text: entry.text,
245-
...camelToSnakeCase(entry.providerData),
248+
...camelOrSnakeToSnakeCase(entry.providerData),
246249
};
247250
} else if (entry.type === 'input_image') {
248251
const imageEntry: OpenAI.Responses.ResponseInputImage = {
@@ -256,7 +259,7 @@ function getInputMessageContent(
256259
}
257260
return {
258261
...imageEntry,
259-
...camelToSnakeCase(entry.providerData),
262+
...camelOrSnakeToSnakeCase(entry.providerData),
260263
};
261264
} else if (entry.type === 'input_file') {
262265
const fileEntry: OpenAI.Responses.ResponseInputFile = {
@@ -269,7 +272,7 @@ function getInputMessageContent(
269272
}
270273
return {
271274
...fileEntry,
272-
...camelToSnakeCase(entry.providerData),
275+
...camelOrSnakeToSnakeCase(entry.providerData),
273276
};
274277
}
275278

@@ -286,15 +289,15 @@ function getOutputMessageContent(
286289
type: 'output_text',
287290
text: entry.text,
288291
annotations: [],
289-
...camelToSnakeCase(entry.providerData),
292+
...camelOrSnakeToSnakeCase(entry.providerData),
290293
};
291294
}
292295

293296
if (entry.type === 'refusal') {
294297
return {
295298
type: 'refusal',
296299
refusal: entry.refusal,
297-
...camelToSnakeCase(entry.providerData),
300+
...camelOrSnakeToSnakeCase(entry.providerData),
298301
};
299302
}
300303

@@ -314,7 +317,7 @@ function getMessageItem(
314317
id: item.id,
315318
role: 'system',
316319
content: item.content,
317-
...camelToSnakeCase(item.providerData),
320+
...camelOrSnakeToSnakeCase(item.providerData),
318321
};
319322
}
320323

@@ -324,15 +327,15 @@ function getMessageItem(
324327
id: item.id,
325328
role: 'user',
326329
content: item.content,
327-
...camelToSnakeCase(item.providerData),
330+
...camelOrSnakeToSnakeCase(item.providerData),
328331
};
329332
}
330333

331334
return {
332335
id: item.id,
333336
role: 'user',
334337
content: item.content.map(getInputMessageContent),
335-
...camelToSnakeCase(item.providerData),
338+
...camelOrSnakeToSnakeCase(item.providerData),
336339
};
337340
}
338341

@@ -343,7 +346,7 @@ function getMessageItem(
343346
role: 'assistant',
344347
content: item.content.map(getOutputMessageContent),
345348
status: item.status,
346-
...camelToSnakeCase(item.providerData),
349+
...camelOrSnakeToSnakeCase(item.providerData),
347350
};
348351
return assistantMessage;
349352
}
@@ -388,7 +391,7 @@ function getInputItems(
388391
call_id: item.callId,
389392
arguments: item.arguments,
390393
status: item.status,
391-
...camelToSnakeCase(item.providerData),
394+
...camelOrSnakeToSnakeCase(item.providerData),
392395
};
393396

394397
return entry;
@@ -406,7 +409,8 @@ function getInputItems(
406409
id: item.id,
407410
call_id: item.callId,
408411
output: item.output.text,
409-
...camelToSnakeCase(item.providerData),
412+
status: item.status,
413+
...camelOrSnakeToSnakeCase(item.providerData),
410414
};
411415

412416
return entry;
@@ -419,9 +423,10 @@ function getInputItems(
419423
summary: item.content.map((content) => ({
420424
type: 'summary_text',
421425
text: content.text,
422-
...camelToSnakeCase(content.providerData),
426+
...camelOrSnakeToSnakeCase(content.providerData),
423427
})),
424-
...camelToSnakeCase(item.providerData),
428+
encrypted_content: item.providerData?.encryptedContent,
429+
...camelOrSnakeToSnakeCase(item.providerData),
425430
};
426431
return entry;
427432
}
@@ -434,7 +439,7 @@ function getInputItems(
434439
action: item.action,
435440
status: item.status,
436441
pending_safety_checks: [],
437-
...camelToSnakeCase(item.providerData),
442+
...camelOrSnakeToSnakeCase(item.providerData),
438443
};
439444

440445
return entry;
@@ -446,7 +451,9 @@ function getInputItems(
446451
id: item.id,
447452
call_id: item.callId,
448453
output: buildResponseOutput(item),
449-
...camelToSnakeCase(item.providerData),
454+
status: item.providerData?.status,
455+
acknowledged_safety_checks: item.providerData?.acknowledgedSafetyChecks,
456+
...camelOrSnakeToSnakeCase(item.providerData),
450457
};
451458
return entry;
452459
}
@@ -457,7 +464,7 @@ function getInputItems(
457464
type: 'web_search_call',
458465
id: item.id!,
459466
status: WebSearchStatus.parse(item.status ?? 'failed'),
460-
...camelToSnakeCase(item.providerData),
467+
...camelOrSnakeToSnakeCase(item.providerData),
461468
};
462469

463470
return entry;
@@ -469,7 +476,8 @@ function getInputItems(
469476
id: item.id!,
470477
status: FileSearchStatus.parse(item.status ?? 'failed'),
471478
queries: item.providerData?.queries ?? [],
472-
...camelToSnakeCase(item.providerData),
479+
results: item.providerData?.results,
480+
...camelOrSnakeToSnakeCase(item.providerData),
473481
};
474482

475483
return entry;
@@ -482,7 +490,8 @@ function getInputItems(
482490
code: item.providerData?.code ?? '',
483491
results: item.providerData?.results ?? [],
484492
status: CodeInterpreterStatus.parse(item.status ?? 'failed'),
485-
...camelToSnakeCase(item.providerData),
493+
container_id: item.providerData?.containerId,
494+
...camelOrSnakeToSnakeCase(item.providerData),
486495
};
487496

488497
return entry;
@@ -494,7 +503,7 @@ function getInputItems(
494503
id: item.id!,
495504
result: item.providerData?.result ?? null,
496505
status: ImageGenerationStatus.parse(item.status ?? 'failed'),
497-
...camelToSnakeCase(item.providerData),
506+
...camelOrSnakeToSnakeCase(item.providerData),
498507
};
499508

500509
return entry;
@@ -509,9 +518,10 @@ function getInputItems(
509518
const entry: OpenAI.Responses.ResponseInputItem.McpListTools = {
510519
type: 'mcp_list_tools',
511520
id: item.id!,
512-
tools: camelToSnakeCase(providerData.tools) as any,
521+
tools: camelOrSnakeToSnakeCase(providerData.tools) as any,
513522
server_label: providerData.serverLabel,
514-
...camelToSnakeCase(item.providerData),
523+
error: providerData.error,
524+
...camelOrSnakeToSnakeCase(item.providerData),
515525
};
516526
return entry;
517527
} else if (
@@ -526,7 +536,7 @@ function getInputItems(
526536
name: providerData.name,
527537
arguments: providerData.arguments,
528538
server_label: providerData.serverLabel,
529-
...camelToSnakeCase(item.providerData),
539+
...camelOrSnakeToSnakeCase(item.providerData),
530540
};
531541
return entry;
532542
} else if (
@@ -537,10 +547,11 @@ function getInputItems(
537547
item.providerData as ProviderData.HostedMCPApprovalResponse;
538548
const entry: OpenAI.Responses.ResponseInputItem.McpApprovalResponse = {
539549
type: 'mcp_approval_response',
550+
id: providerData.id,
540551
approve: providerData.approve,
541552
approval_request_id: providerData.approvalRequestId,
542553
reason: providerData.reason,
543-
...camelToSnakeCase(providerData),
554+
...camelOrSnakeToSnakeCase(providerData),
544555
};
545556
return entry;
546557
} else if (
@@ -554,7 +565,10 @@ function getInputItems(
554565
name: providerData.name,
555566
arguments: providerData.arguments,
556567
server_label: providerData.serverLabel,
557-
...camelToSnakeCase(providerData),
568+
error: providerData.error,
569+
// output, which can be a large text string, is optional here, so we don't include it
570+
// output: item.output,
571+
...camelOrSnakeToSnakeCase(providerData),
558572
};
559573
return entry;
560574
}
@@ -567,7 +581,7 @@ function getInputItems(
567581
if (item.type === 'unknown') {
568582
return {
569583
id: item.id,
570-
...camelToSnakeCase(item.providerData),
584+
...camelOrSnakeToSnakeCase(item.providerData),
571585
} as OpenAI.Responses.ResponseItem;
572586
}
573587

packages/agents-openai/src/utils/providerData.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
/**
2-
* Converts camelCase keys of an object to snake_case recursively.
2+
* Converts camelCase or snake_case keys of an object to snake_case recursively.
33
*/
4-
export function camelToSnakeCase<T extends Record<string, any> | undefined>(
5-
providerData: T | undefined,
6-
): Record<string, any> | undefined {
4+
export function camelOrSnakeToSnakeCase<
5+
T extends Record<string, any> | undefined,
6+
>(providerData: T | undefined): Record<string, any> | undefined {
77
if (
88
!providerData ||
99
typeof providerData !== 'object' ||
@@ -15,7 +15,7 @@ export function camelToSnakeCase<T extends Record<string, any> | undefined>(
1515
const result: Record<string, any> = {};
1616
for (const [key, value] of Object.entries(providerData)) {
1717
const snakeKey = key.replace(/([A-Z])/g, '_$1').toLowerCase();
18-
result[snakeKey] = camelToSnakeCase(value);
18+
result[snakeKey] = camelOrSnakeToSnakeCase(value);
1919
}
2020
return result;
2121
}

packages/agents-openai/test/utils/providerData.test.ts

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,29 @@
11
import { describe, it, expect } from 'vitest';
22
import {
3-
camelToSnakeCase,
3+
camelOrSnakeToSnakeCase,
44
snakeToCamelCase,
55
} from '../../src/utils/providerData';
66

77
describe('camelToSnakeCase', () => {
88
it('converts flat camelCase keys to snake_case', () => {
9-
expect(camelToSnakeCase({ fooBar: 1, bazQux: 2 })).toEqual({
9+
expect(camelOrSnakeToSnakeCase({ fooBar: 1, bazQux: 2 })).toEqual({
1010
foo_bar: 1,
1111
baz_qux: 2,
1212
});
1313
});
1414
it('converts snake_case keys to snake_case', () => {
1515
expect(
16-
camelToSnakeCase({ foo_bar_buz: 1, baz_qux: 2, foo_bar: 3 }),
16+
camelOrSnakeToSnakeCase({ foo_bar_buz: 1, baz_qux: 2, foo_bar: 3 }),
1717
).toEqual({
1818
foo_bar_buz: 1,
1919
baz_qux: 2,
2020
foo_bar: 3,
2121
});
2222
});
2323
it('converts mixed keys to snake_case', () => {
24-
expect(camelToSnakeCase({ foo_barBuz: 1, bazQux: 2, foo_bar: 3 })).toEqual({
24+
expect(
25+
camelOrSnakeToSnakeCase({ foo_barBuz: 1, bazQux: 2, foo_bar: 3 }),
26+
).toEqual({
2527
foo_bar_buz: 1,
2628
baz_qux: 2,
2729
foo_bar: 3,
@@ -30,7 +32,7 @@ describe('camelToSnakeCase', () => {
3032

3133
it('handles nested objects', () => {
3234
expect(
33-
camelToSnakeCase({
35+
camelOrSnakeToSnakeCase({
3436
outerKey: { innerKey: 42, anotherInner: { deepKey: 'x' } },
3537
}),
3638
).toEqual({
@@ -40,7 +42,7 @@ describe('camelToSnakeCase', () => {
4042

4143
it('handles nested objects with mixed keys', () => {
4244
expect(
43-
camelToSnakeCase({
45+
camelOrSnakeToSnakeCase({
4446
outerKey: { innerKey: 42, anotherInner: { deep_key: 'x' } },
4547
}),
4648
).toEqual({
@@ -49,19 +51,21 @@ describe('camelToSnakeCase', () => {
4951
});
5052

5153
it('handles arrays and primitives', () => {
52-
expect(camelToSnakeCase([1, 2, 3])).toEqual([1, 2, 3]);
53-
expect(camelToSnakeCase(undefined)).toBe(undefined);
54+
expect(camelOrSnakeToSnakeCase([1, 2, 3])).toEqual([1, 2, 3]);
55+
expect(camelOrSnakeToSnakeCase(undefined)).toBe(undefined);
5456
});
5557

5658
it('leaves already snake_case keys as is', () => {
57-
expect(camelToSnakeCase({ already_snake: 1, also_snake_case: 2 })).toEqual({
59+
expect(
60+
camelOrSnakeToSnakeCase({ already_snake: 1, also_snake_case: 2 }),
61+
).toEqual({
5862
already_snake: 1,
5963
also_snake_case: 2,
6064
});
6165
});
6266

6367
it('handles mixed keys', () => {
64-
expect(camelToSnakeCase({ fooBar: 1, already_snake: 2 })).toEqual({
68+
expect(camelOrSnakeToSnakeCase({ fooBar: 1, already_snake: 2 })).toEqual({
6569
foo_bar: 1,
6670
already_snake: 2,
6771
});

0 commit comments

Comments
 (0)