baro-ai 0.51.4 → 0.51.5
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 +242 -159
- package/dist/cli.mjs.map +1 -1
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -40350,6 +40350,150 @@ function buildDag(stories, options = {}) {
|
|
|
40350
40350
|
return levels;
|
|
40351
40351
|
}
|
|
40352
40352
|
|
|
40353
|
+
// ../baro-orchestrator/src/routing.ts
|
|
40354
|
+
var BACKENDS = ["claude", "openai", "codex", "opencode", "pi"];
|
|
40355
|
+
function isBackend(s2) {
|
|
40356
|
+
return BACKENDS.includes(s2);
|
|
40357
|
+
}
|
|
40358
|
+
var CLAUDE_TIER_RE = /^(opus|sonnet|haiku)\b/i;
|
|
40359
|
+
function isClaudeTierName(s2) {
|
|
40360
|
+
return CLAUDE_TIER_RE.test(s2.trim());
|
|
40361
|
+
}
|
|
40362
|
+
function splitBackendModel(raw) {
|
|
40363
|
+
const trimmed = raw.trim();
|
|
40364
|
+
if (!trimmed) return {};
|
|
40365
|
+
const idx = trimmed.indexOf(":");
|
|
40366
|
+
if (idx > 0) {
|
|
40367
|
+
const prefix = trimmed.slice(0, idx).toLowerCase();
|
|
40368
|
+
if (isBackend(prefix)) {
|
|
40369
|
+
const model = trimmed.slice(idx + 1).trim();
|
|
40370
|
+
return { backend: prefix, model: model.length ? model : void 0 };
|
|
40371
|
+
}
|
|
40372
|
+
}
|
|
40373
|
+
if (isBackend(trimmed.toLowerCase())) {
|
|
40374
|
+
return { backend: trimmed.toLowerCase() };
|
|
40375
|
+
}
|
|
40376
|
+
return { model: trimmed };
|
|
40377
|
+
}
|
|
40378
|
+
function looksLikeUrl(s2) {
|
|
40379
|
+
return /^https?:\/\//i.test(s2.trim());
|
|
40380
|
+
}
|
|
40381
|
+
function splitModelEndpoint(model) {
|
|
40382
|
+
const at = model.indexOf("@");
|
|
40383
|
+
if (at < 0) return { model };
|
|
40384
|
+
const ref = model.slice(at + 1).trim();
|
|
40385
|
+
return { model: model.slice(0, at).trim(), endpointRef: ref || void 0 };
|
|
40386
|
+
}
|
|
40387
|
+
function resolveEndpoint(ref, opts) {
|
|
40388
|
+
if (looksLikeUrl(ref)) {
|
|
40389
|
+
return { baseUrl: ref, apiKey: opts.defaultApiKey };
|
|
40390
|
+
}
|
|
40391
|
+
const ep = opts.endpoints?.[ref.toLowerCase()] ?? opts.endpoints?.[ref];
|
|
40392
|
+
if (!ep) {
|
|
40393
|
+
throw new Error(
|
|
40394
|
+
`unknown OpenAI endpoint "${ref}" \u2014 define it with --openai-endpoint ${ref}=<url> or use an inline https:// URL`
|
|
40395
|
+
);
|
|
40396
|
+
}
|
|
40397
|
+
return { baseUrl: ep.baseUrl, apiKey: ep.apiKey ?? opts.defaultApiKey };
|
|
40398
|
+
}
|
|
40399
|
+
function resolveStoryRoute(rawModel, opts) {
|
|
40400
|
+
const raw = (opts.override ?? rawModel ?? "").trim();
|
|
40401
|
+
if (!raw) return defaultRoute(opts.fallbackBackend, opts.openaiDefaultModel);
|
|
40402
|
+
const direct = splitBackendModel(raw);
|
|
40403
|
+
if (direct.backend === void 0 && opts.tierMap) {
|
|
40404
|
+
const mapped = opts.tierMap[raw.toLowerCase()] ?? opts.tierMap[raw];
|
|
40405
|
+
if (mapped) {
|
|
40406
|
+
return resolveStoryRoute(mapped, {
|
|
40407
|
+
...opts,
|
|
40408
|
+
override: void 0,
|
|
40409
|
+
tierMap: void 0
|
|
40410
|
+
});
|
|
40411
|
+
}
|
|
40412
|
+
}
|
|
40413
|
+
if (direct.backend) {
|
|
40414
|
+
if (direct.model) return buildRoute(direct.backend, direct.model, opts);
|
|
40415
|
+
return defaultRoute(direct.backend, opts.openaiDefaultModel);
|
|
40416
|
+
}
|
|
40417
|
+
const backend = opts.fallbackBackend;
|
|
40418
|
+
if (backend === "claude") {
|
|
40419
|
+
return { backend, model: direct.model };
|
|
40420
|
+
}
|
|
40421
|
+
if (direct.model && !isClaudeTierName(direct.model)) {
|
|
40422
|
+
return buildRoute(backend, direct.model, opts);
|
|
40423
|
+
}
|
|
40424
|
+
return defaultRoute(backend, opts.openaiDefaultModel);
|
|
40425
|
+
}
|
|
40426
|
+
function buildRoute(backend, model, opts) {
|
|
40427
|
+
if (backend !== "openai") return { backend, model };
|
|
40428
|
+
const { model: bareModel, endpointRef } = splitModelEndpoint(model);
|
|
40429
|
+
if (!endpointRef) return { backend, model: bareModel };
|
|
40430
|
+
const ep = resolveEndpoint(endpointRef, opts);
|
|
40431
|
+
return { backend, model: bareModel, baseUrl: ep.baseUrl, apiKey: ep.apiKey };
|
|
40432
|
+
}
|
|
40433
|
+
function defaultRoute(backend, openaiDefaultModel) {
|
|
40434
|
+
if (backend === "openai") return { backend, model: openaiDefaultModel };
|
|
40435
|
+
return { backend };
|
|
40436
|
+
}
|
|
40437
|
+
function parseTierMap(spec) {
|
|
40438
|
+
const map = {};
|
|
40439
|
+
for (const part of spec.split(",")) {
|
|
40440
|
+
const seg = part.trim();
|
|
40441
|
+
if (!seg) continue;
|
|
40442
|
+
const eq = seg.indexOf("=");
|
|
40443
|
+
if (eq <= 0) {
|
|
40444
|
+
throw new Error(
|
|
40445
|
+
`bad --tier-map entry "${seg}" (expected tier=backend:model)`
|
|
40446
|
+
);
|
|
40447
|
+
}
|
|
40448
|
+
const tier = seg.slice(0, eq).trim().toLowerCase();
|
|
40449
|
+
const route = seg.slice(eq + 1).trim();
|
|
40450
|
+
if (!tier || !route) {
|
|
40451
|
+
throw new Error(
|
|
40452
|
+
`bad --tier-map entry "${seg}" (expected tier=backend:model)`
|
|
40453
|
+
);
|
|
40454
|
+
}
|
|
40455
|
+
const { backend } = splitBackendModel(route);
|
|
40456
|
+
if (!backend) {
|
|
40457
|
+
throw new Error(
|
|
40458
|
+
`--tier-map route "${route}" for tier "${tier}" must name a backend (claude: | openai: | codex: | opencode: | pi:)`
|
|
40459
|
+
);
|
|
40460
|
+
}
|
|
40461
|
+
map[tier] = route;
|
|
40462
|
+
}
|
|
40463
|
+
return map;
|
|
40464
|
+
}
|
|
40465
|
+
function parseEndpoints(specs, keyFor) {
|
|
40466
|
+
const map = {};
|
|
40467
|
+
for (const raw of specs) {
|
|
40468
|
+
const spec = raw.trim();
|
|
40469
|
+
if (!spec) continue;
|
|
40470
|
+
const eq = spec.indexOf("=");
|
|
40471
|
+
if (eq <= 0) {
|
|
40472
|
+
throw new Error(
|
|
40473
|
+
`bad --openai-endpoint "${spec}" (expected name=url)`
|
|
40474
|
+
);
|
|
40475
|
+
}
|
|
40476
|
+
const name = spec.slice(0, eq).trim().toLowerCase();
|
|
40477
|
+
const url = spec.slice(eq + 1).trim();
|
|
40478
|
+
if (!name || !url) {
|
|
40479
|
+
throw new Error(
|
|
40480
|
+
`bad --openai-endpoint "${spec}" (expected name=url)`
|
|
40481
|
+
);
|
|
40482
|
+
}
|
|
40483
|
+
if (!looksLikeUrl(url)) {
|
|
40484
|
+
throw new Error(
|
|
40485
|
+
`--openai-endpoint "${name}" url "${url}" must start with http:// or https://`
|
|
40486
|
+
);
|
|
40487
|
+
}
|
|
40488
|
+
map[name] = { baseUrl: url, apiKey: keyFor?.(name) };
|
|
40489
|
+
}
|
|
40490
|
+
return map;
|
|
40491
|
+
}
|
|
40492
|
+
function formatRoute(route) {
|
|
40493
|
+
const base = route.model ? `${route.backend}:${route.model}` : route.backend;
|
|
40494
|
+
return route.baseUrl ? `${base}@${route.baseUrl}` : base;
|
|
40495
|
+
}
|
|
40496
|
+
|
|
40353
40497
|
// ../baro-orchestrator/src/participants/auditor.ts
|
|
40354
40498
|
import { appendFileSync, mkdirSync } from "fs";
|
|
40355
40499
|
import { dirname } from "path";
|
|
@@ -42914,9 +43058,16 @@ var ProgressForwarder = class extends BaseObserver {
|
|
|
42914
43058
|
};
|
|
42915
43059
|
|
|
42916
43060
|
// ../baro-orchestrator/src/participants/forwarders/story-lifecycle.ts
|
|
43061
|
+
var CREATE_TOOLS = /* @__PURE__ */ new Set(["Write", "write_file"]);
|
|
43062
|
+
var EDIT_TOOLS = /* @__PURE__ */ new Set(["Edit", "MultiEdit", "NotebookEdit", "edit_file"]);
|
|
42917
43063
|
var StoryLifecycleForwarder = class extends BaseObserver {
|
|
42918
43064
|
startedStories = /* @__PURE__ */ new Set();
|
|
42919
43065
|
retryCounts = /* @__PURE__ */ new Map();
|
|
43066
|
+
// storyId → (path → first-touch kind). Distinct paths per story, so a
|
|
43067
|
+
// file touched many times counts once, classified by its first write.
|
|
43068
|
+
// Reset on each retry so story_complete reflects only the winning
|
|
43069
|
+
// attempt's touches, not files a failed attempt wrote and abandoned.
|
|
43070
|
+
filesByStory = /* @__PURE__ */ new Map();
|
|
42920
43071
|
async onExternalEvent(_source, event) {
|
|
42921
43072
|
if (AgentState.is(event)) {
|
|
42922
43073
|
this.handleAgentState(event.data);
|
|
@@ -42927,6 +43078,27 @@ var StoryLifecycleForwarder = class extends BaseObserver {
|
|
|
42927
43078
|
return;
|
|
42928
43079
|
}
|
|
42929
43080
|
}
|
|
43081
|
+
// Same signal the Sentry uses: a write/edit tool call from a story
|
|
43082
|
+
// agent. We attribute the touched path to that agent's story and
|
|
43083
|
+
// remember its first-touch kind so story_complete can report real
|
|
43084
|
+
// per-story file counts instead of a hardcoded 0.
|
|
43085
|
+
async onExternalFunctionCall(source, item) {
|
|
43086
|
+
const isCreate = CREATE_TOOLS.has(item.name);
|
|
43087
|
+
const isEdit = EDIT_TOOLS.has(item.name);
|
|
43088
|
+
if (!isCreate && !isEdit) return;
|
|
43089
|
+
const agentId = source.agentId;
|
|
43090
|
+
if (typeof agentId !== "string") return;
|
|
43091
|
+
const path6 = extractPath(item);
|
|
43092
|
+
if (!path6) return;
|
|
43093
|
+
let paths = this.filesByStory.get(agentId);
|
|
43094
|
+
if (!paths) {
|
|
43095
|
+
paths = /* @__PURE__ */ new Map();
|
|
43096
|
+
this.filesByStory.set(agentId, paths);
|
|
43097
|
+
}
|
|
43098
|
+
if (!paths.has(path6)) {
|
|
43099
|
+
paths.set(path6, isCreate ? "created" : "modified");
|
|
43100
|
+
}
|
|
43101
|
+
}
|
|
42930
43102
|
handleAgentState(item) {
|
|
42931
43103
|
if (item.phase === "running" && !this.startedStories.has(item.agentId)) {
|
|
42932
43104
|
this.startedStories.add(item.agentId);
|
|
@@ -42935,19 +43107,31 @@ var StoryLifecycleForwarder = class extends BaseObserver {
|
|
|
42935
43107
|
if (item.phase === "waiting" && item.detail?.includes("retrying")) {
|
|
42936
43108
|
const count = (this.retryCounts.get(item.agentId) ?? 0) + 1;
|
|
42937
43109
|
this.retryCounts.set(item.agentId, count);
|
|
43110
|
+
this.filesByStory.delete(item.agentId);
|
|
42938
43111
|
emit({ type: "story_retry", id: item.agentId, attempt: count });
|
|
42939
43112
|
}
|
|
42940
43113
|
}
|
|
42941
43114
|
handleStoryResult(item) {
|
|
42942
43115
|
if (item.success) {
|
|
43116
|
+
const paths = this.filesByStory.get(item.storyId);
|
|
43117
|
+
let created = 0;
|
|
43118
|
+
let modified = 0;
|
|
43119
|
+
if (paths) {
|
|
43120
|
+
for (const kind of paths.values()) {
|
|
43121
|
+
if (kind === "created") created++;
|
|
43122
|
+
else modified++;
|
|
43123
|
+
}
|
|
43124
|
+
}
|
|
43125
|
+
this.filesByStory.delete(item.storyId);
|
|
42943
43126
|
emit({
|
|
42944
43127
|
type: "story_complete",
|
|
42945
43128
|
id: item.storyId,
|
|
42946
43129
|
duration_secs: item.durationSecs,
|
|
42947
|
-
files_created:
|
|
42948
|
-
files_modified:
|
|
43130
|
+
files_created: created,
|
|
43131
|
+
files_modified: modified
|
|
42949
43132
|
});
|
|
42950
43133
|
} else {
|
|
43134
|
+
this.filesByStory.delete(item.storyId);
|
|
42951
43135
|
emit({
|
|
42952
43136
|
type: "story_error",
|
|
42953
43137
|
id: item.storyId,
|
|
@@ -42958,6 +43142,19 @@ var StoryLifecycleForwarder = class extends BaseObserver {
|
|
|
42958
43142
|
}
|
|
42959
43143
|
}
|
|
42960
43144
|
};
|
|
43145
|
+
function extractPath(item) {
|
|
43146
|
+
let args;
|
|
43147
|
+
try {
|
|
43148
|
+
args = JSON.parse(item.args);
|
|
43149
|
+
} catch {
|
|
43150
|
+
return null;
|
|
43151
|
+
}
|
|
43152
|
+
for (const key of ["file_path", "path", "notebook_path"]) {
|
|
43153
|
+
const v = args[key];
|
|
43154
|
+
if (typeof v === "string") return v;
|
|
43155
|
+
}
|
|
43156
|
+
return null;
|
|
43157
|
+
}
|
|
42961
43158
|
|
|
42962
43159
|
// ../baro-orchestrator/src/participants/forwarders/token-usage.ts
|
|
42963
43160
|
var TokenUsageForwarder = class extends BaseObserver {
|
|
@@ -43594,7 +43791,7 @@ var Sentry = class extends BaseObserver {
|
|
|
43594
43791
|
if (!WRITE_TOOLS.has(item.name)) return;
|
|
43595
43792
|
const agentId = source.agentId;
|
|
43596
43793
|
if (typeof agentId !== "string") return;
|
|
43597
|
-
const path6 =
|
|
43794
|
+
const path6 = extractPath2(item);
|
|
43598
43795
|
if (!path6) return;
|
|
43599
43796
|
const touch = {
|
|
43600
43797
|
agentId,
|
|
@@ -43629,7 +43826,7 @@ var Sentry = class extends BaseObserver {
|
|
|
43629
43826
|
}
|
|
43630
43827
|
}
|
|
43631
43828
|
};
|
|
43632
|
-
function
|
|
43829
|
+
function extractPath2(item) {
|
|
43633
43830
|
let args;
|
|
43634
43831
|
try {
|
|
43635
43832
|
args = JSON.parse(item.args);
|
|
@@ -47014,150 +47211,6 @@ function raceWithTimeout4(p, ms, label) {
|
|
|
47014
47211
|
]);
|
|
47015
47212
|
}
|
|
47016
47213
|
|
|
47017
|
-
// ../baro-orchestrator/src/routing.ts
|
|
47018
|
-
var BACKENDS = ["claude", "openai", "codex", "opencode", "pi"];
|
|
47019
|
-
function isBackend(s2) {
|
|
47020
|
-
return BACKENDS.includes(s2);
|
|
47021
|
-
}
|
|
47022
|
-
var CLAUDE_TIER_RE = /^(opus|sonnet|haiku)\b/i;
|
|
47023
|
-
function isClaudeTierName(s2) {
|
|
47024
|
-
return CLAUDE_TIER_RE.test(s2.trim());
|
|
47025
|
-
}
|
|
47026
|
-
function splitBackendModel(raw) {
|
|
47027
|
-
const trimmed = raw.trim();
|
|
47028
|
-
if (!trimmed) return {};
|
|
47029
|
-
const idx = trimmed.indexOf(":");
|
|
47030
|
-
if (idx > 0) {
|
|
47031
|
-
const prefix = trimmed.slice(0, idx).toLowerCase();
|
|
47032
|
-
if (isBackend(prefix)) {
|
|
47033
|
-
const model = trimmed.slice(idx + 1).trim();
|
|
47034
|
-
return { backend: prefix, model: model.length ? model : void 0 };
|
|
47035
|
-
}
|
|
47036
|
-
}
|
|
47037
|
-
if (isBackend(trimmed.toLowerCase())) {
|
|
47038
|
-
return { backend: trimmed.toLowerCase() };
|
|
47039
|
-
}
|
|
47040
|
-
return { model: trimmed };
|
|
47041
|
-
}
|
|
47042
|
-
function looksLikeUrl(s2) {
|
|
47043
|
-
return /^https?:\/\//i.test(s2.trim());
|
|
47044
|
-
}
|
|
47045
|
-
function splitModelEndpoint(model) {
|
|
47046
|
-
const at = model.indexOf("@");
|
|
47047
|
-
if (at < 0) return { model };
|
|
47048
|
-
const ref = model.slice(at + 1).trim();
|
|
47049
|
-
return { model: model.slice(0, at).trim(), endpointRef: ref || void 0 };
|
|
47050
|
-
}
|
|
47051
|
-
function resolveEndpoint(ref, opts) {
|
|
47052
|
-
if (looksLikeUrl(ref)) {
|
|
47053
|
-
return { baseUrl: ref, apiKey: opts.defaultApiKey };
|
|
47054
|
-
}
|
|
47055
|
-
const ep = opts.endpoints?.[ref.toLowerCase()] ?? opts.endpoints?.[ref];
|
|
47056
|
-
if (!ep) {
|
|
47057
|
-
throw new Error(
|
|
47058
|
-
`unknown OpenAI endpoint "${ref}" \u2014 define it with --openai-endpoint ${ref}=<url> or use an inline https:// URL`
|
|
47059
|
-
);
|
|
47060
|
-
}
|
|
47061
|
-
return { baseUrl: ep.baseUrl, apiKey: ep.apiKey ?? opts.defaultApiKey };
|
|
47062
|
-
}
|
|
47063
|
-
function resolveStoryRoute(rawModel, opts) {
|
|
47064
|
-
const raw = (opts.override ?? rawModel ?? "").trim();
|
|
47065
|
-
if (!raw) return defaultRoute(opts.fallbackBackend, opts.openaiDefaultModel);
|
|
47066
|
-
const direct = splitBackendModel(raw);
|
|
47067
|
-
if (direct.backend === void 0 && opts.tierMap) {
|
|
47068
|
-
const mapped = opts.tierMap[raw.toLowerCase()] ?? opts.tierMap[raw];
|
|
47069
|
-
if (mapped) {
|
|
47070
|
-
return resolveStoryRoute(mapped, {
|
|
47071
|
-
...opts,
|
|
47072
|
-
override: void 0,
|
|
47073
|
-
tierMap: void 0
|
|
47074
|
-
});
|
|
47075
|
-
}
|
|
47076
|
-
}
|
|
47077
|
-
if (direct.backend) {
|
|
47078
|
-
if (direct.model) return buildRoute(direct.backend, direct.model, opts);
|
|
47079
|
-
return defaultRoute(direct.backend, opts.openaiDefaultModel);
|
|
47080
|
-
}
|
|
47081
|
-
const backend = opts.fallbackBackend;
|
|
47082
|
-
if (backend === "claude") {
|
|
47083
|
-
return { backend, model: direct.model };
|
|
47084
|
-
}
|
|
47085
|
-
if (direct.model && !isClaudeTierName(direct.model)) {
|
|
47086
|
-
return buildRoute(backend, direct.model, opts);
|
|
47087
|
-
}
|
|
47088
|
-
return defaultRoute(backend, opts.openaiDefaultModel);
|
|
47089
|
-
}
|
|
47090
|
-
function buildRoute(backend, model, opts) {
|
|
47091
|
-
if (backend !== "openai") return { backend, model };
|
|
47092
|
-
const { model: bareModel, endpointRef } = splitModelEndpoint(model);
|
|
47093
|
-
if (!endpointRef) return { backend, model: bareModel };
|
|
47094
|
-
const ep = resolveEndpoint(endpointRef, opts);
|
|
47095
|
-
return { backend, model: bareModel, baseUrl: ep.baseUrl, apiKey: ep.apiKey };
|
|
47096
|
-
}
|
|
47097
|
-
function defaultRoute(backend, openaiDefaultModel) {
|
|
47098
|
-
if (backend === "openai") return { backend, model: openaiDefaultModel };
|
|
47099
|
-
return { backend };
|
|
47100
|
-
}
|
|
47101
|
-
function parseTierMap(spec) {
|
|
47102
|
-
const map = {};
|
|
47103
|
-
for (const part of spec.split(",")) {
|
|
47104
|
-
const seg = part.trim();
|
|
47105
|
-
if (!seg) continue;
|
|
47106
|
-
const eq = seg.indexOf("=");
|
|
47107
|
-
if (eq <= 0) {
|
|
47108
|
-
throw new Error(
|
|
47109
|
-
`bad --tier-map entry "${seg}" (expected tier=backend:model)`
|
|
47110
|
-
);
|
|
47111
|
-
}
|
|
47112
|
-
const tier = seg.slice(0, eq).trim().toLowerCase();
|
|
47113
|
-
const route = seg.slice(eq + 1).trim();
|
|
47114
|
-
if (!tier || !route) {
|
|
47115
|
-
throw new Error(
|
|
47116
|
-
`bad --tier-map entry "${seg}" (expected tier=backend:model)`
|
|
47117
|
-
);
|
|
47118
|
-
}
|
|
47119
|
-
const { backend } = splitBackendModel(route);
|
|
47120
|
-
if (!backend) {
|
|
47121
|
-
throw new Error(
|
|
47122
|
-
`--tier-map route "${route}" for tier "${tier}" must name a backend (claude: | openai: | codex: | opencode: | pi:)`
|
|
47123
|
-
);
|
|
47124
|
-
}
|
|
47125
|
-
map[tier] = route;
|
|
47126
|
-
}
|
|
47127
|
-
return map;
|
|
47128
|
-
}
|
|
47129
|
-
function parseEndpoints(specs, keyFor) {
|
|
47130
|
-
const map = {};
|
|
47131
|
-
for (const raw of specs) {
|
|
47132
|
-
const spec = raw.trim();
|
|
47133
|
-
if (!spec) continue;
|
|
47134
|
-
const eq = spec.indexOf("=");
|
|
47135
|
-
if (eq <= 0) {
|
|
47136
|
-
throw new Error(
|
|
47137
|
-
`bad --openai-endpoint "${spec}" (expected name=url)`
|
|
47138
|
-
);
|
|
47139
|
-
}
|
|
47140
|
-
const name = spec.slice(0, eq).trim().toLowerCase();
|
|
47141
|
-
const url = spec.slice(eq + 1).trim();
|
|
47142
|
-
if (!name || !url) {
|
|
47143
|
-
throw new Error(
|
|
47144
|
-
`bad --openai-endpoint "${spec}" (expected name=url)`
|
|
47145
|
-
);
|
|
47146
|
-
}
|
|
47147
|
-
if (!looksLikeUrl(url)) {
|
|
47148
|
-
throw new Error(
|
|
47149
|
-
`--openai-endpoint "${name}" url "${url}" must start with http:// or https://`
|
|
47150
|
-
);
|
|
47151
|
-
}
|
|
47152
|
-
map[name] = { baseUrl: url, apiKey: keyFor?.(name) };
|
|
47153
|
-
}
|
|
47154
|
-
return map;
|
|
47155
|
-
}
|
|
47156
|
-
function formatRoute(route) {
|
|
47157
|
-
const base = route.model ? `${route.backend}:${route.model}` : route.backend;
|
|
47158
|
-
return route.baseUrl ? `${base}@${route.baseUrl}` : base;
|
|
47159
|
-
}
|
|
47160
|
-
|
|
47161
47214
|
// ../baro-orchestrator/src/participants/story-factory.ts
|
|
47162
47215
|
var StoryFactory = class extends BaseObserver {
|
|
47163
47216
|
constructor(opts) {
|
|
@@ -47347,7 +47400,8 @@ var Surgeon = class extends BaseObserver {
|
|
|
47347
47400
|
maxReplans: opts.maxReplans ?? 10,
|
|
47348
47401
|
claudeBin: opts.claudeBin ?? "claude",
|
|
47349
47402
|
timeoutMs: opts.timeoutMs ?? 9e4,
|
|
47350
|
-
snapshot: opts.snapshot
|
|
47403
|
+
snapshot: opts.snapshot,
|
|
47404
|
+
resolveRoute: opts.resolveRoute
|
|
47351
47405
|
};
|
|
47352
47406
|
}
|
|
47353
47407
|
/** Resolves once every in-flight LLM evaluation has completed. */
|
|
@@ -47386,7 +47440,7 @@ var Surgeon = class extends BaseObserver {
|
|
|
47386
47440
|
*/
|
|
47387
47441
|
async evaluateWithLlm(failure) {
|
|
47388
47442
|
const snap = this.opts.snapshot();
|
|
47389
|
-
const prompt = buildSurgeonPrompt(snap, failure);
|
|
47443
|
+
const prompt = buildSurgeonPrompt(snap, failure, this.opts.resolveRoute);
|
|
47390
47444
|
try {
|
|
47391
47445
|
const { stdout } = await execFileAsync3(
|
|
47392
47446
|
this.opts.claudeBin,
|
|
@@ -47436,11 +47490,12 @@ var Surgeon = class extends BaseObserver {
|
|
|
47436
47490
|
}
|
|
47437
47491
|
}
|
|
47438
47492
|
};
|
|
47439
|
-
function buildSurgeonPrompt(snap, failure) {
|
|
47493
|
+
function buildSurgeonPrompt(snap, failure, resolveRoute) {
|
|
47440
47494
|
const storyLines = snap.stories.map(
|
|
47441
47495
|
(s2) => ` - ${s2.id} ${s2.passes ? "[passed]" : "[pending]"} ${s2.model ? `<tier:${s2.model}> ` : ""}"${s2.title}" deps=${JSON.stringify(s2.dependsOn)}`
|
|
47442
47496
|
).join("\n");
|
|
47443
47497
|
const failureStory = snap.stories.find((s2) => s2.id === failure.storyId);
|
|
47498
|
+
const ranOn = resolveRoute ? resolveRoute(failureStory?.model) : null;
|
|
47444
47499
|
return [
|
|
47445
47500
|
`# Project: ${snap.project}`,
|
|
47446
47501
|
`Description: ${snap.description}`,
|
|
@@ -47453,6 +47508,9 @@ function buildSurgeonPrompt(snap, failure) {
|
|
|
47453
47508
|
`Title: ${failureStory?.title ?? "(unknown)"}`,
|
|
47454
47509
|
`Description: ${failureStory?.description ?? "(unknown)"}`,
|
|
47455
47510
|
`Tier that just failed: ${failureStory?.model ?? "(default)"}`,
|
|
47511
|
+
...ranOn ? [
|
|
47512
|
+
`Model that actually ran: ${ranOn} (an override replaced the planner tier above; refer to THIS model in your reason, not the tier)`
|
|
47513
|
+
] : [],
|
|
47456
47514
|
`Attempts: ${failure.attempts}`,
|
|
47457
47515
|
`Error: ${failure.error ?? "(no reason captured)"}`,
|
|
47458
47516
|
"",
|
|
@@ -47503,7 +47561,8 @@ var SurgeonCodex = class extends BaseObserver {
|
|
|
47503
47561
|
maxReplans: opts.maxReplans ?? 10,
|
|
47504
47562
|
codexBin: opts.codexBin ?? "codex",
|
|
47505
47563
|
timeoutMs: opts.timeoutMs ?? 3e5,
|
|
47506
|
-
snapshot: opts.snapshot
|
|
47564
|
+
snapshot: opts.snapshot,
|
|
47565
|
+
resolveRoute: opts.resolveRoute
|
|
47507
47566
|
};
|
|
47508
47567
|
}
|
|
47509
47568
|
async idle() {
|
|
@@ -47527,7 +47586,7 @@ var SurgeonCodex = class extends BaseObserver {
|
|
|
47527
47586
|
}
|
|
47528
47587
|
async evaluateWithLlm(failure) {
|
|
47529
47588
|
const snap = this.opts.snapshot();
|
|
47530
|
-
const userPrompt = buildSurgeonPrompt(snap, failure);
|
|
47589
|
+
const userPrompt = buildSurgeonPrompt(snap, failure, this.opts.resolveRoute);
|
|
47531
47590
|
const prompt = `${SURGEON_SYSTEM_PROMPT}
|
|
47532
47591
|
|
|
47533
47592
|
${userPrompt}`;
|
|
@@ -47599,7 +47658,8 @@ var SurgeonOpenAI = class extends BaseObserver {
|
|
|
47599
47658
|
this.opts = {
|
|
47600
47659
|
maxReplans: opts.maxReplans ?? 10,
|
|
47601
47660
|
model: opts.model ?? "gpt-5.5",
|
|
47602
|
-
snapshot: opts.snapshot
|
|
47661
|
+
snapshot: opts.snapshot,
|
|
47662
|
+
resolveRoute: opts.resolveRoute
|
|
47603
47663
|
};
|
|
47604
47664
|
this.model = pickModel3(this.opts.model);
|
|
47605
47665
|
}
|
|
@@ -47631,7 +47691,7 @@ var SurgeonOpenAI = class extends BaseObserver {
|
|
|
47631
47691
|
*/
|
|
47632
47692
|
async evaluate(failure) {
|
|
47633
47693
|
const snap = this.opts.snapshot();
|
|
47634
|
-
const userPrompt = buildSurgeonPrompt(snap, failure);
|
|
47694
|
+
const userPrompt = buildSurgeonPrompt(snap, failure, this.opts.resolveRoute);
|
|
47635
47695
|
const context = ModelContext.create("surgeon").addContextItem(SystemMessageItem.create(SURGEON_SYSTEM_PROMPT)).addContextItem(UserMessageItem.create(userPrompt));
|
|
47636
47696
|
try {
|
|
47637
47697
|
const round = await runInferenceRound(context, this.model);
|
|
@@ -47688,7 +47748,8 @@ var SurgeonOpenCode = class extends BaseObserver {
|
|
|
47688
47748
|
maxReplans: opts.maxReplans ?? 10,
|
|
47689
47749
|
opencodeBin: opts.opencodeBin ?? "opencode",
|
|
47690
47750
|
timeoutMs: opts.timeoutMs ?? 3e5,
|
|
47691
|
-
snapshot: opts.snapshot
|
|
47751
|
+
snapshot: opts.snapshot,
|
|
47752
|
+
resolveRoute: opts.resolveRoute
|
|
47692
47753
|
};
|
|
47693
47754
|
}
|
|
47694
47755
|
async idle() {
|
|
@@ -47712,7 +47773,7 @@ var SurgeonOpenCode = class extends BaseObserver {
|
|
|
47712
47773
|
}
|
|
47713
47774
|
async evaluateWithLlm(failure) {
|
|
47714
47775
|
const snap = this.opts.snapshot();
|
|
47715
|
-
const userPrompt = buildSurgeonPrompt(snap, failure);
|
|
47776
|
+
const userPrompt = buildSurgeonPrompt(snap, failure, this.opts.resolveRoute);
|
|
47716
47777
|
const prompt = `${SURGEON_SYSTEM_PROMPT}
|
|
47717
47778
|
|
|
47718
47779
|
${userPrompt}`;
|
|
@@ -47767,7 +47828,8 @@ var SurgeonPi = class extends BaseObserver {
|
|
|
47767
47828
|
maxReplans: opts.maxReplans ?? 10,
|
|
47768
47829
|
piBin: opts.piBin ?? "pi",
|
|
47769
47830
|
timeoutMs: opts.timeoutMs ?? 3e5,
|
|
47770
|
-
snapshot: opts.snapshot
|
|
47831
|
+
snapshot: opts.snapshot,
|
|
47832
|
+
resolveRoute: opts.resolveRoute
|
|
47771
47833
|
};
|
|
47772
47834
|
}
|
|
47773
47835
|
async idle() {
|
|
@@ -47791,7 +47853,7 @@ var SurgeonPi = class extends BaseObserver {
|
|
|
47791
47853
|
}
|
|
47792
47854
|
async evaluateWithLlm(failure) {
|
|
47793
47855
|
const snap = this.opts.snapshot();
|
|
47794
|
-
const userPrompt = buildSurgeonPrompt(snap, failure);
|
|
47856
|
+
const userPrompt = buildSurgeonPrompt(snap, failure, this.opts.resolveRoute);
|
|
47795
47857
|
const prompt = `${SURGEON_SYSTEM_PROMPT}
|
|
47796
47858
|
|
|
47797
47859
|
${userPrompt}`;
|
|
@@ -47968,32 +48030,53 @@ async function orchestrate(config) {
|
|
|
47968
48030
|
}))
|
|
47969
48031
|
};
|
|
47970
48032
|
};
|
|
48033
|
+
const storyRouting = {
|
|
48034
|
+
fallbackBackend: storyLlm,
|
|
48035
|
+
openaiDefaultModel: config.storyModel ?? "gpt-5.5",
|
|
48036
|
+
override: config.storyModel,
|
|
48037
|
+
tierMap: config.tierMap,
|
|
48038
|
+
endpoints: config.openaiEndpoints,
|
|
48039
|
+
defaultApiKey: process.env.OPENAI_API_KEY
|
|
48040
|
+
};
|
|
48041
|
+
const routingOverridden = storyLlm !== "claude" || !!config.storyModel || !!config.tierMap;
|
|
48042
|
+
const resolveRoute = routingOverridden ? (model) => {
|
|
48043
|
+
try {
|
|
48044
|
+
return formatRoute(resolveStoryRoute(model, storyRouting));
|
|
48045
|
+
} catch {
|
|
48046
|
+
return null;
|
|
48047
|
+
}
|
|
48048
|
+
} : void 0;
|
|
47971
48049
|
if (surgeonLlm === "openai") {
|
|
47972
48050
|
surgeon = new SurgeonOpenAI({
|
|
47973
48051
|
snapshot,
|
|
48052
|
+
resolveRoute,
|
|
47974
48053
|
model: config.surgeonModel ?? "gpt-5.5"
|
|
47975
48054
|
});
|
|
47976
48055
|
} else if (surgeonLlm === "codex") {
|
|
47977
48056
|
surgeon = new SurgeonCodex({
|
|
47978
48057
|
snapshot,
|
|
48058
|
+
resolveRoute,
|
|
47979
48059
|
useLlm: config.surgeonUseLlm ?? true,
|
|
47980
48060
|
model: config.surgeonModel
|
|
47981
48061
|
});
|
|
47982
48062
|
} else if (surgeonLlm === "opencode") {
|
|
47983
48063
|
surgeon = new SurgeonOpenCode({
|
|
47984
48064
|
snapshot,
|
|
48065
|
+
resolveRoute,
|
|
47985
48066
|
useLlm: config.surgeonUseLlm ?? true,
|
|
47986
48067
|
model: config.surgeonModel
|
|
47987
48068
|
});
|
|
47988
48069
|
} else if (surgeonLlm === "pi") {
|
|
47989
48070
|
surgeon = new SurgeonPi({
|
|
47990
48071
|
snapshot,
|
|
48072
|
+
resolveRoute,
|
|
47991
48073
|
useLlm: config.surgeonUseLlm ?? true,
|
|
47992
48074
|
model: config.surgeonModel
|
|
47993
48075
|
});
|
|
47994
48076
|
} else {
|
|
47995
48077
|
surgeon = new Surgeon({
|
|
47996
48078
|
snapshot,
|
|
48079
|
+
resolveRoute,
|
|
47997
48080
|
useLlm: config.surgeonUseLlm ?? false,
|
|
47998
48081
|
model: config.surgeonModel ?? "opus"
|
|
47999
48082
|
});
|