baro-ai 0.72.0 → 0.73.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/runner.mjs +110 -18
- package/dist/runner.mjs.map +1 -1
- package/package.json +1 -1
package/dist/runner.mjs
CHANGED
|
@@ -3717,6 +3717,7 @@ import { execFileSync, spawn } from "child_process";
|
|
|
3717
3717
|
import { appendFileSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "fs";
|
|
3718
3718
|
import { hostname, homedir, tmpdir } from "os";
|
|
3719
3719
|
import { join } from "path";
|
|
3720
|
+
import { createInterface } from "readline/promises";
|
|
3720
3721
|
|
|
3721
3722
|
// ../../node_modules/ws/wrapper.mjs
|
|
3722
3723
|
var import_stream = __toESM(require_stream(), 1);
|
|
@@ -3728,14 +3729,7 @@ var import_subprotocol = __toESM(require_subprotocol(), 1);
|
|
|
3728
3729
|
var import_websocket = __toESM(require_websocket(), 1);
|
|
3729
3730
|
var import_websocket_server = __toESM(require_websocket_server(), 1);
|
|
3730
3731
|
|
|
3731
|
-
// ../baro-orchestrator/scripts/runner.ts
|
|
3732
|
-
var encode = (m) => JSON.stringify(m);
|
|
3733
|
-
var url = process.env.CONTROL_URL ?? "wss://api.baro.jigjoy.ai";
|
|
3734
|
-
var token = process.env.RUNNER_TOKEN;
|
|
3735
|
-
var httpBase = url.replace(/^ws/, "http").replace(/\/+$/, "");
|
|
3736
|
-
var credsPath = join(homedir(), ".baro", "credentials.json");
|
|
3737
|
-
var VERSION = "0.72.0";
|
|
3738
|
-
var updateCachePath = join(homedir(), ".baro", "update-check.json");
|
|
3732
|
+
// ../baro-orchestrator/scripts/runner-helpers.ts
|
|
3739
3733
|
function semverLt(a, b) {
|
|
3740
3734
|
const pa = a.split(".").map(Number);
|
|
3741
3735
|
const pb = b.split(".").map(Number);
|
|
@@ -3746,6 +3740,23 @@ function semverLt(a, b) {
|
|
|
3746
3740
|
}
|
|
3747
3741
|
return false;
|
|
3748
3742
|
}
|
|
3743
|
+
function buildReexec(execPath, argv, env) {
|
|
3744
|
+
return { cmd: execPath, args: argv.slice(1), env: { ...env, BARO_UPDATED: "1" } };
|
|
3745
|
+
}
|
|
3746
|
+
function buildInstallServiceArgs(opts) {
|
|
3747
|
+
const args = ["connect", "--install-service", "--token", opts.token, "--workspace", opts.workspace];
|
|
3748
|
+
if (opts.controlUrl) args.push("--control-url", opts.controlUrl);
|
|
3749
|
+
return args;
|
|
3750
|
+
}
|
|
3751
|
+
|
|
3752
|
+
// ../baro-orchestrator/scripts/runner.ts
|
|
3753
|
+
var encode = (m) => JSON.stringify(m);
|
|
3754
|
+
var url = process.env.CONTROL_URL ?? "wss://api.baro.jigjoy.ai";
|
|
3755
|
+
var token = process.env.RUNNER_TOKEN;
|
|
3756
|
+
var httpBase = url.replace(/^ws/, "http").replace(/\/+$/, "");
|
|
3757
|
+
var credsPath = join(homedir(), ".baro", "credentials.json");
|
|
3758
|
+
var VERSION = "0.73.0";
|
|
3759
|
+
var updateCachePath = join(homedir(), ".baro", "update-check.json");
|
|
3749
3760
|
async function getLatest(force = false) {
|
|
3750
3761
|
if (!force) {
|
|
3751
3762
|
try {
|
|
@@ -3779,6 +3790,15 @@ async function selfUpdate(latest) {
|
|
|
3779
3790
|
child.on("error", () => resolve(false));
|
|
3780
3791
|
});
|
|
3781
3792
|
}
|
|
3793
|
+
function reexecUpdated() {
|
|
3794
|
+
const { cmd, args, env } = buildReexec(process.execPath, process.argv, process.env);
|
|
3795
|
+
const child = spawn(cmd, args, { stdio: "inherit", detached: false, env });
|
|
3796
|
+
child.on("exit", (code, signal) => process.exit(signal ? 0 : code ?? 0));
|
|
3797
|
+
child.on("error", (e) => {
|
|
3798
|
+
console.error(`[baro] could not restart into the updated runner (${e.message}) \u2014 run \`baro connect\` again`);
|
|
3799
|
+
process.exit(1);
|
|
3800
|
+
});
|
|
3801
|
+
}
|
|
3782
3802
|
var readCliToken = () => {
|
|
3783
3803
|
try {
|
|
3784
3804
|
return JSON.parse(readFileSync(credsPath, "utf8")).token;
|
|
@@ -3818,6 +3838,7 @@ var workspaceDir = process.env.WORKSPACE_DIR ?? process.cwd();
|
|
|
3818
3838
|
var baroBin = process.env.BARO_BIN ?? "baro";
|
|
3819
3839
|
var runnerId = process.env.RUNNER_ID ?? hostname();
|
|
3820
3840
|
var runOnce = process.env.BARO_RUN_ONCE === "1";
|
|
3841
|
+
var isService = process.env.BARO_SERVICE === "1";
|
|
3821
3842
|
function cloneRepo(fullName, token2, emit) {
|
|
3822
3843
|
return new Promise((resolve, reject) => {
|
|
3823
3844
|
const dir = mkdtempSync(join(tmpdir(), "baro-clone-"));
|
|
@@ -3915,8 +3936,11 @@ async function runGoal(d, emit, signal) {
|
|
|
3915
3936
|
const child = spawn(
|
|
3916
3937
|
baroBin,
|
|
3917
3938
|
["--headless", d.goal, "--cwd", cwd, "--llm", d.route?.backend ?? "claude", "--parallel", String(d.parallel), "--timeout", String(d.timeoutSecs), ...d.quick ? ["--quick"] : [], ...d.followUp ? ["--continue"] : []],
|
|
3918
|
-
|
|
3939
|
+
// stdin is piped: baro --headless forwards JSON command lines
|
|
3940
|
+
// (agent_message) into the orchestrator's stdin lane.
|
|
3941
|
+
{ cwd, env, stdio: ["pipe", "pipe", "pipe"] }
|
|
3919
3942
|
);
|
|
3943
|
+
activeChild = child;
|
|
3920
3944
|
const started = Date.now();
|
|
3921
3945
|
const secs = () => Math.max(1, Math.round((Date.now() - started) / 1e3));
|
|
3922
3946
|
const stories = /* @__PURE__ */ new Set();
|
|
@@ -3958,6 +3982,7 @@ async function runGoal(d, emit, signal) {
|
|
|
3958
3982
|
});
|
|
3959
3983
|
signal.addEventListener("abort", () => child.kill("SIGTERM"));
|
|
3960
3984
|
child.on("close", (code) => {
|
|
3985
|
+
if (activeChild === child) activeChild = null;
|
|
3961
3986
|
const ok = doneSuccess ?? (code === 0 && failed === 0 && passed > 0);
|
|
3962
3987
|
const goalLines = new Set(d.goal.split("\n").map((s) => s.trim()).filter(Boolean));
|
|
3963
3988
|
const isNoise = (l) => /no stdin data received|redirect stdin explicitly|proceeding without it/i.test(l);
|
|
@@ -4028,6 +4053,7 @@ ${fails || r.out.slice(-500)}`);
|
|
|
4028
4053
|
var rejected;
|
|
4029
4054
|
var currentWs = null;
|
|
4030
4055
|
var inflight = /* @__PURE__ */ new Map();
|
|
4056
|
+
var activeChild = null;
|
|
4031
4057
|
var send = (m) => {
|
|
4032
4058
|
if (currentWs?.readyState === import_websocket.default.OPEN) currentWs.send(encode(m));
|
|
4033
4059
|
};
|
|
@@ -4040,6 +4066,13 @@ function handleMessage(m) {
|
|
|
4040
4066
|
send({ t: "pong", ts: m.ts });
|
|
4041
4067
|
} else if (m.t === "cancel") {
|
|
4042
4068
|
inflight.get(m.storyId)?.abort();
|
|
4069
|
+
} else if (m.t === "agent_message") {
|
|
4070
|
+
const { storyId, text } = m;
|
|
4071
|
+
const stdin = activeChild?.stdin;
|
|
4072
|
+
if (stdin && stdin.writable && !stdin.destroyed) {
|
|
4073
|
+
stdin.write(`${JSON.stringify({ type: "agent_message", id: storyId, text })}
|
|
4074
|
+
`);
|
|
4075
|
+
}
|
|
4043
4076
|
} else if (m.t === "dispatch_run") {
|
|
4044
4077
|
const d = m;
|
|
4045
4078
|
if (inflight.has(d.runId)) return;
|
|
@@ -4060,6 +4093,43 @@ function handleMessage(m) {
|
|
|
4060
4093
|
});
|
|
4061
4094
|
}
|
|
4062
4095
|
}
|
|
4096
|
+
function goodbyeAndExit() {
|
|
4097
|
+
console.log("\n[baro] runner going offline \u2014 runs will fall back to cloud. Keep it always-on: baro connect --install-service");
|
|
4098
|
+
process.exit(0);
|
|
4099
|
+
}
|
|
4100
|
+
var serviceOffered = false;
|
|
4101
|
+
async function maybeOfferServiceInstall() {
|
|
4102
|
+
if (serviceOffered || isService || runOnce || process.env.BARO_NO_SERVICE_PROMPT === "1") return;
|
|
4103
|
+
serviceOffered = true;
|
|
4104
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) return;
|
|
4105
|
+
await new Promise((r) => setTimeout(r, 1500));
|
|
4106
|
+
if (rejected || !token || currentWs?.readyState !== import_websocket.default.OPEN) return;
|
|
4107
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
4108
|
+
rl.on("SIGINT", () => {
|
|
4109
|
+
rl.close();
|
|
4110
|
+
goodbyeAndExit();
|
|
4111
|
+
});
|
|
4112
|
+
const answer = (await rl.question("\nKeep this runner online in the background (installs a login service)? [Y/n] ")).trim().toLowerCase();
|
|
4113
|
+
rl.close();
|
|
4114
|
+
if (answer === "n" || answer === "no") {
|
|
4115
|
+
console.log("[baro] staying in the foreground \u2014 this runner goes offline when the terminal closes.\n[baro] install the service any time: baro connect --install-service --token <rt_\u2026>");
|
|
4116
|
+
return;
|
|
4117
|
+
}
|
|
4118
|
+
console.log("[baro] installing the background service\u2026");
|
|
4119
|
+
const args = buildInstallServiceArgs({ token, workspace: workspaceDir, controlUrl: process.env.CONTROL_URL });
|
|
4120
|
+
const ok = await new Promise((resolve) => {
|
|
4121
|
+
const ch = spawn(baroBin, args, { stdio: "inherit", shell: process.platform === "win32" });
|
|
4122
|
+
ch.on("exit", (code) => resolve(code === 0));
|
|
4123
|
+
ch.on("error", () => resolve(false));
|
|
4124
|
+
});
|
|
4125
|
+
if (ok) {
|
|
4126
|
+
console.log("[baro] \u2713 service installed \u2014 the runner now stays online across terminal close, logout, and reboot.");
|
|
4127
|
+
console.log("[baro] handing off to the service; this foreground runner is exiting.");
|
|
4128
|
+
currentWs?.close();
|
|
4129
|
+
process.exit(0);
|
|
4130
|
+
}
|
|
4131
|
+
console.warn("[baro] service install failed \u2014 staying in the foreground. Try manually: baro connect --install-service --token <rt_\u2026>");
|
|
4132
|
+
}
|
|
4063
4133
|
function connectOnce() {
|
|
4064
4134
|
return new Promise((resolve) => {
|
|
4065
4135
|
const ws = new import_websocket.default(url);
|
|
@@ -4067,6 +4137,7 @@ function connectOnce() {
|
|
|
4067
4137
|
ws.on("open", () => {
|
|
4068
4138
|
ws.send(encode({ t: "register", runnerId, hostname: hostname(), token, backends: ["claude"], workspaceIds: ["default"], version: VERSION }));
|
|
4069
4139
|
console.log(inflight.size ? `[baro] reconnected to ${url} \u2014 resuming ${inflight.size} in-flight run(s)` : `[baro] connected to ${url} \u2014 workspace ${workspaceDir}`);
|
|
4140
|
+
void maybeOfferServiceInstall();
|
|
4070
4141
|
});
|
|
4071
4142
|
ws.on("message", (data) => {
|
|
4072
4143
|
let m;
|
|
@@ -4093,20 +4164,37 @@ async function main() {
|
|
|
4093
4164
|
await getLatest(true);
|
|
4094
4165
|
return;
|
|
4095
4166
|
}
|
|
4096
|
-
|
|
4097
|
-
|
|
4098
|
-
|
|
4099
|
-
if (
|
|
4167
|
+
if (process.env.BARO_UPDATED !== "1") {
|
|
4168
|
+
try {
|
|
4169
|
+
const latest = await getLatest(true);
|
|
4170
|
+
if (latest && semverLt(VERSION, latest)) {
|
|
4100
4171
|
if (await selfUpdate(latest)) {
|
|
4101
|
-
|
|
4102
|
-
|
|
4172
|
+
if (isService) {
|
|
4173
|
+
console.log(`[baro] updated to ${latest} \u2014 restarting service\u2026`);
|
|
4174
|
+
process.exit(0);
|
|
4175
|
+
}
|
|
4176
|
+
console.log(`[baro] updated to ${latest} \u2014 restarting the runner\u2026`);
|
|
4177
|
+
reexecUpdated();
|
|
4178
|
+
return;
|
|
4103
4179
|
}
|
|
4104
4180
|
console.warn(`[baro] could not self-update (likely a root-owned global install). Update manually: npm i -g baro-ai@latest`);
|
|
4105
|
-
} else {
|
|
4106
|
-
console.warn(`[baro] a newer baro is available (${VERSION} \u2192 ${latest}). Update: npm i -g baro-ai`);
|
|
4107
4181
|
}
|
|
4182
|
+
} catch {
|
|
4108
4183
|
}
|
|
4109
|
-
}
|
|
4184
|
+
}
|
|
4185
|
+
if (isService) {
|
|
4186
|
+
setInterval(() => {
|
|
4187
|
+
void (async () => {
|
|
4188
|
+
try {
|
|
4189
|
+
const latest = await getLatest(true);
|
|
4190
|
+
if (latest && semverLt(VERSION, latest) && inflight.size === 0 && await selfUpdate(latest)) {
|
|
4191
|
+
console.log(`[baro] updated to ${latest} \u2014 restarting service\u2026`);
|
|
4192
|
+
process.exit(0);
|
|
4193
|
+
}
|
|
4194
|
+
} catch {
|
|
4195
|
+
}
|
|
4196
|
+
})();
|
|
4197
|
+
}, 6 * 36e5).unref();
|
|
4110
4198
|
}
|
|
4111
4199
|
if (!token) {
|
|
4112
4200
|
const cli = readCliToken();
|
|
@@ -4122,6 +4210,10 @@ async function main() {
|
|
|
4122
4210
|
console.error("[baro] not signed in. Run `baro login` first, or pass --token <rt_\u2026> (get one from the dashboard).");
|
|
4123
4211
|
process.exit(1);
|
|
4124
4212
|
}
|
|
4213
|
+
if (!isService && !runOnce) {
|
|
4214
|
+
process.on("SIGINT", goodbyeAndExit);
|
|
4215
|
+
process.on("SIGTERM", goodbyeAndExit);
|
|
4216
|
+
}
|
|
4125
4217
|
if (runOnce) {
|
|
4126
4218
|
setTimeout(() => {
|
|
4127
4219
|
if (inflight.size === 0) {
|