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 +606 -10
- package/dist/cli.mjs.map +1 -1
- package/dist/run-architect.mjs +8 -5
- package/dist/run-architect.mjs.map +1 -1
- package/dist/run-planner.mjs +5 -4
- package/dist/run-planner.mjs.map +1 -1
- package/package.json +1 -1
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
|
|
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 =
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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(
|
|
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;
|