baro-ai 0.23.6 → 0.25.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.
- package/dist/cli.mjs +134 -11
- package/dist/cli.mjs.map +1 -1
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -8049,11 +8049,13 @@ function normalizePrd(input, source) {
|
|
|
8049
8049
|
const branchName = typeof input.branchName === "string" ? input.branchName : "";
|
|
8050
8050
|
const description = typeof input.description === "string" ? input.description : "";
|
|
8051
8051
|
const stories = Array.isArray(input.userStories) ? input.userStories : [];
|
|
8052
|
+
const decisionDocument = typeof input.decisionDocument === "string" && input.decisionDocument.trim().length > 0 ? input.decisionDocument : void 0;
|
|
8052
8053
|
return {
|
|
8053
8054
|
project,
|
|
8054
8055
|
branchName,
|
|
8055
8056
|
description,
|
|
8056
|
-
userStories: stories.map((s, i) => normalizeStory(s, i, source))
|
|
8057
|
+
userStories: stories.map((s, i) => normalizeStory(s, i, source)),
|
|
8058
|
+
decisionDocument
|
|
8057
8059
|
};
|
|
8058
8060
|
}
|
|
8059
8061
|
function normalizeStory(input, index, source) {
|
|
@@ -8794,6 +8796,12 @@ var Conductor = class extends Participant {
|
|
|
8794
8796
|
spawnQueue = [];
|
|
8795
8797
|
/** Stories currently in flight in the active level. */
|
|
8796
8798
|
inFlight = /* @__PURE__ */ new Set();
|
|
8799
|
+
/**
|
|
8800
|
+
* Timer handle when we're deliberately spacing out intra-level
|
|
8801
|
+
* spawns. Re-entering `fillSpawnSlots` while this is set is a
|
|
8802
|
+
* no-op; the timer callback resumes pumping.
|
|
8803
|
+
*/
|
|
8804
|
+
pendingNextSpawn = null;
|
|
8797
8805
|
/** Resolved when the run terminates, exposed for callers that need it. */
|
|
8798
8806
|
done;
|
|
8799
8807
|
resolveDone;
|
|
@@ -8803,8 +8811,12 @@ var Conductor = class extends Participant {
|
|
|
8803
8811
|
parallel: 0,
|
|
8804
8812
|
timeoutSecs: 600,
|
|
8805
8813
|
defaultModel: "sonnet",
|
|
8814
|
+
intraLevelDelaySecs: 10,
|
|
8806
8815
|
...opts
|
|
8807
8816
|
};
|
|
8817
|
+
if (this.opts.intraLevelDelaySecs == null) {
|
|
8818
|
+
this.opts.intraLevelDelaySecs = 10;
|
|
8819
|
+
}
|
|
8808
8820
|
this.done = new Promise((resolve2) => {
|
|
8809
8821
|
this.resolveDone = resolve2;
|
|
8810
8822
|
});
|
|
@@ -8950,10 +8962,25 @@ var Conductor = class extends Participant {
|
|
|
8950
8962
|
}
|
|
8951
8963
|
async fillSpawnSlots() {
|
|
8952
8964
|
if (!this.currentLevel) return;
|
|
8965
|
+
if (this.pendingNextSpawn) return;
|
|
8953
8966
|
const cap = this.opts.parallel > 0 ? this.opts.parallel : Number.MAX_SAFE_INTEGER;
|
|
8967
|
+
const delaySecs = this.opts.intraLevelDelaySecs ?? 0;
|
|
8954
8968
|
while (this.spawnQueue.length > 0 && this.inFlight.size < cap) {
|
|
8955
8969
|
const story = this.spawnQueue.shift();
|
|
8956
8970
|
await this.requestStorySpawn(story);
|
|
8971
|
+
if (this.spawnQueue.length > 0 && this.inFlight.size < cap && delaySecs > 0) {
|
|
8972
|
+
this.pendingNextSpawn = setTimeout(() => {
|
|
8973
|
+
this.pendingNextSpawn = null;
|
|
8974
|
+
if (this.phase === "done") return;
|
|
8975
|
+
this.fillSpawnSlots().catch((err) => {
|
|
8976
|
+
process.stderr.write(
|
|
8977
|
+
`[conductor] fillSpawnSlots resume failed: ${err?.stack ?? String(err)}
|
|
8978
|
+
`
|
|
8979
|
+
);
|
|
8980
|
+
});
|
|
8981
|
+
}, delaySecs * 1e3);
|
|
8982
|
+
return;
|
|
8983
|
+
}
|
|
8957
8984
|
}
|
|
8958
8985
|
}
|
|
8959
8986
|
async requestStorySpawn(story) {
|
|
@@ -9085,13 +9112,32 @@ ${prompt}`;
|
|
|
9085
9112
|
}
|
|
9086
9113
|
resolvePrompt(story) {
|
|
9087
9114
|
const candidatePath = this.opts.promptTemplatePath ?? join(this.opts.cwd, "prompt.md");
|
|
9115
|
+
let prompt;
|
|
9088
9116
|
if (existsSync(candidatePath)) {
|
|
9089
9117
|
const tpl = readFileSyncSafe(candidatePath);
|
|
9090
|
-
|
|
9091
|
-
|
|
9092
|
-
|
|
9093
|
-
}
|
|
9094
|
-
|
|
9118
|
+
prompt = tpl ? applyTemplate(tpl, story) : buildDefaultStoryPrompt(story);
|
|
9119
|
+
} else {
|
|
9120
|
+
prompt = buildDefaultStoryPrompt(story);
|
|
9121
|
+
}
|
|
9122
|
+
const doc = this.prd?.decisionDocument;
|
|
9123
|
+
if (doc && doc.trim().length > 0) {
|
|
9124
|
+
const header = [
|
|
9125
|
+
"## Design spec (authoritative \u2014 already decided)",
|
|
9126
|
+
"",
|
|
9127
|
+
"The Architect made these decisions before any story started.",
|
|
9128
|
+
"Treat them as fixed: use these exact file paths, names,",
|
|
9129
|
+
"schemas, API shapes, and dependency choices. Do NOT",
|
|
9130
|
+
"improvise alternatives \u2014 your siblings are working from",
|
|
9131
|
+
"the same spec and divergence breaks the build.",
|
|
9132
|
+
"",
|
|
9133
|
+
doc.trim(),
|
|
9134
|
+
"",
|
|
9135
|
+
"---",
|
|
9136
|
+
""
|
|
9137
|
+
].join("\n");
|
|
9138
|
+
prompt = header + prompt;
|
|
9139
|
+
}
|
|
9140
|
+
return prompt;
|
|
9095
9141
|
}
|
|
9096
9142
|
emit(item) {
|
|
9097
9143
|
this.envRef?.deliverContextItem(this, item);
|
|
@@ -9785,15 +9831,21 @@ var EXPLORATION_TOOLS = /* @__PURE__ */ new Set([
|
|
|
9785
9831
|
"WebFetch",
|
|
9786
9832
|
"WebSearch"
|
|
9787
9833
|
]);
|
|
9834
|
+
var BROADCAST_TOOLS = /* @__PURE__ */ new Set(["Read", "Grep", "Glob", "LSP"]);
|
|
9788
9835
|
var Librarian = class extends Participant {
|
|
9789
9836
|
opts;
|
|
9790
9837
|
pending = /* @__PURE__ */ new Map();
|
|
9791
9838
|
knowledge = [];
|
|
9839
|
+
// Mid-flight bookkeeping
|
|
9840
|
+
inFlight = /* @__PURE__ */ new Set();
|
|
9841
|
+
storyHints = /* @__PURE__ */ new Map();
|
|
9842
|
+
broadcastBytes = /* @__PURE__ */ new Map();
|
|
9792
9843
|
constructor(opts = {}) {
|
|
9793
9844
|
super();
|
|
9794
9845
|
this.opts = {
|
|
9795
9846
|
maxContentChars: opts.maxContentChars ?? 4e3,
|
|
9796
|
-
maxInjectedChars: opts.maxInjectedChars ??
|
|
9847
|
+
maxInjectedChars: opts.maxInjectedChars ?? 2e4,
|
|
9848
|
+
maxBroadcastBytesPerStory: opts.maxBroadcastBytesPerStory ?? 5e4
|
|
9797
9849
|
};
|
|
9798
9850
|
}
|
|
9799
9851
|
/** All indexed knowledge entries, in order discovered. */
|
|
@@ -9834,9 +9886,11 @@ var Librarian = class extends Participant {
|
|
|
9834
9886
|
}
|
|
9835
9887
|
if (lines.length === 0) return null;
|
|
9836
9888
|
return [
|
|
9837
|
-
"
|
|
9838
|
-
"
|
|
9839
|
-
"
|
|
9889
|
+
"## Codebase context (current as of this run)",
|
|
9890
|
+
"",
|
|
9891
|
+
"The following file contents and discovery results are authoritative",
|
|
9892
|
+
"and up-to-date. Do not re-read or re-search unless you have specific",
|
|
9893
|
+
"reason to suspect a file has changed since these were captured.",
|
|
9840
9894
|
"",
|
|
9841
9895
|
...lines
|
|
9842
9896
|
].join("\n");
|
|
@@ -9850,6 +9904,18 @@ var Librarian = class extends Participant {
|
|
|
9850
9904
|
this.completeWithOutput(source, item);
|
|
9851
9905
|
return;
|
|
9852
9906
|
}
|
|
9907
|
+
if (item instanceof StorySpawnRequestItem) {
|
|
9908
|
+
this.storyHints.set(item.storyId, tokenizeHints(item.prompt));
|
|
9909
|
+
return;
|
|
9910
|
+
}
|
|
9911
|
+
if (item instanceof StorySpawnedItem) {
|
|
9912
|
+
this.inFlight.add(item.storyId);
|
|
9913
|
+
return;
|
|
9914
|
+
}
|
|
9915
|
+
if (item instanceof StoryResultItem) {
|
|
9916
|
+
this.inFlight.delete(item.storyId);
|
|
9917
|
+
return;
|
|
9918
|
+
}
|
|
9853
9919
|
}
|
|
9854
9920
|
recordPending(source, item) {
|
|
9855
9921
|
if (!EXPLORATION_TOOLS.has(item.name)) return;
|
|
@@ -9896,6 +9962,51 @@ var Librarian = class extends Participant {
|
|
|
9896
9962
|
)
|
|
9897
9963
|
);
|
|
9898
9964
|
}
|
|
9965
|
+
if (BROADCAST_TOOLS.has(entry.tool)) {
|
|
9966
|
+
this.broadcastFinding(entry);
|
|
9967
|
+
}
|
|
9968
|
+
}
|
|
9969
|
+
broadcastFinding(finding) {
|
|
9970
|
+
if (this.inFlight.size === 0) return;
|
|
9971
|
+
const envs = this.getEnvironments();
|
|
9972
|
+
if (envs.length === 0) return;
|
|
9973
|
+
const findingTokens = new Set(
|
|
9974
|
+
[...finding.tags, finding.summary].join(" ").toLowerCase().split(/[^a-z0-9_/.\\-]+/).filter((t) => t.length >= 3)
|
|
9975
|
+
);
|
|
9976
|
+
const block = formatEntry(finding);
|
|
9977
|
+
const text = [
|
|
9978
|
+
"## Just-in-time codebase context",
|
|
9979
|
+
"",
|
|
9980
|
+
`Another agent in this run (${finding.sourceAgentId}) just`,
|
|
9981
|
+
"discovered the following. It is authoritative and current;",
|
|
9982
|
+
"use it directly without re-fetching.",
|
|
9983
|
+
"",
|
|
9984
|
+
block
|
|
9985
|
+
].join("\n");
|
|
9986
|
+
const bytes = text.length;
|
|
9987
|
+
for (const recipientId of this.inFlight) {
|
|
9988
|
+
if (recipientId === finding.sourceAgentId) continue;
|
|
9989
|
+
const recipientHints = this.storyHints.get(recipientId) ?? [];
|
|
9990
|
+
if (recipientHints.length > 0) {
|
|
9991
|
+
const overlap = recipientHints.some(
|
|
9992
|
+
(h) => findingTokens.has(h.toLowerCase())
|
|
9993
|
+
);
|
|
9994
|
+
if (!overlap) continue;
|
|
9995
|
+
}
|
|
9996
|
+
const already = this.broadcastBytes.get(recipientId) ?? 0;
|
|
9997
|
+
if (already + bytes > this.opts.maxBroadcastBytesPerStory) continue;
|
|
9998
|
+
this.broadcastBytes.set(recipientId, already + bytes);
|
|
9999
|
+
for (const env of envs) {
|
|
10000
|
+
env.deliverContextItem(
|
|
10001
|
+
this,
|
|
10002
|
+
new AgentTargetedMessageItem(recipientId, text, {
|
|
10003
|
+
source: "librarian",
|
|
10004
|
+
finding: finding.summary,
|
|
10005
|
+
from_agent: finding.sourceAgentId
|
|
10006
|
+
})
|
|
10007
|
+
);
|
|
10008
|
+
}
|
|
10009
|
+
}
|
|
9899
10010
|
}
|
|
9900
10011
|
};
|
|
9901
10012
|
function describeCall(tool, args) {
|
|
@@ -9948,6 +10059,9 @@ function formatEntry(k) {
|
|
|
9948
10059
|
""
|
|
9949
10060
|
].join("\n");
|
|
9950
10061
|
}
|
|
10062
|
+
function tokenizeHints(prompt) {
|
|
10063
|
+
return prompt.toLowerCase().split(/[^a-z0-9_/.\-]+/).filter((t) => t.length >= 3);
|
|
10064
|
+
}
|
|
9951
10065
|
|
|
9952
10066
|
// ../baro-orchestrator/src/participants/operator.ts
|
|
9953
10067
|
var Operator = class extends Participant {
|
|
@@ -10412,6 +10526,7 @@ async function orchestrate(config) {
|
|
|
10412
10526
|
timeoutSecs: config.timeoutSecs ?? 600,
|
|
10413
10527
|
overrideModel: config.overrideModel ?? void 0,
|
|
10414
10528
|
defaultModel: config.defaultModel ?? "opus",
|
|
10529
|
+
intraLevelDelaySecs: config.intraLevelDelaySecs,
|
|
10415
10530
|
onRunStart: useGit ? async (prd) => {
|
|
10416
10531
|
baseSha = await getHeadSha(config.cwd);
|
|
10417
10532
|
if (prd.branchName) {
|
|
@@ -10750,6 +10865,12 @@ function parseArgs(argv) {
|
|
|
10750
10865
|
case "--surgeon-model":
|
|
10751
10866
|
args.surgeonModel = required(argv, ++i, "--surgeon-model");
|
|
10752
10867
|
break;
|
|
10868
|
+
case "--intra-level-delay":
|
|
10869
|
+
args.intraLevelDelaySecs = parseInt(
|
|
10870
|
+
required(argv, ++i, "--intra-level-delay"),
|
|
10871
|
+
10
|
|
10872
|
+
);
|
|
10873
|
+
break;
|
|
10753
10874
|
default:
|
|
10754
10875
|
process.stderr.write(`[cli] unknown flag: ${a}
|
|
10755
10876
|
`);
|
|
@@ -10791,6 +10912,7 @@ function printHelp() {
|
|
|
10791
10912
|
" --with-surgeon Enable Surgeon (adaptive DAG mutation)",
|
|
10792
10913
|
" --surgeon-use-llm Use LLM evaluation in Surgeon (default: deterministic)",
|
|
10793
10914
|
" --surgeon-model <name> Model for Surgeon LLM (default: opus)",
|
|
10915
|
+
" --intra-level-delay <secs> Stagger story spawns within a level (default: 10, 0 disables)",
|
|
10794
10916
|
" -h, --help Show this message",
|
|
10795
10917
|
""
|
|
10796
10918
|
].join("\n")
|
|
@@ -10825,7 +10947,8 @@ async function main() {
|
|
|
10825
10947
|
withSentry: args.noSentry ? false : void 0,
|
|
10826
10948
|
withSurgeon: args.withSurgeon,
|
|
10827
10949
|
surgeonUseLlm: args.surgeonUseLlm,
|
|
10828
|
-
surgeonModel: args.surgeonModel
|
|
10950
|
+
surgeonModel: args.surgeonModel,
|
|
10951
|
+
intraLevelDelaySecs: args.intraLevelDelaySecs
|
|
10829
10952
|
};
|
|
10830
10953
|
process.stderr.write(
|
|
10831
10954
|
`[cli] starting orchestrator: prd=${prdPath} cwd=${cwd} parallel=${args.parallel} timeout=${args.timeout}s
|