@galda/cli 0.10.33 → 0.10.34

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.
@@ -11,7 +11,7 @@ import { existsSync } from 'node:fs';
11
11
  import { join, resolve, dirname } from 'node:path';
12
12
  import { fileURLToPath, pathToFileURL } from 'node:url';
13
13
  import { createServer } from 'node:net';
14
- import { isCommandOnPath, resolveConnectedAgents } from '../engine/lib.mjs';
14
+ import { isCommandOnPath, resolveConnectedAgents, resolveOpenBrowserDefault } from '../engine/lib.mjs';
15
15
 
16
16
  const ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..');
17
17
  const say = (m) => console.log(`[galda] ${m}`);
@@ -78,7 +78,11 @@ if (ffmpeg.error || ffmpeg.status !== 0) {
78
78
  }
79
79
 
80
80
  // 4) start the server (state in ~/.manager-for-ai unless MANAGER_HOME is set)
81
- process.env.MANAGER_OPEN_BROWSER = process.env.MANAGER_OPEN_BROWSER ?? '1';
81
+ // Default to opening a browser only for an interactive (human) run. A worker or
82
+ // CI that shells out to this CLI is non-interactive (piped stdout) and must never
83
+ // pop a Google sign-in window on the user's desktop — 2026-07-18 incident. An
84
+ // explicit MANAGER_OPEN_BROWSER (including empty) is always respected.
85
+ process.env.MANAGER_OPEN_BROWSER = resolveOpenBrowserDefault({ existing: process.env.MANAGER_OPEN_BROWSER, isTTY: Boolean(process.stdout.isTTY) });
82
86
  // Public-build defaults (this CLI is the shipped entry point): point at the
83
87
  // deployed billing worker + the fixed-URL relay unless the operator overrides.
84
88
  // Set on env BEFORE importing the server so it reads them like any other config.
package/engine/lib.mjs CHANGED
@@ -3353,6 +3353,20 @@ export function shouldOpenBrowserOnBoot({ openBrowser, platform, managerPort } =
3353
3353
  return true;
3354
3354
  }
3355
3355
 
3356
+ // The launcher (bin/manager-for-ai.mjs) side of the same rule: what to DEFAULT
3357
+ // MANAGER_OPEN_BROWSER to when the operator did not set it. shouldOpenBrowserOnBoot
3358
+ // is the belt on the spawn side (ephemeral port-0 boots never open); this is the
3359
+ // belt on the entry side. A human who ran `npx @galda/cli` in a terminal has an
3360
+ // interactive stdout (isTTY); a worker / CI / automation that shells out to the
3361
+ // CLI to "verify against a real server" is non-interactive (piped) — and must
3362
+ // never pop a Google sign-in window on the user's desktop (that path resolves a
3363
+ // real port, so the port-0 belt alone would not catch it). An explicit value
3364
+ // (including empty, meaning "self-hosted, no hosted flow") is always respected.
3365
+ export function resolveOpenBrowserDefault({ existing, isTTY } = {}) {
3366
+ if (existing !== undefined && existing !== null) return String(existing);
3367
+ return isTTY ? '1' : '0';
3368
+ }
3369
+
3356
3370
  // --- device-flow (PKCE) sign-in helpers --------------------------------------
3357
3371
  // The browser no longer delivers the minted token to a live loopback port —
3358
3372
  // the engine POLLS the Worker to claim it (device-flow). PKCE ties the claim to
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@galda/cli",
3
- "version": "0.10.33",
3
+ "version": "0.10.34",
4
4
  "type": "module",
5
5
  "description": "Galda - hand off work to Claude Code or Codex, get proof back. Runs on your existing subscription, no extra API cost.",
6
6
  "scripts": {