baro-ai 0.72.1 → 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 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.1";
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-"));
@@ -4072,6 +4093,43 @@ function handleMessage(m) {
4072
4093
  });
4073
4094
  }
4074
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
+ }
4075
4133
  function connectOnce() {
4076
4134
  return new Promise((resolve) => {
4077
4135
  const ws = new import_websocket.default(url);
@@ -4079,6 +4137,7 @@ function connectOnce() {
4079
4137
  ws.on("open", () => {
4080
4138
  ws.send(encode({ t: "register", runnerId, hostname: hostname(), token, backends: ["claude"], workspaceIds: ["default"], version: VERSION }));
4081
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();
4082
4141
  });
4083
4142
  ws.on("message", (data) => {
4084
4143
  let m;
@@ -4105,20 +4164,37 @@ async function main() {
4105
4164
  await getLatest(true);
4106
4165
  return;
4107
4166
  }
4108
- try {
4109
- const latest = await getLatest();
4110
- if (latest && semverLt(VERSION, latest)) {
4111
- if (process.env.BARO_SERVICE === "1") {
4167
+ if (process.env.BARO_UPDATED !== "1") {
4168
+ try {
4169
+ const latest = await getLatest(true);
4170
+ if (latest && semverLt(VERSION, latest)) {
4112
4171
  if (await selfUpdate(latest)) {
4113
- console.log(`[baro] updated to ${latest} \u2014 restarting service\u2026`);
4114
- process.exit(0);
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;
4115
4179
  }
4116
4180
  console.warn(`[baro] could not self-update (likely a root-owned global install). Update manually: npm i -g baro-ai@latest`);
4117
- } else {
4118
- console.warn(`[baro] a newer baro is available (${VERSION} \u2192 ${latest}). Update: npm i -g baro-ai`);
4119
4181
  }
4182
+ } catch {
4120
4183
  }
4121
- } catch {
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();
4122
4198
  }
4123
4199
  if (!token) {
4124
4200
  const cli = readCliToken();
@@ -4134,6 +4210,10 @@ async function main() {
4134
4210
  console.error("[baro] not signed in. Run `baro login` first, or pass --token <rt_\u2026> (get one from the dashboard).");
4135
4211
  process.exit(1);
4136
4212
  }
4213
+ if (!isService && !runOnce) {
4214
+ process.on("SIGINT", goodbyeAndExit);
4215
+ process.on("SIGTERM", goodbyeAndExit);
4216
+ }
4137
4217
  if (runOnce) {
4138
4218
  setTimeout(() => {
4139
4219
  if (inflight.size === 0) {