@openai/agents-extensions 0.3.8 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1037 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.codexTool = codexTool;
4
+ const agents_1 = require("@openai/agents");
5
+ const _shims_1 = require("@openai/agents-core/_shims");
6
+ const utils_1 = require("@openai/agents-core/utils");
7
+ const codex_sdk_1 = require("@openai/codex-sdk");
8
+ const zod_1 = require("zod");
9
+ const MAX_SPAN_TEXT_LENGTH = 2000;
10
+ const MAX_SPAN_LIST_ITEMS = 200;
11
+ const MAX_TODO_TEXT_LENGTH = 200;
12
+ const CodexToolInputTextSchema = zod_1.z
13
+ .object({
14
+ type: zod_1.z.literal('text'),
15
+ text: zod_1.z
16
+ .string()
17
+ .trim()
18
+ .min(1, 'Text inputs must include a non-empty "text" field.'),
19
+ })
20
+ .strict();
21
+ const CodexToolInputImageSchema = zod_1.z
22
+ .object({
23
+ type: zod_1.z.literal('local_image'),
24
+ path: zod_1.z
25
+ .string()
26
+ .trim()
27
+ .min(1, 'Local image inputs must include a non-empty "path" field.'),
28
+ })
29
+ .strict();
30
+ const CodexToolInputItemSchema = zod_1.z.union([
31
+ CodexToolInputTextSchema,
32
+ CodexToolInputImageSchema,
33
+ ]);
34
+ const OutputSchemaStringSchema = zod_1.z
35
+ .object({
36
+ type: zod_1.z.literal('string'),
37
+ description: zod_1.z.string().trim().optional(),
38
+ enum: zod_1.z.array(zod_1.z.string().trim().min(1)).min(1).optional(),
39
+ })
40
+ .strict();
41
+ const OutputSchemaNumberSchema = zod_1.z
42
+ .object({
43
+ type: zod_1.z.literal('number'),
44
+ description: zod_1.z.string().trim().optional(),
45
+ enum: zod_1.z.array(zod_1.z.number()).min(1).optional(),
46
+ })
47
+ .strict();
48
+ const OutputSchemaIntegerSchema = zod_1.z
49
+ .object({
50
+ type: zod_1.z.literal('integer'),
51
+ description: zod_1.z.string().trim().optional(),
52
+ enum: zod_1.z.array(zod_1.z.number().int()).min(1).optional(),
53
+ })
54
+ .strict();
55
+ const OutputSchemaBooleanSchema = zod_1.z
56
+ .object({
57
+ type: zod_1.z.literal('boolean'),
58
+ description: zod_1.z.string().trim().optional(),
59
+ enum: zod_1.z.array(zod_1.z.boolean()).min(1).optional(),
60
+ })
61
+ .strict();
62
+ const OutputSchemaPrimitiveSchema = zod_1.z.union([
63
+ OutputSchemaStringSchema,
64
+ OutputSchemaNumberSchema,
65
+ OutputSchemaIntegerSchema,
66
+ OutputSchemaBooleanSchema,
67
+ ]);
68
+ const OutputSchemaArraySchema = zod_1.z
69
+ .object({
70
+ type: zod_1.z.literal('array'),
71
+ description: zod_1.z.string().trim().optional(),
72
+ items: OutputSchemaPrimitiveSchema,
73
+ })
74
+ .strict();
75
+ const OutputSchemaFieldSchema = zod_1.z.union([
76
+ OutputSchemaPrimitiveSchema,
77
+ OutputSchemaArraySchema,
78
+ ]);
79
+ const OutputSchemaPropertyDescriptorSchema = zod_1.z
80
+ .object({
81
+ name: zod_1.z.string().trim().min(1),
82
+ description: zod_1.z.string().trim().optional(),
83
+ schema: OutputSchemaFieldSchema,
84
+ })
85
+ .strict();
86
+ const OutputSchemaDescriptorSchema = zod_1.z
87
+ .object({
88
+ title: zod_1.z.string().trim().optional(),
89
+ description: zod_1.z.string().trim().optional(),
90
+ properties: zod_1.z
91
+ .array(OutputSchemaPropertyDescriptorSchema)
92
+ .min(1)
93
+ .describe('Property descriptors for the Codex response. Each property name must be unique.'),
94
+ required: zod_1.z.array(zod_1.z.string().trim().min(1)).optional(),
95
+ })
96
+ .strict()
97
+ .superRefine((descriptor, ctx) => {
98
+ const seen = new Set();
99
+ for (const property of descriptor.properties) {
100
+ if (seen.has(property.name)) {
101
+ ctx.addIssue({
102
+ code: zod_1.z.ZodIssueCode.custom,
103
+ message: `Duplicate property name "${property.name}" in output_schema.`,
104
+ path: ['properties'],
105
+ });
106
+ break;
107
+ }
108
+ seen.add(property.name);
109
+ }
110
+ if (descriptor.required) {
111
+ for (const name of descriptor.required) {
112
+ if (!seen.has(name)) {
113
+ ctx.addIssue({
114
+ code: zod_1.z.ZodIssueCode.custom,
115
+ message: `Required property "${name}" must also be defined in "properties".`,
116
+ path: ['required'],
117
+ });
118
+ }
119
+ }
120
+ }
121
+ });
122
+ const codexParametersSchema = zod_1.z
123
+ .object({
124
+ inputs: zod_1.z
125
+ .array(CodexToolInputItemSchema)
126
+ .min(1, 'Codex tool requires at least one input item.')
127
+ .describe('Structured inputs appended to the Codex task. Provide at least one input item.'),
128
+ })
129
+ .strict();
130
+ function resolveDefaultCodexApiKey(options) {
131
+ if (options?.apiKey) {
132
+ return options.apiKey;
133
+ }
134
+ const envOverride = options?.env;
135
+ if (envOverride?.CODEX_API_KEY) {
136
+ return envOverride.CODEX_API_KEY;
137
+ }
138
+ if (envOverride?.OPENAI_API_KEY) {
139
+ return envOverride.OPENAI_API_KEY;
140
+ }
141
+ const env = (0, _shims_1.loadEnv)();
142
+ return env.CODEX_API_KEY ?? env.OPENAI_API_KEY;
143
+ }
144
+ function resolveCodexOptions(options) {
145
+ if (options?.apiKey) {
146
+ return options;
147
+ }
148
+ const apiKey = resolveDefaultCodexApiKey(options);
149
+ if (!apiKey) {
150
+ return options;
151
+ }
152
+ if (!options) {
153
+ return { apiKey };
154
+ }
155
+ return { ...options, apiKey };
156
+ }
157
+ function createCodexResolver(providedCodex, options) {
158
+ if (providedCodex) {
159
+ return async () => providedCodex;
160
+ }
161
+ let codexInstance = null;
162
+ return async () => {
163
+ if (!codexInstance) {
164
+ codexInstance = new codex_sdk_1.Codex(options);
165
+ }
166
+ return codexInstance;
167
+ };
168
+ }
169
+ const defaultParameters = codexParametersSchema;
170
+ /**
171
+ * Wraps the Codex SDK in a function tool that can be consumed by the Agents SDK.
172
+ *
173
+ * The tool streams Codex events, creating child spans for reasoning items, command executions,
174
+ * and MCP tool invocations. Those spans are nested under the Codex tool span automatically when
175
+ * tracing is enabled.
176
+ */
177
+ function codexTool(options = {}) {
178
+ const { name = 'codex', description = 'Executes an agentic Codex task against the current workspace.', parameters = defaultParameters, codex: providedCodex, codexOptions, defaultThreadOptions, defaultTurnOptions, outputSchema: outputSchemaOption, threadId: defaultThreadId, sandboxMode, workingDirectory, skipGitRepoCheck, persistSession = false, onStream, } = options;
179
+ const resolvedCodexOptions = resolveCodexOptions(codexOptions);
180
+ const resolveCodex = createCodexResolver(providedCodex, resolvedCodexOptions);
181
+ const validatedOutputSchema = resolveOutputSchema(outputSchemaOption);
182
+ const resolvedThreadOptions = defaultThreadOptions ||
183
+ sandboxMode ||
184
+ workingDirectory ||
185
+ typeof skipGitRepoCheck === 'boolean'
186
+ ? {
187
+ ...(defaultThreadOptions ?? {}),
188
+ ...(sandboxMode ? { sandboxMode } : {}),
189
+ ...(workingDirectory ? { workingDirectory } : {}),
190
+ ...(typeof skipGitRepoCheck === 'boolean'
191
+ ? { skipGitRepoCheck }
192
+ : {}),
193
+ }
194
+ : undefined;
195
+ let persistedThread = null;
196
+ return (0, agents_1.tool)({
197
+ name,
198
+ description,
199
+ parameters,
200
+ strict: true,
201
+ execute: async (input, runContext = new agents_1.RunContext(), details) => {
202
+ const args = normalizeParameters(input);
203
+ const codex = await resolveCodex();
204
+ const thread = persistSession
205
+ ? getOrCreatePersistedThread(codex, defaultThreadId, resolvedThreadOptions, persistedThread)
206
+ : getThread(codex, defaultThreadId, resolvedThreadOptions);
207
+ if (persistSession && !persistedThread) {
208
+ persistedThread = thread;
209
+ }
210
+ const turnOptions = buildTurnOptions(defaultTurnOptions, validatedOutputSchema);
211
+ const codexInput = buildCodexInput(args);
212
+ const streamResult = await thread.runStreamed(codexInput, turnOptions);
213
+ const { response, usage, threadId: streamedThreadId, } = await consumeEvents(streamResult, {
214
+ args,
215
+ onStream,
216
+ toolCall: details?.toolCall,
217
+ });
218
+ const resolvedThreadId = thread.id ?? streamedThreadId;
219
+ if (usage) {
220
+ const inputTokensDetails = typeof usage.cached_input_tokens === 'number'
221
+ ? { cached_input_tokens: usage.cached_input_tokens }
222
+ : undefined;
223
+ runContext.usage.add(new agents_1.Usage({
224
+ input_tokens: usage.input_tokens,
225
+ output_tokens: usage.output_tokens,
226
+ total_tokens: usage.input_tokens + usage.output_tokens,
227
+ input_tokens_details: inputTokensDetails,
228
+ requests: 1,
229
+ }));
230
+ }
231
+ return {
232
+ threadId: resolvedThreadId,
233
+ response,
234
+ usage,
235
+ };
236
+ },
237
+ needsApproval: false,
238
+ isEnabled: true,
239
+ });
240
+ }
241
+ function resolveOutputSchema(option) {
242
+ if (!option) {
243
+ return undefined;
244
+ }
245
+ if ((0, utils_1.isZodObject)(option)) {
246
+ const schema = zodJsonSchemaCompat(option);
247
+ if (!schema) {
248
+ throw new agents_1.UserError('Codex output schema must be a Zod object that can be converted to JSON Schema.');
249
+ }
250
+ return schema;
251
+ }
252
+ if (isJsonObjectSchema(option)) {
253
+ if (option.additionalProperties !== false) {
254
+ throw new agents_1.UserError('Codex output schema must set "additionalProperties" to false.');
255
+ }
256
+ return option;
257
+ }
258
+ const descriptor = OutputSchemaDescriptorSchema.parse(option);
259
+ return buildCodexOutputSchema(descriptor);
260
+ }
261
+ function buildTurnOptions(defaults, outputSchema) {
262
+ if (!defaults && !outputSchema) {
263
+ return undefined;
264
+ }
265
+ return {
266
+ ...(defaults ?? {}),
267
+ ...(outputSchema ? { outputSchema } : {}),
268
+ };
269
+ }
270
+ function normalizeParameters(params) {
271
+ const inputs = params.inputs.map((item) => item.type === 'text'
272
+ ? { type: 'text', text: item.text.trim() }
273
+ : { type: 'local_image', path: item.path.trim() });
274
+ return {
275
+ inputs: inputs && inputs.length > 0 ? inputs : undefined,
276
+ };
277
+ }
278
+ function buildCodexOutputSchema(descriptor) {
279
+ const properties = Object.fromEntries(descriptor.properties.map((property) => {
280
+ const schema = buildCodexOutputSchemaField(property.schema);
281
+ if (property.description) {
282
+ schema.description = property.description;
283
+ }
284
+ return [property.name, schema];
285
+ }));
286
+ const required = descriptor.required
287
+ ? Array.from(new Set(descriptor.required))
288
+ : undefined;
289
+ const schema = {
290
+ type: 'object',
291
+ additionalProperties: false,
292
+ properties,
293
+ };
294
+ if (required && required.length > 0) {
295
+ schema.required = required;
296
+ }
297
+ if (descriptor.title) {
298
+ schema.title = descriptor.title;
299
+ }
300
+ if (descriptor.description) {
301
+ schema.description = descriptor.description;
302
+ }
303
+ return schema;
304
+ }
305
+ function buildCodexOutputSchemaField(field) {
306
+ if (field.type === 'array') {
307
+ const schema = {
308
+ type: 'array',
309
+ items: buildCodexOutputSchemaPrimitive(field.items),
310
+ };
311
+ if (field.description) {
312
+ schema.description = field.description;
313
+ }
314
+ return schema;
315
+ }
316
+ return buildCodexOutputSchemaPrimitive(field);
317
+ }
318
+ function buildCodexOutputSchemaPrimitive(field) {
319
+ const result = {
320
+ type: field.type,
321
+ };
322
+ if (field.description) {
323
+ result.description = field.description;
324
+ }
325
+ if (field.enum) {
326
+ result.enum = field.enum;
327
+ }
328
+ return result;
329
+ }
330
+ function isJsonObjectSchema(value) {
331
+ if (!value || typeof value !== 'object') {
332
+ return false;
333
+ }
334
+ const record = value;
335
+ return record.type === 'object';
336
+ }
337
+ const JSON_SCHEMA_DRAFT_07 = 'http://json-schema.org/draft-07/schema#';
338
+ const OPTIONAL_WRAPPERS = new Set(['optional']);
339
+ const DECORATOR_WRAPPERS = new Set([
340
+ 'brand',
341
+ 'branded',
342
+ 'catch',
343
+ 'default',
344
+ 'effects',
345
+ 'pipeline',
346
+ 'pipe',
347
+ 'prefault',
348
+ 'readonly',
349
+ 'refinement',
350
+ 'transform',
351
+ ]);
352
+ const SIMPLE_TYPE_MAPPING = {
353
+ string: { type: 'string' },
354
+ number: { type: 'number' },
355
+ bigint: { type: 'integer' },
356
+ boolean: { type: 'boolean' },
357
+ date: { type: 'string', format: 'date-time' },
358
+ };
359
+ function readZodDefinition(input) {
360
+ if (typeof input !== 'object' || input === null) {
361
+ return undefined;
362
+ }
363
+ const candidate = input;
364
+ return candidate._zod?.def || candidate._def || candidate.def;
365
+ }
366
+ function readZodType(input) {
367
+ const def = readZodDefinition(input);
368
+ if (!def) {
369
+ return undefined;
370
+ }
371
+ const rawType = (typeof def.typeName === 'string' && def.typeName) ||
372
+ (typeof def.type === 'string' && def.type);
373
+ if (typeof rawType !== 'string') {
374
+ return undefined;
375
+ }
376
+ const lower = rawType.toLowerCase();
377
+ return lower.startsWith('zod') ? lower.slice(3) : lower;
378
+ }
379
+ function zodJsonSchemaCompat(input) {
380
+ const schema = buildObjectSchema(input);
381
+ if (!schema) {
382
+ return undefined;
383
+ }
384
+ if (!Array.isArray(schema.required)) {
385
+ schema.required = [];
386
+ }
387
+ if (typeof schema.additionalProperties === 'undefined') {
388
+ schema.additionalProperties = false;
389
+ }
390
+ if (typeof schema.$schema !== 'string') {
391
+ schema.$schema = JSON_SCHEMA_DRAFT_07;
392
+ }
393
+ return schema;
394
+ }
395
+ function buildObjectSchema(value) {
396
+ const shape = readShape(value);
397
+ if (!shape) {
398
+ return undefined;
399
+ }
400
+ const properties = {};
401
+ const required = [];
402
+ for (const [key, field] of Object.entries(shape)) {
403
+ const { schema, optional } = convertProperty(field);
404
+ if (!schema) {
405
+ return undefined;
406
+ }
407
+ properties[key] = schema;
408
+ if (!optional) {
409
+ required.push(key);
410
+ }
411
+ }
412
+ return { type: 'object', properties, required, additionalProperties: false };
413
+ }
414
+ function convertProperty(value) {
415
+ let current = unwrapDecorators(value);
416
+ let optional = false;
417
+ while (OPTIONAL_WRAPPERS.has(readZodType(current) ?? '')) {
418
+ optional = true;
419
+ const def = readZodDefinition(current);
420
+ const next = unwrapDecorators(def?.innerType);
421
+ if (!next || next === current) {
422
+ break;
423
+ }
424
+ current = next;
425
+ }
426
+ return { schema: convertSchema(current), optional };
427
+ }
428
+ function convertSchema(value) {
429
+ if (value === undefined) {
430
+ return undefined;
431
+ }
432
+ const unwrapped = unwrapDecorators(value);
433
+ const type = readZodType(unwrapped);
434
+ const def = readZodDefinition(unwrapped);
435
+ if (!type) {
436
+ return undefined;
437
+ }
438
+ if (type in SIMPLE_TYPE_MAPPING) {
439
+ return SIMPLE_TYPE_MAPPING[type];
440
+ }
441
+ switch (type) {
442
+ case 'object':
443
+ return buildObjectSchema(unwrapped);
444
+ case 'array':
445
+ return buildArraySchema(def);
446
+ case 'tuple':
447
+ return buildTupleSchema(def);
448
+ case 'union':
449
+ return buildUnionSchema(def);
450
+ case 'intersection':
451
+ return buildIntersectionSchema(def);
452
+ case 'literal':
453
+ return buildLiteral(def);
454
+ case 'enum':
455
+ case 'nativeenum':
456
+ return buildEnum(def);
457
+ case 'record':
458
+ return buildRecordSchema(def);
459
+ case 'map':
460
+ return buildMapSchema(def);
461
+ case 'set':
462
+ return buildSetSchema(def);
463
+ case 'nullable':
464
+ return buildNullableSchema(def);
465
+ default:
466
+ return undefined;
467
+ }
468
+ }
469
+ function buildArraySchema(def) {
470
+ const items = convertSchema(extractFirst(def, 'element', 'items', 'type'));
471
+ return items ? { type: 'array', items } : undefined;
472
+ }
473
+ function buildTupleSchema(def) {
474
+ const items = coerceArray(def?.items)
475
+ .map((item) => convertSchema(item))
476
+ .filter(Boolean);
477
+ if (!items.length) {
478
+ return undefined;
479
+ }
480
+ const schema = {
481
+ type: 'array',
482
+ items,
483
+ minItems: items.length,
484
+ };
485
+ if (!def?.rest) {
486
+ schema.maxItems = items.length;
487
+ }
488
+ return schema;
489
+ }
490
+ function buildUnionSchema(def) {
491
+ const options = coerceArray(def?.options ?? def?.schemas)
492
+ .map((option) => convertSchema(option))
493
+ .filter(Boolean);
494
+ return options.length ? { anyOf: options } : undefined;
495
+ }
496
+ function buildIntersectionSchema(def) {
497
+ const left = convertSchema(def?.left);
498
+ const right = convertSchema(def?.right);
499
+ return left && right ? { allOf: [left, right] } : undefined;
500
+ }
501
+ function buildRecordSchema(def) {
502
+ const valueSchema = convertSchema(def?.valueType ?? def?.values);
503
+ return valueSchema
504
+ ? { type: 'object', additionalProperties: valueSchema }
505
+ : undefined;
506
+ }
507
+ function buildMapSchema(def) {
508
+ const valueSchema = convertSchema(def?.valueType ?? def?.values);
509
+ return valueSchema ? { type: 'array', items: valueSchema } : undefined;
510
+ }
511
+ function buildSetSchema(def) {
512
+ const valueSchema = convertSchema(def?.valueType);
513
+ return valueSchema
514
+ ? { type: 'array', items: valueSchema, uniqueItems: true }
515
+ : undefined;
516
+ }
517
+ function buildNullableSchema(def) {
518
+ const inner = convertSchema(def?.innerType ?? def?.type);
519
+ return inner ? { anyOf: [inner, { type: 'null' }] } : undefined;
520
+ }
521
+ function unwrapDecorators(value) {
522
+ let current = value;
523
+ while (DECORATOR_WRAPPERS.has(readZodType(current) ?? '')) {
524
+ const def = readZodDefinition(current);
525
+ const next = def?.innerType ??
526
+ def?.schema ??
527
+ def?.base ??
528
+ def?.type ??
529
+ def?.wrapped ??
530
+ def?.underlying;
531
+ if (!next || next === current) {
532
+ return current;
533
+ }
534
+ current = next;
535
+ }
536
+ return current;
537
+ }
538
+ function extractFirst(def, ...keys) {
539
+ if (!def) {
540
+ return undefined;
541
+ }
542
+ for (const key of keys) {
543
+ if (key in def && def[key] !== undefined) {
544
+ return def[key];
545
+ }
546
+ }
547
+ return undefined;
548
+ }
549
+ function coerceArray(value) {
550
+ if (Array.isArray(value)) {
551
+ return value;
552
+ }
553
+ return value === undefined ? [] : [value];
554
+ }
555
+ function buildLiteral(def) {
556
+ if (!def) {
557
+ return undefined;
558
+ }
559
+ const literal = extractFirst(def, 'value', 'literal');
560
+ if (literal === undefined) {
561
+ return undefined;
562
+ }
563
+ return {
564
+ const: literal,
565
+ type: literal === null ? 'null' : typeof literal,
566
+ };
567
+ }
568
+ function buildEnum(def) {
569
+ if (!def) {
570
+ return undefined;
571
+ }
572
+ if (Array.isArray(def.values)) {
573
+ return { enum: def.values };
574
+ }
575
+ if (Array.isArray(def.options)) {
576
+ return { enum: def.options };
577
+ }
578
+ if (def.values && typeof def.values === 'object') {
579
+ return { enum: Object.values(def.values) };
580
+ }
581
+ if (def.enum && typeof def.enum === 'object') {
582
+ return { enum: Object.values(def.enum) };
583
+ }
584
+ return undefined;
585
+ }
586
+ function readShape(input) {
587
+ if (typeof input !== 'object' || input === null) {
588
+ return undefined;
589
+ }
590
+ const candidate = input;
591
+ if (candidate.shape && typeof candidate.shape === 'object') {
592
+ return candidate.shape;
593
+ }
594
+ if (typeof candidate.shape === 'function') {
595
+ try {
596
+ return candidate.shape();
597
+ }
598
+ catch (_error) {
599
+ return undefined;
600
+ }
601
+ }
602
+ const def = readZodDefinition(candidate);
603
+ const shape = def?.shape;
604
+ if (shape && typeof shape === 'object') {
605
+ return shape;
606
+ }
607
+ if (typeof shape === 'function') {
608
+ try {
609
+ return shape();
610
+ }
611
+ catch (_error) {
612
+ return undefined;
613
+ }
614
+ }
615
+ return undefined;
616
+ }
617
+ function getThread(codex, threadId, defaults) {
618
+ if (threadId) {
619
+ return codex.resumeThread(threadId, defaults);
620
+ }
621
+ return codex.startThread(defaults);
622
+ }
623
+ function getOrCreatePersistedThread(codex, threadId, threadOptions, existingThread) {
624
+ if (existingThread) {
625
+ if (threadId) {
626
+ const existingId = existingThread.id;
627
+ if (existingId && existingId !== threadId) {
628
+ throw new agents_1.UserError('Codex tool is configured with persistSession=true and already has an active thread.');
629
+ }
630
+ }
631
+ return existingThread;
632
+ }
633
+ return getThread(codex, threadId, threadOptions);
634
+ }
635
+ function buildCodexInput(args) {
636
+ if (args.inputs && args.inputs.length > 0) {
637
+ return args.inputs;
638
+ }
639
+ return '';
640
+ }
641
+ async function emitStreamEvent(handler, payload) {
642
+ if (!handler) {
643
+ return;
644
+ }
645
+ await Promise.allSettled([Promise.resolve().then(() => handler(payload))]);
646
+ }
647
+ async function consumeEvents({ events }, options) {
648
+ const { args, onStream, toolCall } = options;
649
+ const activeSpans = new Map();
650
+ let finalResponse = '';
651
+ let usage = null;
652
+ let threadId = null;
653
+ try {
654
+ for await (const event of events) {
655
+ if (event.type === 'thread.started') {
656
+ threadId = event.thread_id;
657
+ }
658
+ await emitStreamEvent(onStream, {
659
+ event,
660
+ threadId,
661
+ toolCall,
662
+ });
663
+ switch (event.type) {
664
+ case 'item.started':
665
+ handleItemStarted(event.item, activeSpans);
666
+ break;
667
+ case 'item.updated':
668
+ handleItemUpdated(event.item, activeSpans);
669
+ break;
670
+ case 'item.completed':
671
+ handleItemCompleted(event.item, activeSpans);
672
+ if (event.item.type === 'agent_message' &&
673
+ typeof event.item.text === 'string') {
674
+ finalResponse = event.item.text;
675
+ }
676
+ break;
677
+ case 'turn.completed':
678
+ usage = event.usage ?? null;
679
+ break;
680
+ case 'turn.failed':
681
+ throw new agents_1.UserError(`Codex turn failed${event.error?.message ? `: ${event.error.message}` : ''}`);
682
+ case 'error':
683
+ throw new agents_1.UserError(`Codex stream error: ${event.message}`);
684
+ default:
685
+ // ignore other events
686
+ break;
687
+ }
688
+ }
689
+ }
690
+ finally {
691
+ for (const span of activeSpans.values()) {
692
+ span.end();
693
+ }
694
+ activeSpans.clear();
695
+ }
696
+ if (!finalResponse) {
697
+ finalResponse = buildDefaultResponse(args);
698
+ }
699
+ return { response: finalResponse, usage, threadId };
700
+ }
701
+ function handleItemStarted(item, spans) {
702
+ if (isCommandExecutionItem(item)) {
703
+ const span = (0, agents_1.createCustomSpan)({
704
+ data: {
705
+ name: 'Codex command execution',
706
+ data: buildCommandSpanData(item),
707
+ },
708
+ });
709
+ span.start();
710
+ spans.set(item.id, span);
711
+ return;
712
+ }
713
+ if (isFileChangeItem(item)) {
714
+ const span = (0, agents_1.createCustomSpan)({
715
+ data: {
716
+ name: 'Codex file change',
717
+ data: buildFileChangeSpanData(item),
718
+ },
719
+ });
720
+ span.start();
721
+ spans.set(item.id, span);
722
+ return;
723
+ }
724
+ if (isMcpToolCallItem(item)) {
725
+ const span = (0, agents_1.createCustomSpan)({
726
+ data: {
727
+ name: `Codex MCP tool call`,
728
+ data: buildMcpToolSpanData(item),
729
+ },
730
+ });
731
+ span.start();
732
+ spans.set(item.id, span);
733
+ return;
734
+ }
735
+ if (isWebSearchItem(item)) {
736
+ const span = (0, agents_1.createCustomSpan)({
737
+ data: {
738
+ name: 'Codex web search',
739
+ data: buildWebSearchSpanData(item),
740
+ },
741
+ });
742
+ span.start();
743
+ spans.set(item.id, span);
744
+ return;
745
+ }
746
+ if (isTodoListItem(item)) {
747
+ const span = (0, agents_1.createCustomSpan)({
748
+ data: {
749
+ name: 'Codex todo list',
750
+ data: buildTodoListSpanData(item),
751
+ },
752
+ });
753
+ span.start();
754
+ spans.set(item.id, span);
755
+ return;
756
+ }
757
+ if (isErrorItem(item)) {
758
+ const span = (0, agents_1.createCustomSpan)({
759
+ data: {
760
+ name: 'Codex error',
761
+ data: buildErrorSpanData(item),
762
+ },
763
+ });
764
+ span.start();
765
+ spans.set(item.id, span);
766
+ return;
767
+ }
768
+ if (isReasoningItem(item)) {
769
+ const span = (0, agents_1.createCustomSpan)({
770
+ data: {
771
+ name: 'Codex reasoning',
772
+ data: buildReasoningSpanData(item),
773
+ },
774
+ });
775
+ span.start();
776
+ spans.set(item.id, span);
777
+ }
778
+ }
779
+ function handleItemUpdated(item, spans) {
780
+ const span = item.id ? spans.get(item.id) : undefined;
781
+ if (!span) {
782
+ return;
783
+ }
784
+ if (isCommandExecutionItem(item)) {
785
+ updateCommandSpan(span, item);
786
+ }
787
+ else if (isFileChangeItem(item)) {
788
+ updateFileChangeSpan(span, item);
789
+ }
790
+ else if (isMcpToolCallItem(item)) {
791
+ updateMcpToolSpan(span, item);
792
+ }
793
+ else if (isWebSearchItem(item)) {
794
+ updateWebSearchSpan(span, item);
795
+ }
796
+ else if (isTodoListItem(item)) {
797
+ updateTodoListSpan(span, item);
798
+ }
799
+ else if (isErrorItem(item)) {
800
+ updateErrorSpan(span, item);
801
+ }
802
+ else if (isReasoningItem(item)) {
803
+ updateReasoningSpan(span, item);
804
+ }
805
+ }
806
+ function handleItemCompleted(item, spans) {
807
+ const span = item.id ? spans.get(item.id) : undefined;
808
+ if (!span) {
809
+ return;
810
+ }
811
+ if (isCommandExecutionItem(item)) {
812
+ updateCommandSpan(span, item);
813
+ if (item.status === 'failed') {
814
+ span.setError({
815
+ message: 'Codex command execution failed.',
816
+ data: {
817
+ exitCode: item.exit_code ?? null,
818
+ output: item.aggregated_output ?? '',
819
+ },
820
+ });
821
+ }
822
+ }
823
+ else if (isFileChangeItem(item)) {
824
+ updateFileChangeSpan(span, item);
825
+ if (item.status === 'failed') {
826
+ span.setError({
827
+ message: 'Codex file change failed.',
828
+ data: {
829
+ changes: item.changes,
830
+ },
831
+ });
832
+ }
833
+ }
834
+ else if (isMcpToolCallItem(item)) {
835
+ updateMcpToolSpan(span, item);
836
+ if (item.status === 'failed' && item.error?.message) {
837
+ span.setError({
838
+ message: item.error.message,
839
+ });
840
+ }
841
+ }
842
+ else if (isWebSearchItem(item)) {
843
+ updateWebSearchSpan(span, item);
844
+ }
845
+ else if (isTodoListItem(item)) {
846
+ updateTodoListSpan(span, item);
847
+ }
848
+ else if (isErrorItem(item)) {
849
+ updateErrorSpan(span, item);
850
+ span.setError({
851
+ message: item.message,
852
+ });
853
+ }
854
+ else if (isReasoningItem(item)) {
855
+ updateReasoningSpan(span, item);
856
+ }
857
+ span.end();
858
+ spans.delete(item.id);
859
+ }
860
+ function updateCommandSpan(span, item) {
861
+ replaceSpanData(span, buildCommandSpanData(item));
862
+ }
863
+ function updateFileChangeSpan(span, item) {
864
+ replaceSpanData(span, buildFileChangeSpanData(item));
865
+ }
866
+ function updateMcpToolSpan(span, item) {
867
+ replaceSpanData(span, buildMcpToolSpanData(item));
868
+ }
869
+ function updateWebSearchSpan(span, item) {
870
+ replaceSpanData(span, buildWebSearchSpanData(item));
871
+ }
872
+ function updateTodoListSpan(span, item) {
873
+ replaceSpanData(span, buildTodoListSpanData(item));
874
+ }
875
+ function updateErrorSpan(span, item) {
876
+ replaceSpanData(span, buildErrorSpanData(item));
877
+ }
878
+ function updateReasoningSpan(span, item) {
879
+ replaceSpanData(span, buildReasoningSpanData(item));
880
+ }
881
+ function buildDefaultResponse(args) {
882
+ const inputSummary = args.inputs?.length ? 'with inputs.' : 'with no inputs.';
883
+ return `Codex task completed ${inputSummary}`;
884
+ }
885
+ function replaceSpanData(span, next) {
886
+ const data = span.spanData.data;
887
+ for (const key of Object.keys(data)) {
888
+ delete data[key];
889
+ }
890
+ Object.assign(data, next);
891
+ }
892
+ function buildCommandSpanData(item) {
893
+ const data = {
894
+ command: item.command,
895
+ status: item.status,
896
+ exitCode: item.exit_code ?? null,
897
+ };
898
+ const output = item.aggregated_output ?? '';
899
+ applyTruncatedField(data, 'output', output, {
900
+ maxLength: MAX_SPAN_TEXT_LENGTH,
901
+ mode: 'tail',
902
+ });
903
+ return data;
904
+ }
905
+ function buildFileChangeSpanData(item) {
906
+ const changes = item.changes.slice(0, MAX_SPAN_LIST_ITEMS).map((change) => ({
907
+ path: change.path,
908
+ kind: change.kind,
909
+ }));
910
+ const data = {
911
+ changes,
912
+ status: item.status,
913
+ };
914
+ if (item.changes.length > changes.length) {
915
+ data.changes_truncated = true;
916
+ data.changes_total = item.changes.length;
917
+ }
918
+ return data;
919
+ }
920
+ function buildMcpToolSpanData(item) {
921
+ const data = {
922
+ server: item.server,
923
+ tool: item.tool,
924
+ status: item.status,
925
+ };
926
+ if (typeof item.arguments !== 'undefined') {
927
+ applyTruncatedField(data, 'arguments', (0, utils_1.toSmartString)(item.arguments), {
928
+ maxLength: MAX_SPAN_TEXT_LENGTH,
929
+ mode: 'head',
930
+ });
931
+ }
932
+ if (item.result) {
933
+ const resultSummary = {
934
+ content_items: Array.isArray(item.result.content)
935
+ ? item.result.content.length
936
+ : 0,
937
+ };
938
+ if (typeof item.result.structured_content !== 'undefined') {
939
+ applyTruncatedField(resultSummary, 'structured_content', (0, utils_1.toSmartString)(item.result.structured_content), { maxLength: MAX_SPAN_TEXT_LENGTH, mode: 'head' });
940
+ }
941
+ data.result = resultSummary;
942
+ }
943
+ if (item.error?.message) {
944
+ applyTruncatedField(data, 'error', item.error.message, {
945
+ maxLength: MAX_SPAN_TEXT_LENGTH,
946
+ mode: 'head',
947
+ });
948
+ }
949
+ return data;
950
+ }
951
+ function buildWebSearchSpanData(item) {
952
+ const data = {};
953
+ applyTruncatedField(data, 'query', item.query, {
954
+ maxLength: MAX_SPAN_TEXT_LENGTH,
955
+ mode: 'head',
956
+ });
957
+ return data;
958
+ }
959
+ function buildTodoListSpanData(item) {
960
+ const items = item.items.slice(0, MAX_SPAN_LIST_ITEMS).map((entry) => {
961
+ const result = { completed: entry.completed };
962
+ applyTruncatedField(result, 'text', entry.text, {
963
+ maxLength: MAX_TODO_TEXT_LENGTH,
964
+ mode: 'head',
965
+ });
966
+ return result;
967
+ });
968
+ const data = { items };
969
+ if (item.items.length > items.length) {
970
+ data.items_truncated = true;
971
+ data.items_total = item.items.length;
972
+ }
973
+ return data;
974
+ }
975
+ function buildErrorSpanData(item) {
976
+ const data = {};
977
+ applyTruncatedField(data, 'message', item.message, {
978
+ maxLength: MAX_SPAN_TEXT_LENGTH,
979
+ mode: 'head',
980
+ });
981
+ return data;
982
+ }
983
+ function buildReasoningSpanData(item) {
984
+ const data = {};
985
+ applyTruncatedField(data, 'text', item.text, {
986
+ maxLength: MAX_SPAN_TEXT_LENGTH,
987
+ mode: 'head',
988
+ });
989
+ return data;
990
+ }
991
+ function applyTruncatedField(target, field, value, options) {
992
+ const { text, truncated, length } = truncateText(value, options);
993
+ target[field] = text;
994
+ if (truncated) {
995
+ target[`${field}_truncated`] = true;
996
+ target[`${field}_length`] = length;
997
+ }
998
+ }
999
+ function truncateText(value, { maxLength, mode }) {
1000
+ if (value.length <= maxLength) {
1001
+ return { text: value, truncated: false, length: value.length };
1002
+ }
1003
+ if (mode === 'tail') {
1004
+ return {
1005
+ text: `…${value.slice(-maxLength)}`,
1006
+ truncated: true,
1007
+ length: value.length,
1008
+ };
1009
+ }
1010
+ return {
1011
+ text: `${value.slice(0, maxLength)}…`,
1012
+ truncated: true,
1013
+ length: value.length,
1014
+ };
1015
+ }
1016
+ function isCommandExecutionItem(item) {
1017
+ return item?.type === 'command_execution';
1018
+ }
1019
+ function isFileChangeItem(item) {
1020
+ return item?.type === 'file_change';
1021
+ }
1022
+ function isMcpToolCallItem(item) {
1023
+ return item?.type === 'mcp_tool_call';
1024
+ }
1025
+ function isWebSearchItem(item) {
1026
+ return item?.type === 'web_search';
1027
+ }
1028
+ function isTodoListItem(item) {
1029
+ return item?.type === 'todo_list';
1030
+ }
1031
+ function isErrorItem(item) {
1032
+ return item?.type === 'error';
1033
+ }
1034
+ function isReasoningItem(item) {
1035
+ return item?.type === 'reasoning';
1036
+ }
1037
+ //# sourceMappingURL=index.js.map