coding-agents-sdk 0.0.1 → 0.2.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.
Files changed (41) hide show
  1. package/README.md +242 -0
  2. package/dist/Agent-D8WkUilj.mjs +262 -0
  3. package/dist/SdkAgent-B47mJiIE.mjs +38 -0
  4. package/dist/adapters/claude-code-cli/index.d.mts +2 -0
  5. package/dist/adapters/claude-code-cli/index.mjs +490 -0
  6. package/dist/adapters/claude-code-sdk/index.d.mts +2 -0
  7. package/dist/adapters/claude-code-sdk/index.mjs +483 -0
  8. package/dist/adapters/codex-cli/index.d.mts +2 -0
  9. package/dist/adapters/codex-cli/index.mjs +626 -0
  10. package/dist/adapters/codex-sdk/index.d.mts +2 -0
  11. package/dist/adapters/codex-sdk/index.mjs +286 -0
  12. package/dist/adapters/gemini-cli/index.d.mts +2 -0
  13. package/dist/adapters/gemini-cli/index.mjs +292 -0
  14. package/dist/classify-error-pL6jeu4T.mjs +456 -0
  15. package/dist/container/index.d.mts +2 -0
  16. package/dist/container/index.mjs +24 -0
  17. package/dist/container-2UmPZ0CI.mjs +22 -0
  18. package/dist/container-CHxKIonn.mjs +440 -0
  19. package/dist/container-D2Z0ITDJ.mjs +22 -0
  20. package/dist/diff-De8d3MVb.mjs +333 -0
  21. package/dist/errors-BAmHDQu8.mjs +45 -0
  22. package/dist/events-nxuRbYIu.d.mts +239 -0
  23. package/dist/index-B3YqrgIp.d.mts +45 -0
  24. package/dist/index-ByAOGMUM.d.mts +224 -0
  25. package/dist/index-C3ZxLAd0.d.mts +315 -0
  26. package/dist/index-CFpNOmdA.d.mts +145 -0
  27. package/dist/index-dRVpEAr8.d.mts +39 -0
  28. package/dist/index-nzo1sBiK.d.mts +110 -0
  29. package/dist/index.d.mts +16 -0
  30. package/dist/index.mjs +61 -0
  31. package/dist/oci-DMZZQZ47.mjs +438 -0
  32. package/dist/schemas/index.d.mts +2 -0
  33. package/dist/schemas/index.mjs +2 -0
  34. package/dist/schemas-DwD4pwJB.mjs +96 -0
  35. package/dist/spawner-Bw9UBEGX.mjs +54 -0
  36. package/dist/structured-output-BHtr_zpz.mjs +19 -0
  37. package/dist/types-Cb_EXIEe.d.mts +177 -0
  38. package/dist/types-aNMD8h3x.mjs +19 -0
  39. package/dist/util-B4RQZkKr.mjs +77 -0
  40. package/package.json +86 -9
  41. package/index.js +0 -7
@@ -0,0 +1,626 @@
1
+ import { n as AgentValidationError } from "../../types-aNMD8h3x.mjs";
2
+ import { a as toArray, i as sumTokens, n as isRecord, r as parseJsonResponseText } from "../../util-B4RQZkKr.mjs";
3
+ import { c as getInputText, l as toTextPart, o as createAgentEvent, s as createEventParser } from "../../classify-error-pL6jeu4T.mjs";
4
+ import { t as Agent } from "../../Agent-D8WkUilj.mjs";
5
+ import { z } from "zod/v4";
6
+ import { mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
7
+ import { tmpdir } from "node:os";
8
+ import { join } from "node:path";
9
+ //#region src/adapters/codex-cli/events/schemas.ts
10
+ const codexEventSchema = z.object({ type: z.string() }).passthrough();
11
+ const codexUsageSchema = z.object({
12
+ input_tokens: z.number().optional(),
13
+ cached_input_tokens: z.number().optional(),
14
+ output_tokens: z.number().optional(),
15
+ reasoning_output_tokens: z.number().optional(),
16
+ total_tokens: z.number().optional()
17
+ }).passthrough();
18
+ const codexThreadStartedEventSchema = z.object({
19
+ type: z.literal("thread.started"),
20
+ thread_id: z.string()
21
+ }).passthrough();
22
+ const codexTurnCompletedEventSchema = z.object({
23
+ type: z.literal("turn.completed"),
24
+ usage: codexUsageSchema.optional(),
25
+ last_agent_message: z.string().optional(),
26
+ duration_ms: z.number().optional(),
27
+ num_turns: z.number().optional()
28
+ }).passthrough();
29
+ const codexTurnFailedEventSchema = z.object({
30
+ type: z.literal("turn.failed"),
31
+ usage: codexUsageSchema.optional(),
32
+ last_agent_message: z.string().optional(),
33
+ duration_ms: z.number().optional(),
34
+ num_turns: z.number().optional(),
35
+ message: z.string().optional(),
36
+ error: z.unknown().optional()
37
+ }).passthrough();
38
+ const codexItemSchema = z.object({
39
+ id: z.string(),
40
+ type: z.string()
41
+ }).passthrough();
42
+ const codexItemStartedEventSchema = z.object({
43
+ type: z.literal("item.started"),
44
+ item: codexItemSchema
45
+ }).passthrough();
46
+ const codexItemUpdatedEventSchema = z.object({
47
+ type: z.literal("item.updated"),
48
+ item: codexItemSchema
49
+ }).passthrough();
50
+ const codexItemCompletedEventSchema = z.object({
51
+ type: z.literal("item.completed"),
52
+ item: codexItemSchema
53
+ }).passthrough();
54
+ const codexErrorEventSchema = z.object({
55
+ type: z.literal("error"),
56
+ message: z.string().optional(),
57
+ error: z.unknown().optional()
58
+ }).passthrough();
59
+ //#endregion
60
+ //#region src/adapters/codex-cli/events/mappers.ts
61
+ const asRecord = (value) => {
62
+ return isRecord(value) ? value : void 0;
63
+ };
64
+ const getValue = (record, keys) => {
65
+ if (!record) return void 0;
66
+ for (const key of keys) if (key in record) return record[key];
67
+ };
68
+ const getString = (record, keys) => {
69
+ const value = getValue(record, keys);
70
+ return typeof value === "string" ? value : void 0;
71
+ };
72
+ const getNumber = (record, keys) => {
73
+ const value = getValue(record, keys);
74
+ return typeof value === "number" ? value : void 0;
75
+ };
76
+ const getCompactObject = (value) => {
77
+ const entries = Object.entries(value).filter(([, entry]) => entry !== void 0);
78
+ if (entries.length === 0) return;
79
+ return Object.fromEntries(entries);
80
+ };
81
+ const normalizeItemType = (value) => {
82
+ return value.replace(/([\da-z])([A-Z])/g, "$1_$2").toLowerCase();
83
+ };
84
+ const getErrorMessage = (value, fallback) => {
85
+ if (typeof value === "string" && value.trim() !== "") return value;
86
+ const record = asRecord(value);
87
+ if (!record) return fallback;
88
+ return getString(record, [
89
+ "message",
90
+ "error",
91
+ "status_message"
92
+ ]) ?? getString(asRecord(record.additional_details), ["message"]) ?? fallback;
93
+ };
94
+ const toStats = (event) => {
95
+ const usage = asRecord(event.usage);
96
+ const inputTokens = getNumber(usage, ["input_tokens"]);
97
+ const cacheReadInputTokens = getNumber(usage, ["cached_input_tokens"]);
98
+ const outputTokens = getNumber(usage, ["output_tokens"]);
99
+ const reasoningOutputTokens = getNumber(usage, ["reasoning_output_tokens"]);
100
+ const totalTokens = getNumber(usage, ["total_tokens"]) ?? sumTokens(inputTokens, cacheReadInputTokens, outputTokens, reasoningOutputTokens);
101
+ return {
102
+ durationMs: getNumber(event, ["duration_ms", "durationMs"]) ?? 0,
103
+ apiDurationMs: getNumber(event, ["duration_ms", "durationMs"]) ?? 0,
104
+ turns: getNumber(event, ["num_turns", "numTurns"]) ?? 1,
105
+ costUsd: 0,
106
+ inputTokens,
107
+ cacheReadInputTokens,
108
+ outputTokens,
109
+ totalTokens
110
+ };
111
+ };
112
+ const getCommandToolRecord = (item) => ({
113
+ toolName: "Bash",
114
+ input: getCompactObject({
115
+ command: getString(item, ["command"]),
116
+ cwd: getString(item, ["cwd", "working_directory"]),
117
+ parsedCommand: getValue(item, ["parsed_cmd", "parsedCommand"])
118
+ })
119
+ });
120
+ const getMcpToolRecord = (item) => {
121
+ const toolName = getString(item, ["tool", "tool_name"]) ?? "mcp_tool_call";
122
+ const server = getString(item, ["server"]);
123
+ const argumentsValue = getValue(item, [
124
+ "arguments",
125
+ "invocation",
126
+ "input"
127
+ ]);
128
+ return {
129
+ toolName,
130
+ input: server === void 0 ? argumentsValue : getCompactObject({
131
+ server,
132
+ arguments: argumentsValue
133
+ })
134
+ };
135
+ };
136
+ const getWebSearchToolRecord = (item) => ({
137
+ toolName: "WebSearch",
138
+ input: getCompactObject({
139
+ query: getString(item, ["query"]),
140
+ action: getValue(item, ["action"])
141
+ })
142
+ });
143
+ const getToolErrorState = (item) => {
144
+ const status = getString(item, ["status"]);
145
+ const exitCode = getNumber(item, ["exit_code", "exitCode"]);
146
+ const error = getString(item, ["error"]) ?? getString(asRecord(item.result), ["error"]);
147
+ return {
148
+ isError: status === "error" || status === "failed" || status === "errored" || status === "interrupted" || exitCode !== void 0 && exitCode !== 0 || error !== void 0,
149
+ error
150
+ };
151
+ };
152
+ const mapThreadStartedEvent = (event) => ({
153
+ events: [],
154
+ sessionId: event.thread_id
155
+ });
156
+ const mapTurnCompletedEvent = (event, context) => {
157
+ const state = {
158
+ stats: toStats(event),
159
+ status: "completed"
160
+ };
161
+ if (event.last_agent_message !== void 0) state.output = { text: event.last_agent_message };
162
+ if (context.schemaRequested && event.last_agent_message) try {
163
+ state.output = {
164
+ ...state.output,
165
+ value: parseJsonResponseText(event.last_agent_message)
166
+ };
167
+ } catch {}
168
+ return {
169
+ events: [],
170
+ state
171
+ };
172
+ };
173
+ const mapTurnFailedEvent = (event) => ({
174
+ events: [],
175
+ state: {
176
+ stats: toStats(event),
177
+ status: "failed",
178
+ output: event.last_agent_message === void 0 ? void 0 : { text: event.last_agent_message },
179
+ error: {
180
+ kind: "provider",
181
+ message: getErrorMessage(event.error ?? event.message, "Codex turn failed.")
182
+ }
183
+ }
184
+ });
185
+ const mapErrorEvent = (event) => ({
186
+ events: [],
187
+ state: {
188
+ status: "failed",
189
+ error: {
190
+ kind: "provider",
191
+ message: getErrorMessage(event.error ?? event.message, "Codex emitted an error event.")
192
+ }
193
+ }
194
+ });
195
+ const mapToolCallStart = (item, context, toolRecord, options) => {
196
+ const toolCallId = getString(item, ["id"]);
197
+ if (!toolCallId) return { events: [] };
198
+ return {
199
+ events: [createAgentEvent(context.runId, "tool-call", {
200
+ sessionId: context.sessionId,
201
+ model: options.model ?? null,
202
+ toolCallId,
203
+ toolName: toolRecord.toolName,
204
+ input: toolRecord.input
205
+ })],
206
+ toolCalls: [{
207
+ toolCallId,
208
+ toolName: toolRecord.toolName,
209
+ input: toolRecord.input
210
+ }]
211
+ };
212
+ };
213
+ const getCommandOutput = (item) => getValue(item, [
214
+ "aggregated_output",
215
+ "aggregatedOutput",
216
+ "output",
217
+ "result",
218
+ "text"
219
+ ]) ?? "";
220
+ const getMcpOutput = (item) => getValue(item, ["result", "output"]) ?? getString(item, ["error"]) ?? "";
221
+ const getWebSearchOutput = (item) => getValue(item, [
222
+ "results",
223
+ "result",
224
+ "action"
225
+ ]) ?? "";
226
+ const mapToolResultCompletion = (item, context, toolRecord, output, options) => {
227
+ const toolCallId = getString(item, ["id"]);
228
+ if (!toolCallId) return { events: [] };
229
+ const priorToolCall = context.toolCalls.get(toolCallId);
230
+ const resolvedTool = priorToolCall ?? toolRecord;
231
+ const errorState = getToolErrorState(item);
232
+ const events = [];
233
+ const toolCalls = [];
234
+ if (!priorToolCall) {
235
+ events.push(createAgentEvent(context.runId, "tool-call", {
236
+ sessionId: context.sessionId,
237
+ model: options.model ?? null,
238
+ toolCallId,
239
+ toolName: toolRecord.toolName,
240
+ input: toolRecord.input
241
+ }));
242
+ toolCalls.push({
243
+ toolCallId,
244
+ toolName: toolRecord.toolName,
245
+ input: toolRecord.input
246
+ });
247
+ }
248
+ events.push(createAgentEvent(context.runId, "tool-result", {
249
+ sessionId: context.sessionId,
250
+ toolCallId,
251
+ toolName: resolvedTool.toolName,
252
+ input: resolvedTool.input,
253
+ output,
254
+ isError: errorState.isError || void 0,
255
+ error: errorState.error
256
+ }));
257
+ return {
258
+ events,
259
+ toolCalls
260
+ };
261
+ };
262
+ const getReasoningText = (item) => {
263
+ const directText = getString(item, [
264
+ "summary_text",
265
+ "reasoning_text",
266
+ "text",
267
+ "summary",
268
+ "raw_content"
269
+ ]);
270
+ if (directText) return directText;
271
+ const summaryParts = getValue(item, ["summary"]);
272
+ if (Array.isArray(summaryParts)) {
273
+ const joined = summaryParts.flatMap((part) => {
274
+ if (typeof part === "string") return [part];
275
+ const text = getString(asRecord(part), ["text", "summary_text"]);
276
+ return text ? [text] : [];
277
+ }).join("\n");
278
+ if (joined) return joined;
279
+ }
280
+ };
281
+ const cacheItem = (item, options) => {
282
+ const id = getString(item, ["id"]);
283
+ if (!id || !options.itemCache) return;
284
+ const existing = options.itemCache.get(id);
285
+ options.itemCache.set(id, existing ? {
286
+ ...existing,
287
+ ...item
288
+ } : { ...item });
289
+ };
290
+ const mergeWithCached = (item, options) => {
291
+ const id = getString(item, ["id"]);
292
+ if (!id || !options.itemCache) return item;
293
+ const cached = options.itemCache.get(id);
294
+ options.itemCache.delete(id);
295
+ if (!cached) return item;
296
+ return {
297
+ ...cached,
298
+ ...item
299
+ };
300
+ };
301
+ const mapItemStartedEvent = (event, context, options) => {
302
+ const item = asRecord(event.item);
303
+ if (!item) return { events: [] };
304
+ cacheItem(item, options);
305
+ switch (normalizeItemType(getString(item, ["type"]) ?? "")) {
306
+ case "command_execution": return mapToolCallStart(item, context, getCommandToolRecord(item), options);
307
+ case "mcp_tool_call": return mapToolCallStart(item, context, getMcpToolRecord(item), options);
308
+ case "web_search": return mapToolCallStart(item, context, getWebSearchToolRecord(item), options);
309
+ default: return { events: [] };
310
+ }
311
+ };
312
+ const mapItemUpdatedEvent = (event, options) => {
313
+ const item = asRecord(event.item);
314
+ if (item) cacheItem(item, options);
315
+ return { events: [] };
316
+ };
317
+ const mapItemCompletedEvent = (event, context, options) => {
318
+ const rawItem = asRecord(event.item);
319
+ if (!rawItem) return { events: [] };
320
+ const item = mergeWithCached(rawItem, options);
321
+ switch (normalizeItemType(getString(item, ["type"]) ?? "")) {
322
+ case "agent_message": {
323
+ const text = getString(item, ["text"]);
324
+ if (!text) return { events: [] };
325
+ const isFinalAnswer = context.schemaRequested && (getString(item, ["phase"]) === void 0 || getString(item, ["phase"]) === "final_answer");
326
+ let parsedOutput;
327
+ if (isFinalAnswer) try {
328
+ parsedOutput = parseJsonResponseText(text);
329
+ } catch {}
330
+ return {
331
+ events: [createAgentEvent(context.runId, "message", {
332
+ sessionId: context.sessionId,
333
+ model: options.model ?? null,
334
+ role: "assistant",
335
+ content: [toTextPart(text)],
336
+ text
337
+ })],
338
+ state: { output: {
339
+ text,
340
+ ...parsedOutput === void 0 ? {} : { value: parsedOutput }
341
+ } }
342
+ };
343
+ }
344
+ case "reasoning": {
345
+ const text = getReasoningText(item);
346
+ if (!text) return { events: [] };
347
+ return { events: [createAgentEvent(context.runId, "reasoning", {
348
+ sessionId: context.sessionId,
349
+ model: options.model ?? null,
350
+ content: [toTextPart(text)],
351
+ text
352
+ })] };
353
+ }
354
+ case "command_execution": return mapToolResultCompletion(item, context, getCommandToolRecord(item), getCommandOutput(item), options);
355
+ case "mcp_tool_call": return mapToolResultCompletion(item, context, getMcpToolRecord(item), getMcpOutput(item), options);
356
+ case "web_search": return mapToolResultCompletion(item, context, getWebSearchToolRecord(item), getWebSearchOutput(item), options);
357
+ default: return { events: [] };
358
+ }
359
+ };
360
+ function mapCodexEventDetailed(event, context, options = {}) {
361
+ const threadStarted = codexThreadStartedEventSchema.safeParse(event);
362
+ if (threadStarted.success) return {
363
+ batch: mapThreadStartedEvent(threadStarted.data),
364
+ disposition: "mapped"
365
+ };
366
+ if (event.type === "turn.started") return {
367
+ batch: { events: [] },
368
+ disposition: "known-ignored"
369
+ };
370
+ const turnCompleted = codexTurnCompletedEventSchema.safeParse(event);
371
+ if (turnCompleted.success) return {
372
+ batch: mapTurnCompletedEvent(turnCompleted.data, context),
373
+ disposition: "mapped"
374
+ };
375
+ const turnFailed = codexTurnFailedEventSchema.safeParse(event);
376
+ if (turnFailed.success) return {
377
+ batch: mapTurnFailedEvent(turnFailed.data),
378
+ disposition: "mapped"
379
+ };
380
+ const errorEvent = codexErrorEventSchema.safeParse(event);
381
+ if (errorEvent.success) return {
382
+ batch: mapErrorEvent(errorEvent.data),
383
+ disposition: "mapped"
384
+ };
385
+ const itemStarted = codexItemStartedEventSchema.safeParse(event);
386
+ if (itemStarted.success) {
387
+ const batch = mapItemStartedEvent(itemStarted.data, context, options);
388
+ return {
389
+ batch,
390
+ disposition: batch.events.length > 0 || (batch.toolCalls?.length ?? 0) > 0 ? "mapped" : "known-ignored"
391
+ };
392
+ }
393
+ const itemUpdated = codexItemUpdatedEventSchema.safeParse(event);
394
+ if (itemUpdated.success) return {
395
+ batch: mapItemUpdatedEvent(itemUpdated.data, options),
396
+ disposition: "known-ignored"
397
+ };
398
+ const itemCompleted = codexItemCompletedEventSchema.safeParse(event);
399
+ if (itemCompleted.success) {
400
+ const batch = mapItemCompletedEvent(itemCompleted.data, context, options);
401
+ return {
402
+ batch,
403
+ disposition: batch.events.length > 0 || batch.state !== void 0 || (batch.toolCalls?.length ?? 0) > 0 || batch.sessionId !== void 0 ? "mapped" : "known-ignored"
404
+ };
405
+ }
406
+ switch (event.type) {
407
+ case "thread.started":
408
+ case "turn.started":
409
+ case "turn.completed":
410
+ case "turn.failed":
411
+ case "item.started":
412
+ case "item.updated":
413
+ case "item.completed":
414
+ case "error": return {
415
+ batch: { events: [] },
416
+ disposition: "known-malformed"
417
+ };
418
+ default: return {
419
+ batch: { events: [] },
420
+ disposition: "unknown"
421
+ };
422
+ }
423
+ }
424
+ //#endregion
425
+ //#region src/adapters/codex-cli/events/parser.ts
426
+ const parseCodexEvent = createEventParser(codexEventSchema);
427
+ //#endregion
428
+ //#region src/adapters/codex-cli/adapter.ts
429
+ const CODEX_CLI_CAPABILITIES = {
430
+ structuredOutput: true,
431
+ sessionResume: true,
432
+ imageInput: false,
433
+ mcp: true,
434
+ eventStreaming: true
435
+ };
436
+ const isSafeKey = (value) => /^\w+$/.test(value);
437
+ const formatConfigKey = (value) => isSafeKey(value) ? value : JSON.stringify(value);
438
+ const joinConfigPath = (...parts) => parts.map(formatConfigKey).join(".");
439
+ const fmtValue = (value) => JSON.stringify(value);
440
+ const fmtArray = (values) => `[${values.map((v) => JSON.stringify(v)).join(",")}]`;
441
+ const mcpServersToConfigArgs = (servers) => {
442
+ const args = [];
443
+ for (const [name, server] of Object.entries(servers)) {
444
+ const base = joinConfigPath("mcp_servers", name);
445
+ if (server.url) args.push("--config", `${base}.url=${fmtValue(server.url)}`);
446
+ if (server.command) args.push("--config", `${base}.command=${fmtValue(server.command)}`);
447
+ if (server.args && server.args.length > 0) args.push("--config", `${base}.args=${fmtArray(server.args)}`);
448
+ if (server.cwd) args.push("--config", `${base}.cwd=${fmtValue(server.cwd)}`);
449
+ if (server.headers) for (const [key, value] of Object.entries(server.headers)) args.push("--config", `${joinConfigPath("mcp_servers", name, "http_headers", key)}=${fmtValue(value)}`);
450
+ if (server.env) for (const [key, value] of Object.entries(server.env)) args.push("--config", `${joinConfigPath("mcp_servers", name, "env", key)}=${fmtValue(value)}`);
451
+ }
452
+ return args;
453
+ };
454
+ const readStringArray = (value, label) => {
455
+ if (value === void 0) return;
456
+ if (!Array.isArray(value) || value.some((entry) => typeof entry !== "string")) throw new AgentValidationError(`${label} must be an array of strings.`);
457
+ return [...value];
458
+ };
459
+ const readStringRecord = (value, label) => {
460
+ if (value === void 0) return;
461
+ if (!isRecord(value) || Array.isArray(value)) throw new AgentValidationError(`${label} must be an object.`);
462
+ const result = {};
463
+ for (const [key, entry] of Object.entries(value)) {
464
+ if (typeof entry !== "string") throw new AgentValidationError(`${label}.${key} must be a string.`);
465
+ result[key] = entry;
466
+ }
467
+ return result;
468
+ };
469
+ const readMcpServerConfig = (value, label) => {
470
+ if (!isRecord(value) || Array.isArray(value)) throw new AgentValidationError(`${label} must be an object.`);
471
+ const command = value.command;
472
+ const url = value.url;
473
+ const cwd = value.cwd;
474
+ if (command !== void 0 && typeof command !== "string") throw new AgentValidationError(`${label}.command must be a string.`);
475
+ if (url !== void 0 && typeof url !== "string") throw new AgentValidationError(`${label}.url must be a string.`);
476
+ if (cwd !== void 0 && typeof cwd !== "string") throw new AgentValidationError(`${label}.cwd must be a string.`);
477
+ return {
478
+ command,
479
+ url,
480
+ cwd,
481
+ args: readStringArray(value.args, `${label}.args`),
482
+ env: readStringRecord(value.env, `${label}.env`),
483
+ headers: readStringRecord(value.headers, `${label}.headers`)
484
+ };
485
+ };
486
+ const readMcpConfig = (configPath) => {
487
+ let parsed;
488
+ try {
489
+ parsed = JSON.parse(readFileSync(configPath, "utf8"));
490
+ } catch (error) {
491
+ if (error instanceof Error && "code" in error && error.code === "ENOENT") throw new AgentValidationError(`mcpConfig file not found: ${configPath}`);
492
+ throw new AgentValidationError(`mcpConfig must be valid JSON: ${configPath}`);
493
+ }
494
+ if (!isRecord(parsed) || Array.isArray(parsed)) throw new AgentValidationError(`mcpConfig must contain a JSON object: ${configPath}`);
495
+ const mcpServers = parsed.mcpServers;
496
+ if (mcpServers === void 0) return;
497
+ if (!isRecord(mcpServers) || Array.isArray(mcpServers)) throw new AgentValidationError(`mcpConfig.mcpServers must be an object: ${configPath}`);
498
+ const parsedServers = {};
499
+ for (const [name, server] of Object.entries(mcpServers)) parsedServers[name] = readMcpServerConfig(server, `mcpConfig.mcpServers.${name}`);
500
+ return parsedServers;
501
+ };
502
+ const buildMcpConfigArgs = (configPath) => {
503
+ const servers = readMcpConfig(configPath);
504
+ return servers ? mcpServersToConfigArgs(servers) : [];
505
+ };
506
+ var CodexCliAgentImpl = class extends Agent {
507
+ type = "codex-cli";
508
+ creationOptions;
509
+ runDefaults;
510
+ schemaDirs = /* @__PURE__ */ new Map();
511
+ runModels = /* @__PURE__ */ new Map();
512
+ itemCaches = /* @__PURE__ */ new Map();
513
+ constructor(options = {}) {
514
+ super({
515
+ type: "codex-cli",
516
+ capabilities: CODEX_CLI_CAPABILITIES,
517
+ defaults: {
518
+ cwd: options.cwd,
519
+ env: options.env,
520
+ command: toArray(options.command ?? "codex"),
521
+ sessionId: options.sessionId,
522
+ model: options.model
523
+ },
524
+ spawner: options.spawner,
525
+ container: options.container,
526
+ logPath: options.logPath,
527
+ onEvent: options.onEvent
528
+ });
529
+ this.creationOptions = options;
530
+ this.runDefaults = {
531
+ sandbox: options.sandbox,
532
+ additionalDirectories: options.additionalDirectories ? [...options.additionalDirectories] : void 0,
533
+ skipGitRepoCheck: options.skipGitRepoCheck,
534
+ permissionMode: options.permissionMode,
535
+ ephemeral: options.ephemeral,
536
+ mcpConfig: options.mcpConfig,
537
+ mcpServers: options.mcpServers ? { ...options.mcpServers } : void 0,
538
+ extraArgs: options.extraArgs ? [...options.extraArgs] : void 0
539
+ };
540
+ }
541
+ onValidateRun(request, _normalizedRequest) {
542
+ const mcpConfig = request.mcpConfig ?? this.runDefaults.mcpConfig;
543
+ if (mcpConfig) readMcpConfig(mcpConfig);
544
+ }
545
+ buildArgs(request, run) {
546
+ const args = ["exec", "--json"];
547
+ const sandbox = request.sandbox ?? this.runDefaults.sandbox;
548
+ const additionalDirectories = request.additionalDirectories ?? this.runDefaults.additionalDirectories;
549
+ const skipGitRepoCheck = request.skipGitRepoCheck ?? this.runDefaults.skipGitRepoCheck;
550
+ const permissionMode = request.permissionMode ?? this.runDefaults.permissionMode;
551
+ const ephemeral = request.ephemeral ?? this.runDefaults.ephemeral;
552
+ const extraArgs = request.extraArgs ?? this.runDefaults.extraArgs;
553
+ this.runModels.set(run.runId, request.model);
554
+ if (request.model) args.push("--model", request.model);
555
+ if (sandbox) args.push("--sandbox", sandbox);
556
+ if (permissionMode === "full-auto") args.push("--full-auto");
557
+ else if (permissionMode === "full-access") args.push("--dangerously-bypass-approvals-and-sandbox");
558
+ if (skipGitRepoCheck) args.push("--skip-git-repo-check");
559
+ if (ephemeral) args.push("--ephemeral");
560
+ for (const dir of additionalDirectories ?? []) args.push("--add-dir", dir);
561
+ if (request.schema.kind !== "none") args.push("--output-schema", this.createSchemaFile(run.runId, request.schema.jsonSchema));
562
+ const mcpConfig = request.mcpConfig ?? this.runDefaults.mcpConfig;
563
+ if (mcpConfig) args.push(...buildMcpConfigArgs(mcpConfig));
564
+ const mcpServers = request.mcpServers ?? this.runDefaults.mcpServers;
565
+ if (mcpServers) args.push(...mcpServersToConfigArgs(mcpServers));
566
+ if (extraArgs && extraArgs.length > 0) args.push(...extraArgs);
567
+ if (run.requestedSessionId) args.push("resume", run.requestedSessionId);
568
+ const inputText = getInputText(request.input);
569
+ if (inputText.trim().startsWith("-")) args.push("--", inputText);
570
+ else args.push(inputText);
571
+ return args;
572
+ }
573
+ buildEnv(_request, _run) {
574
+ return this.buildDefaultEnv(this.creationOptions.propagateEnv);
575
+ }
576
+ mapRawEvent(raw, context) {
577
+ this.appendRawLog(raw);
578
+ const parsed = parseCodexEvent(raw);
579
+ if (!parsed) {
580
+ this.onParseError(JSON.stringify(raw).slice(0, 200), /* @__PURE__ */ new Error("schema validation failed"));
581
+ return { events: [] };
582
+ }
583
+ let itemCache = this.itemCaches.get(context.runId);
584
+ if (!itemCache) {
585
+ itemCache = /* @__PURE__ */ new Map();
586
+ this.itemCaches.set(context.runId, itemCache);
587
+ }
588
+ const result = mapCodexEventDetailed(parsed, context, {
589
+ model: this.runModels.get(context.runId),
590
+ itemCache
591
+ });
592
+ if (result.disposition === "known-malformed") this.onParseError(JSON.stringify(raw).slice(0, 200), /* @__PURE__ */ new Error(`known Codex event "${parsed.type}" did not match the expected payload shape`));
593
+ return result.batch;
594
+ }
595
+ async onRunFinished(run) {
596
+ await super.onRunFinished(run);
597
+ this.runModels.delete(run.runId);
598
+ this.itemCaches.delete(run.runId);
599
+ const schemaDir = this.schemaDirs.get(run.runId);
600
+ if (!schemaDir) return;
601
+ this.schemaDirs.delete(run.runId);
602
+ rmSync(schemaDir, {
603
+ recursive: true,
604
+ force: true
605
+ });
606
+ }
607
+ createSchemaFile(runId, schema) {
608
+ const schemaDir = mkdtempSync(join(tmpdir(), "coding-agents-sdk-codex-cli-"));
609
+ const schemaPath = join(schemaDir, "output-schema.json");
610
+ writeFileSync(schemaPath, JSON.stringify(schema, null, 2), {
611
+ encoding: "utf8",
612
+ mode: 384
613
+ });
614
+ this.schemaDirs.set(runId, schemaDir);
615
+ return schemaPath;
616
+ }
617
+ };
618
+ const createCodexCliAgent = (options) => {
619
+ if (!options?.container) return new CodexCliAgentImpl(options);
620
+ return new CodexCliAgentImpl({
621
+ ...options,
622
+ spawner: options.container.spawner
623
+ });
624
+ };
625
+ //#endregion
626
+ export { createCodexCliAgent };
@@ -0,0 +1,2 @@
1
+ import { a as CodexSdkItem, i as CodexSdkEvent, n as CodexSdkAgent, o as CodexSdkPermissionMode, r as CodexSdkAgentOptions, s as CodexSdkRunOptions, t as createCodexSdkAgent } from "../../index-CFpNOmdA.mjs";
2
+ export { CodexSdkAgent, CodexSdkAgentOptions, CodexSdkEvent, CodexSdkItem, CodexSdkPermissionMode, CodexSdkRunOptions, createCodexSdkAgent };