baro-ai 0.41.0 → 0.42.1

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.
package/dist/cli.mjs CHANGED
@@ -9904,6 +9904,10 @@ var ClaudeSystem = defineSemanticEvent("claude_system");
9904
9904
  var AgentResult = defineSemanticEvent("claude_result");
9905
9905
  var ClaudeStreamChunk = defineSemanticEvent("claude_stream_chunk");
9906
9906
  var ClaudeRateLimit = defineSemanticEvent("claude_rate_limit");
9907
+ var CodexSystem = defineSemanticEvent("codex_system");
9908
+ var CodexTurnEvent = defineSemanticEvent("codex_turn_event");
9909
+ var CodexItemEvent = defineSemanticEvent("codex_item_event");
9910
+ var CodexUnknownEvent = defineSemanticEvent("codex_unknown_event");
9907
9911
  var Critique = defineSemanticEvent("critique");
9908
9912
  var ClaudeUnknownEvent = defineSemanticEvent("claude_unknown_event");
9909
9913
  var RunStartRequest = defineSemanticEvent("run_start_request");
@@ -11761,6 +11765,584 @@ function extractPath(item) {
11761
11765
  return null;
11762
11766
  }
11763
11767
 
11768
+ // ../baro-orchestrator/src/participants/codex-story-agent.ts
11769
+ import { setTimeout as setTimeoutPromise } from "timers/promises";
11770
+
11771
+ // ../baro-orchestrator/src/participants/codex-cli-participant.ts
11772
+ import { spawn } from "child_process";
11773
+
11774
+ // ../baro-orchestrator/src/codex-stream-mapper.ts
11775
+ function mapCodexEvent(agentId, event) {
11776
+ const threadId = typeof event.thread_id === "string" ? event.thread_id : null;
11777
+ const items = [];
11778
+ const type = typeof event.type === "string" ? event.type : "";
11779
+ if (type === "thread.started" || type === "thread.completed") {
11780
+ items.push(
11781
+ CodexSystem.create({
11782
+ agentId,
11783
+ subtype: type,
11784
+ raw: event
11785
+ })
11786
+ );
11787
+ return { items, threadId };
11788
+ }
11789
+ if (type === "turn.started" || type === "turn.completed" || type === "turn.failed") {
11790
+ items.push(
11791
+ CodexTurnEvent.create({
11792
+ agentId,
11793
+ phase: type.slice("turn.".length),
11794
+ raw: event
11795
+ })
11796
+ );
11797
+ return { items, threadId };
11798
+ }
11799
+ if (type === "error") {
11800
+ items.push(
11801
+ CodexSystem.create({
11802
+ agentId,
11803
+ subtype: "error",
11804
+ raw: event
11805
+ })
11806
+ );
11807
+ return { items, threadId };
11808
+ }
11809
+ if (type === "item.started" || type === "item.updated") {
11810
+ const inner = event.item && typeof event.item === "object" ? event.item : {};
11811
+ const innerType = typeof inner.type === "string" ? inner.type : "unknown";
11812
+ items.push(
11813
+ CodexItemEvent.create({
11814
+ agentId,
11815
+ itemType: `${type.slice("item.".length)}:${innerType}`,
11816
+ raw: event
11817
+ })
11818
+ );
11819
+ return { items, threadId };
11820
+ }
11821
+ if (type === "item.completed") {
11822
+ const inner = event.item && typeof event.item === "object" ? event.item : {};
11823
+ const innerType = typeof inner.type === "string" ? inner.type : "unknown";
11824
+ if (innerType === "agent_message" || innerType === "message") {
11825
+ const text = typeof inner.text === "string" ? inner.text : "";
11826
+ if (text) {
11827
+ items.push(ModelMessageItem.rehydrate({ text }));
11828
+ }
11829
+ items.push(
11830
+ CodexItemEvent.create({
11831
+ agentId,
11832
+ itemType: innerType,
11833
+ raw: event
11834
+ })
11835
+ );
11836
+ return { items, threadId };
11837
+ }
11838
+ if (innerType === "reasoning") {
11839
+ items.push(
11840
+ CodexItemEvent.create({
11841
+ agentId,
11842
+ itemType: innerType,
11843
+ raw: event
11844
+ })
11845
+ );
11846
+ return { items, threadId };
11847
+ }
11848
+ if (innerType === "command_execution" || innerType === "file_change" || innerType === "mcp_tool_call" || innerType === "web_search") {
11849
+ const callId = stringifyId(inner);
11850
+ const name = inferToolName(innerType, inner);
11851
+ const args = inferToolArgs(inner);
11852
+ items.push(FunctionCallItem.rehydrate({ callId, name, args }));
11853
+ const output = inferToolOutput(innerType, inner);
11854
+ if (output !== null) {
11855
+ items.push(FunctionCallOutputItem.create(callId, output));
11856
+ }
11857
+ items.push(
11858
+ CodexItemEvent.create({
11859
+ agentId,
11860
+ itemType: innerType,
11861
+ raw: event
11862
+ })
11863
+ );
11864
+ return { items, threadId };
11865
+ }
11866
+ items.push(
11867
+ CodexItemEvent.create({
11868
+ agentId,
11869
+ itemType: innerType,
11870
+ raw: event
11871
+ })
11872
+ );
11873
+ return { items, threadId };
11874
+ }
11875
+ items.push(
11876
+ CodexUnknownEvent.create({
11877
+ agentId,
11878
+ codexType: type || "unspecified",
11879
+ raw: event
11880
+ })
11881
+ );
11882
+ return { items, threadId };
11883
+ }
11884
+ function stringifyId(event) {
11885
+ if (typeof event.id === "string") return event.id;
11886
+ if (typeof event.call_id === "string") return event.call_id;
11887
+ if (typeof event.item_id === "string") return event.item_id;
11888
+ const hint = typeof event.command === "string" ? event.command.slice(0, 32) : typeof event.path === "string" ? event.path : typeof event.tool_name === "string" ? event.tool_name : "anon";
11889
+ return `codex:${event.type ?? "item"}:${hint}`;
11890
+ }
11891
+ function inferToolName(itemType, event) {
11892
+ if (typeof event.tool_name === "string") return event.tool_name;
11893
+ switch (itemType) {
11894
+ case "command_execution":
11895
+ return "shell";
11896
+ case "file_change":
11897
+ return "edit";
11898
+ case "web_search":
11899
+ return "web_search";
11900
+ default:
11901
+ return itemType;
11902
+ }
11903
+ }
11904
+ function inferToolArgs(event) {
11905
+ if (event.arguments !== void 0) {
11906
+ return typeof event.arguments === "string" ? event.arguments : JSON.stringify(event.arguments);
11907
+ }
11908
+ const candidate = {};
11909
+ for (const key of ["command", "path", "diff", "query"]) {
11910
+ if (event[key] !== void 0) candidate[key] = event[key];
11911
+ }
11912
+ if (Object.keys(candidate).length > 0) return JSON.stringify(candidate);
11913
+ const { type: _t, ...rest } = event;
11914
+ return JSON.stringify(rest);
11915
+ }
11916
+ function inferToolOutput(itemType, event) {
11917
+ if (typeof event.output === "string") return event.output;
11918
+ if (typeof event.aggregated_output === "string") {
11919
+ return event.aggregated_output;
11920
+ }
11921
+ if (typeof event.result === "string") return event.result;
11922
+ if (itemType === "command_execution" && typeof event.exit_code === "number") {
11923
+ return `exit_code=${event.exit_code}`;
11924
+ }
11925
+ return null;
11926
+ }
11927
+
11928
+ // ../baro-orchestrator/src/participants/codex-cli-participant.ts
11929
+ var CodexCliParticipant = class _CodexCliParticipant extends BaseObserver {
11930
+ constructor(agentId, opts) {
11931
+ super();
11932
+ this.agentId = agentId;
11933
+ this.options = {
11934
+ codexBin: "codex",
11935
+ fullAuto: false,
11936
+ skipGitRepoCheck: false,
11937
+ ...opts
11938
+ };
11939
+ this.ready = new Promise((res, rej) => {
11940
+ this.resolveReady = res;
11941
+ this.rejectReady = rej;
11942
+ });
11943
+ this.done = new Promise((res) => {
11944
+ this.resolveDone = res;
11945
+ });
11946
+ }
11947
+ /**
11948
+ * Process-wide registry of every Codex child currently running. Used
11949
+ * by the orchestrator's SIGINT/SIGTERM handlers to nuke orphans so a
11950
+ * killed baro doesn't leave a swarm of background agents burning
11951
+ * quota.
11952
+ */
11953
+ static active = /* @__PURE__ */ new Set();
11954
+ /** Send a signal to every active Codex child. Idempotent. */
11955
+ static killAll(signal = "SIGTERM") {
11956
+ for (const p of _CodexCliParticipant.active) {
11957
+ try {
11958
+ p.proc?.kill(signal);
11959
+ } catch {
11960
+ }
11961
+ }
11962
+ }
11963
+ options;
11964
+ proc = null;
11965
+ buffer = "";
11966
+ envRef = null;
11967
+ currentPhase = "idle";
11968
+ threadId = null;
11969
+ exitCode = null;
11970
+ spawnError = null;
11971
+ resolveDone;
11972
+ resolveReady;
11973
+ rejectReady;
11974
+ /** Resolves once Codex emits its first `thread.started` event. */
11975
+ ready;
11976
+ /** Resolves once the Codex process exits (regardless of success). */
11977
+ done;
11978
+ getThreadId() {
11979
+ return this.threadId;
11980
+ }
11981
+ getPhase() {
11982
+ return this.currentPhase;
11983
+ }
11984
+ /**
11985
+ * Spawn the Codex process and start streaming its events into the
11986
+ * environment. Idempotent: subsequent calls are a no-op.
11987
+ */
11988
+ start(environment) {
11989
+ if (this.proc) return;
11990
+ this.envRef = environment;
11991
+ const args = this.buildArgs();
11992
+ let proc;
11993
+ try {
11994
+ proc = spawn(this.options.codexBin, args, {
11995
+ cwd: this.options.cwd,
11996
+ stdio: ["ignore", "pipe", "pipe"]
11997
+ });
11998
+ } catch (e) {
11999
+ this.spawnError = e instanceof Error ? e : new Error(String(e));
12000
+ this.transition("failed", this.spawnError.message);
12001
+ this.rejectReady(this.spawnError);
12002
+ this.resolveDone({
12003
+ threadId: null,
12004
+ exitCode: null,
12005
+ error: this.spawnError
12006
+ });
12007
+ return;
12008
+ }
12009
+ this.proc = proc;
12010
+ _CodexCliParticipant.active.add(this);
12011
+ this.transition("starting");
12012
+ proc.stdout.setEncoding("utf8");
12013
+ proc.stderr.setEncoding("utf8");
12014
+ proc.stdout.on("data", (chunk) => this.handleStdout(chunk));
12015
+ proc.stderr.on("data", (chunk) => this.handleStderr(chunk));
12016
+ proc.on("error", (err) => {
12017
+ this.spawnError = err;
12018
+ this.rejectReady(err);
12019
+ });
12020
+ proc.on("exit", (code) => {
12021
+ _CodexCliParticipant.active.delete(this);
12022
+ this.exitCode = code;
12023
+ const finalPhase = this.spawnError != null || code != null && code !== 0 ? "failed" : "done";
12024
+ this.transition(
12025
+ finalPhase,
12026
+ code != null ? `exit code ${code}` : "no exit code"
12027
+ );
12028
+ this.resolveDone({
12029
+ threadId: this.threadId,
12030
+ exitCode: code,
12031
+ error: this.spawnError
12032
+ });
12033
+ });
12034
+ }
12035
+ /** Kill the Codex process. Resolves once exit fires. */
12036
+ abort(signal = "SIGTERM") {
12037
+ this.transition("aborted");
12038
+ this.proc?.kill(signal);
12039
+ }
12040
+ async onExternalEvent(_source, event) {
12041
+ if (AgentTargetedMessage.is(event) && event.data.recipientId === this.agentId) {
12042
+ process.stderr.write(
12043
+ `[codex:${this.agentId}] received AgentTargetedMessage but Codex exec is one-shot \u2014 dropped
12044
+ `
12045
+ );
12046
+ }
12047
+ }
12048
+ buildArgs() {
12049
+ const args = ["exec", "--json"];
12050
+ if (this.options.skipGitRepoCheck) args.push("--skip-git-repo-check");
12051
+ if (this.options.fullAuto) args.push("--full-auto");
12052
+ if (this.options.model) args.push("--model", this.options.model);
12053
+ if (this.options.extraArgs?.length) args.push(...this.options.extraArgs);
12054
+ args.push(this.options.prompt);
12055
+ return args;
12056
+ }
12057
+ handleStdout(chunk) {
12058
+ this.buffer += chunk;
12059
+ let nl;
12060
+ while ((nl = this.buffer.indexOf("\n")) >= 0) {
12061
+ const line = this.buffer.slice(0, nl).trim();
12062
+ this.buffer = this.buffer.slice(nl + 1);
12063
+ if (!line) continue;
12064
+ this.processLine(line);
12065
+ }
12066
+ }
12067
+ handleStderr(chunk) {
12068
+ const trimmed = chunk.trimEnd();
12069
+ if (!trimmed) return;
12070
+ process.stderr.write(`[codex:${this.agentId}/stderr] ${trimmed}
12071
+ `);
12072
+ }
12073
+ processLine(line) {
12074
+ let parsed;
12075
+ try {
12076
+ parsed = JSON.parse(line);
12077
+ } catch {
12078
+ process.stderr.write(
12079
+ `[codex:${this.agentId}] non-JSON stdout: ${line.slice(0, 200)}
12080
+ `
12081
+ );
12082
+ return;
12083
+ }
12084
+ const { items, threadId } = mapCodexEvent(this.agentId, parsed);
12085
+ if (threadId && !this.threadId) {
12086
+ this.threadId = threadId;
12087
+ }
12088
+ for (const item of items) {
12089
+ if (item instanceof SemanticEvent) {
12090
+ if (CodexSystem.is(item) && item.data.subtype === "thread.started") {
12091
+ this.transition("running", "codex thread started");
12092
+ this.resolveReady();
12093
+ }
12094
+ if (CodexTurnEvent.is(item)) {
12095
+ const phase = item.data.phase;
12096
+ if (phase === "failed") {
12097
+ this.transition("failed", "codex turn failed");
12098
+ }
12099
+ }
12100
+ }
12101
+ this.dispatch(item);
12102
+ }
12103
+ }
12104
+ /**
12105
+ * Route a mapped event to the right Mozaik delivery channel.
12106
+ * Mirror of ClaudeCliParticipant.dispatch — assistant-side LLM items
12107
+ * use Mozaik's typed channels; everything else goes through
12108
+ * deliverSemanticEvent.
12109
+ */
12110
+ dispatch(item) {
12111
+ if (!this.envRef) return;
12112
+ if (item instanceof ModelMessageItem) {
12113
+ this.envRef.deliverModelMessage(this, item);
12114
+ return;
12115
+ }
12116
+ if (item instanceof FunctionCallItem) {
12117
+ this.envRef.deliverFunctionCall(this, item);
12118
+ return;
12119
+ }
12120
+ if (item instanceof FunctionCallOutputItem) {
12121
+ this.envRef.deliverFunctionCallOutput(this, item);
12122
+ return;
12123
+ }
12124
+ this.envRef.deliverSemanticEvent(this, item);
12125
+ }
12126
+ transition(next, detail) {
12127
+ if (next === this.currentPhase) return;
12128
+ this.currentPhase = next;
12129
+ this.envRef?.deliverSemanticEvent(
12130
+ this,
12131
+ AgentState.create({
12132
+ agentId: this.agentId,
12133
+ phase: next,
12134
+ detail
12135
+ })
12136
+ );
12137
+ }
12138
+ };
12139
+
12140
+ // ../baro-orchestrator/src/participants/codex-story-agent.ts
12141
+ var CodexStoryAgent = class extends BaseObserver {
12142
+ spec;
12143
+ envRef = null;
12144
+ currentCodex = null;
12145
+ currentPhase = "idle";
12146
+ startedAt = null;
12147
+ resolveDone;
12148
+ done;
12149
+ constructor(spec) {
12150
+ super();
12151
+ this.spec = {
12152
+ retries: 2,
12153
+ timeoutSecs: 600,
12154
+ retryDelayMs: 1500,
12155
+ hardTimeoutSecs: 0,
12156
+ fullAuto: true,
12157
+ skipGitRepoCheck: false,
12158
+ ...spec
12159
+ };
12160
+ this.done = new Promise((res) => {
12161
+ this.resolveDone = res;
12162
+ });
12163
+ }
12164
+ get id() {
12165
+ return this.spec.id;
12166
+ }
12167
+ get agentId() {
12168
+ return this.spec.id;
12169
+ }
12170
+ getPhase() {
12171
+ return this.currentPhase;
12172
+ }
12173
+ getCurrentCodex() {
12174
+ return this.currentCodex;
12175
+ }
12176
+ /**
12177
+ * Begin executing the story. Idempotent. Returns the `done` promise
12178
+ * for the caller's convenience.
12179
+ */
12180
+ run(environment) {
12181
+ if (this.startedAt != null) {
12182
+ return this.done;
12183
+ }
12184
+ this.envRef = environment;
12185
+ this.startedAt = Date.now();
12186
+ this.transition("starting", "story queued");
12187
+ void this.executeAllAttempts();
12188
+ return this.done;
12189
+ }
12190
+ /**
12191
+ * No-op: Codex exec is one-shot, there's no stdin channel to forward
12192
+ * mid-flight messages to. Logged at the participant level if we ever
12193
+ * see an AgentTargetedMessage addressed here.
12194
+ */
12195
+ async onExternalEvent(_source, _event) {
12196
+ }
12197
+ /** Abort the story, killing the running Codex (if any). */
12198
+ abort() {
12199
+ this.currentCodex?.abort();
12200
+ this.transition("aborted", "external abort");
12201
+ }
12202
+ async executeAllAttempts() {
12203
+ const maxAttempts = this.spec.retries + 1;
12204
+ let lastSummary = null;
12205
+ let lastError = null;
12206
+ let hardTimedOut = false;
12207
+ const hardTimer = this.spec.hardTimeoutSecs > 0 ? setTimeout(() => {
12208
+ hardTimedOut = true;
12209
+ this.currentCodex?.abort();
12210
+ }, this.spec.hardTimeoutSecs * 1e3) : null;
12211
+ try {
12212
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
12213
+ if (hardTimedOut) {
12214
+ lastError = `hard timeout after ${this.spec.hardTimeoutSecs}s`;
12215
+ break;
12216
+ }
12217
+ if (attempt > 1) {
12218
+ this.transition(
12219
+ "waiting",
12220
+ `retrying (attempt ${attempt}/${maxAttempts})`
12221
+ );
12222
+ await setTimeoutPromise(this.spec.retryDelayMs);
12223
+ if (hardTimedOut) {
12224
+ lastError = `hard timeout after ${this.spec.hardTimeoutSecs}s`;
12225
+ break;
12226
+ }
12227
+ }
12228
+ const result = await this.runOneAttempt(attempt);
12229
+ lastSummary = result.summary;
12230
+ lastError = result.error;
12231
+ if (result.success) {
12232
+ const durationSecs2 = Math.round(
12233
+ (Date.now() - (this.startedAt ?? Date.now())) / 1e3
12234
+ );
12235
+ this.transition("done", `success on attempt ${attempt}`);
12236
+ this.emitStoryResult(true, attempt, durationSecs2, null);
12237
+ this.resolveDone({
12238
+ storyId: this.spec.id,
12239
+ success: true,
12240
+ attempts: attempt,
12241
+ durationSecs: durationSecs2,
12242
+ finalSummary: result.summary,
12243
+ error: null
12244
+ });
12245
+ return;
12246
+ }
12247
+ if (hardTimedOut) {
12248
+ lastError = `hard timeout after ${this.spec.hardTimeoutSecs}s`;
12249
+ break;
12250
+ }
12251
+ }
12252
+ } finally {
12253
+ if (hardTimer !== null) clearTimeout(hardTimer);
12254
+ }
12255
+ const durationSecs = Math.round(
12256
+ (Date.now() - (this.startedAt ?? Date.now())) / 1e3
12257
+ );
12258
+ this.transition("failed", `exhausted ${maxAttempts} attempts`);
12259
+ this.emitStoryResult(false, maxAttempts, durationSecs, lastError);
12260
+ this.resolveDone({
12261
+ storyId: this.spec.id,
12262
+ success: false,
12263
+ attempts: maxAttempts,
12264
+ durationSecs,
12265
+ finalSummary: lastSummary,
12266
+ error: lastError
12267
+ });
12268
+ }
12269
+ async runOneAttempt(attempt) {
12270
+ if (!this.envRef) {
12271
+ return { success: false, summary: null, error: "no environment" };
12272
+ }
12273
+ this.transition("running", `attempt ${attempt}`);
12274
+ const codex = new CodexCliParticipant(this.spec.id, {
12275
+ cwd: this.spec.cwd,
12276
+ prompt: this.spec.prompt,
12277
+ model: this.spec.model,
12278
+ fullAuto: this.spec.fullAuto,
12279
+ skipGitRepoCheck: this.spec.skipGitRepoCheck
12280
+ });
12281
+ this.currentCodex = codex;
12282
+ codex.join(this.envRef);
12283
+ codex.start(this.envRef);
12284
+ let summary;
12285
+ try {
12286
+ summary = await raceWithTimeout(
12287
+ codex.done,
12288
+ this.spec.timeoutSecs * 1e3,
12289
+ `attempt ${attempt} timeout after ${this.spec.timeoutSecs}s`
12290
+ );
12291
+ } catch (e) {
12292
+ codex.abort();
12293
+ const error = e instanceof Error ? e.message : String(e);
12294
+ try {
12295
+ await codex.done;
12296
+ } catch {
12297
+ }
12298
+ codex.leave(this.envRef);
12299
+ this.currentCodex = null;
12300
+ return { success: false, summary: null, error };
12301
+ }
12302
+ codex.leave(this.envRef);
12303
+ this.currentCodex = null;
12304
+ const success = summary.exitCode === 0 && summary.error == null;
12305
+ if (!success) {
12306
+ const reason = summary.error ? summary.error.message : `non-zero exit ${summary.exitCode}`;
12307
+ return { success: false, summary, error: reason };
12308
+ }
12309
+ return { success: true, summary, error: null };
12310
+ }
12311
+ emitStoryResult(success, attempts, durationSecs, error) {
12312
+ if (!this.envRef) return;
12313
+ this.envRef.deliverSemanticEvent(
12314
+ this,
12315
+ StoryResult.create({
12316
+ storyId: this.spec.id,
12317
+ success,
12318
+ attempts,
12319
+ durationSecs,
12320
+ error
12321
+ })
12322
+ );
12323
+ }
12324
+ transition(next, detail) {
12325
+ if (next === this.currentPhase) return;
12326
+ this.currentPhase = next;
12327
+ if (this.envRef) {
12328
+ this.envRef.deliverSemanticEvent(
12329
+ this,
12330
+ AgentState.create({
12331
+ agentId: this.spec.id,
12332
+ phase: next,
12333
+ detail
12334
+ })
12335
+ );
12336
+ }
12337
+ }
12338
+ };
12339
+ function raceWithTimeout(p, ms, label) {
12340
+ return Promise.race([
12341
+ p,
12342
+ new Promise((_, rej) => setTimeout(() => rej(new Error(label)), ms))
12343
+ ]);
12344
+ }
12345
+
11764
12346
  // ../baro-orchestrator/src/planning/story-tools.ts
11765
12347
  import * as fs2 from "fs";
11766
12348
  import * as path3 from "path";
@@ -12549,10 +13131,10 @@ function sleep2(ms) {
12549
13131
  }
12550
13132
 
12551
13133
  // ../baro-orchestrator/src/participants/story-agent.ts
12552
- import { setTimeout as setTimeoutPromise } from "timers/promises";
13134
+ import { setTimeout as setTimeoutPromise2 } from "timers/promises";
12553
13135
 
12554
13136
  // ../baro-orchestrator/src/participants/claude-cli-participant.ts
12555
- import { spawn } from "child_process";
13137
+ import { spawn as spawn2 } from "child_process";
12556
13138
 
12557
13139
  // ../baro-orchestrator/src/stream-json-mapper.ts
12558
13140
  function mapClaudeEvent(agentId, event) {
@@ -12725,7 +13307,7 @@ var ClaudeCliParticipant = class _ClaudeCliParticipant extends BaseObserver {
12725
13307
  const args = this.buildArgs();
12726
13308
  let proc;
12727
13309
  try {
12728
- proc = spawn(this.options.claudeBin, args, {
13310
+ proc = spawn2(this.options.claudeBin, args, {
12729
13311
  cwd: this.options.cwd,
12730
13312
  stdio: ["pipe", "pipe", "pipe"]
12731
13313
  });
@@ -13011,7 +13593,7 @@ var StoryAgent = class extends BaseObserver {
13011
13593
  "waiting",
13012
13594
  `retrying (attempt ${attempt}/${maxAttempts})`
13013
13595
  );
13014
- await setTimeoutPromise(this.spec.retryDelayMs);
13596
+ await setTimeoutPromise2(this.spec.retryDelayMs);
13015
13597
  if (hardTimedOut) {
13016
13598
  lastError = `hard timeout after ${this.spec.hardTimeoutSecs}s`;
13017
13599
  break;
@@ -13082,7 +13664,7 @@ var StoryAgent = class extends BaseObserver {
13082
13664
  const cancelMultiTurn = this.setupMultiTurnLifecycle(claude);
13083
13665
  let summary;
13084
13666
  try {
13085
- summary = await raceWithTimeout(
13667
+ summary = await raceWithTimeout2(
13086
13668
  claude.done,
13087
13669
  this.spec.timeoutSecs * 1e3,
13088
13670
  `attempt ${attempt} timeout after ${this.spec.timeoutSecs}s`
@@ -13183,7 +13765,7 @@ var StoryAgent = class extends BaseObserver {
13183
13765
  }
13184
13766
  }
13185
13767
  };
13186
- function raceWithTimeout(p, ms, label) {
13768
+ function raceWithTimeout2(p, ms, label) {
13187
13769
  return Promise.race([
13188
13770
  p,
13189
13771
  new Promise((_, rej) => setTimeout(() => rej(new Error(label)), ms))
@@ -13223,7 +13805,15 @@ var StoryFactory = class extends BaseObserver {
13223
13805
  const llm = this.opts.llm ?? "claude";
13224
13806
  const claudeModel = this.opts.storyModelOverride ?? req.model;
13225
13807
  const openaiModel = this.opts.storyModelOverride ?? this.opts.openaiModel ?? "gpt-5.5";
13226
- const agent = llm === "openai" ? new OpenAIStoryAgent(
13808
+ const codexModel = this.opts.storyModelOverride;
13809
+ const agent = llm === "codex" ? new CodexStoryAgent({
13810
+ id: req.storyId,
13811
+ prompt: req.prompt,
13812
+ cwd: this.opts.cwd,
13813
+ model: codexModel,
13814
+ retries: req.retries,
13815
+ timeoutSecs: req.timeoutSecs
13816
+ }) : llm === "openai" ? new OpenAIStoryAgent(
13227
13817
  {
13228
13818
  id: req.storyId,
13229
13819
  prompt: req.prompt,
@@ -13579,6 +14169,10 @@ async function orchestrate(config) {
13579
14169
  process.stderr.write(
13580
14170
  "[orchestrate] llm=openai: Architect, Planner, Critic, Surgeon, StoryAgent all running through Mozaik's native OpenAI runner (gpt-5.x).\n"
13581
14171
  );
14172
+ } else if (llm === "codex") {
14173
+ process.stderr.write(
14174
+ "[orchestrate] llm=codex: Story phase shells out to `codex exec --json` (ChatGPT subscription path). Architect / Planner / Critic / Surgeon fall back to Claude in v1 \u2014 codex-* siblings for those phases are a v2 follow-up.\n"
14175
+ );
13582
14176
  } else {
13583
14177
  process.stderr.write(
13584
14178
  "[orchestrate] llm=claude: every LLM phase shells out to the Claude Code CLI.\n"
@@ -14019,9 +14613,11 @@ function parseArgs(argv) {
14019
14613
  break;
14020
14614
  case "--llm": {
14021
14615
  const v = required(argv, ++i, "--llm");
14022
- if (v !== "claude" && v !== "openai") {
14023
- process.stderr.write(`[cli] --llm must be 'claude' or 'openai', got '${v}'
14024
- `);
14616
+ if (v !== "claude" && v !== "openai" && v !== "codex") {
14617
+ process.stderr.write(
14618
+ `[cli] --llm must be 'claude' | 'openai' | 'codex', got '${v}'
14619
+ `
14620
+ );
14025
14621
  process.exit(2);
14026
14622
  }
14027
14623
  args.llm = v;