agy-mcp-bridge 0.1.7 → 0.1.8

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/src/cli.js CHANGED
@@ -12,7 +12,7 @@ import { renderSetup } from './setup.js';
12
12
  import { configuredPort } from './http.js';
13
13
  import { offerSkillInstall, offerSkillUpdate } from './onboarding.js';
14
14
  import { addWorkspace, listWorkspaces, removeWorkspace, resolveWorkspaceDirectory } from './workspace-config.js';
15
- import { checkForUpdate, compareVersions, fetchLatest, isGlobalInstall, isSnoozed, readPackageInfo, runGlobalInstall, snooze, updateCheckEnabled } from './update.js';
15
+ import { checkForUpdate, compareVersions, fetchLatest, installFailureHint, isGlobalInstall, isSnoozed, readPackageInfo, runGlobalInstall, snooze, updateCheckEnabled } from './update.js';
16
16
  const BIN = 'agy-mcp-bridge';
17
17
  const pkg = readPackageInfo();
18
18
  const configFile = process.env.ANTIGRAVITY_BRIDGE_CONFIG ?? paths.configFile;
@@ -88,6 +88,9 @@ async function offerUpdate(info) {
88
88
  process.exit(0);
89
89
  }
90
90
  console.error(`[update] Installation failed (see npm output above). Starting the current version ${info.current}.`);
91
+ const hint = installFailureHint(pkg.name);
92
+ if (hint)
93
+ console.error(`[update] ${hint}`);
91
94
  }
92
95
  async function start(args) {
93
96
  const directories = [];
@@ -156,6 +159,11 @@ async function updateCommand(args) {
156
159
  const status = runGlobalInstall(pkg.name, latest);
157
160
  if (status === 0)
158
161
  console.log(`Updated to ${latest}. Restart a running server (Ctrl+C, then ${BIN}) to use it.`);
162
+ else {
163
+ const hint = installFailureHint(pkg.name);
164
+ if (hint)
165
+ console.error(hint);
166
+ }
159
167
  process.exitCode = status;
160
168
  }
161
169
  function setup(args) {
package/dist/src/paths.js CHANGED
@@ -1,8 +1,13 @@
1
- import { homedir } from 'node:os';
1
+ import { homedir, tmpdir } from 'node:os';
2
2
  import path from 'node:path';
3
3
  import { fileURLToPath } from 'node:url';
4
4
  /** Read-only assets shipped with the code (ui/, skills/, package.json). Two levels above dist/src. */
5
5
  export const packageRoot = fileURLToPath(new URL('../../', import.meta.url));
6
+ /**
7
+ * Working directory for helper processes (`agy --version`, `--help`, `models`). Never the package directory: on Windows a process keeps its
8
+ * working directory open, so a helper (or anything it leaves running) there would make `npm install -g` fail with EBUSY.
9
+ */
10
+ export const helperDirectory = () => tmpdir();
6
11
  /** Per-user, writable, survives package updates (an update replaces the whole install directory). */
7
12
  export function userDataDirectory(env = process.env, platform = process.platform, home = homedir()) {
8
13
  if (platform === 'win32')
@@ -1,5 +1,5 @@
1
1
  import { loadConfig, sessionOnlyWorkspaces } from './config.js';
2
- import { paths } from './paths.js';
2
+ import { helperDirectory, paths } from './paths.js';
3
3
  import { findExecutable, inspectCli, startProcess } from './antigravity/process.js';
4
4
  import { TaskManager } from './tasks/manager.js';
5
5
  import { recoverExecutionLock } from './tasks/execution-lock.js';
@@ -7,7 +7,7 @@ export async function createRuntime() {
7
7
  const config = await loadConfig();
8
8
  let cli = { version: 'unavailable', executable: '', supported: false, warnings: [] };
9
9
  try {
10
- cli = await inspectCli(await findExecutable(config.executable), paths.packageRoot, (executable, args, cwd) => startProcess(executable, args, cwd, { extraEnvPassthrough: config.extra_env_passthrough }), config.prompt_transport === 'stdin');
10
+ cli = await inspectCli(await findExecutable(config.executable), helperDirectory(), (executable, args, cwd) => startProcess(executable, args, cwd, { extraEnvPassthrough: config.extra_env_passthrough }), config.prompt_transport === 'stdin');
11
11
  }
12
12
  catch {
13
13
  console.error('[bridge] CLI unavailable or inspection failed');
@@ -8,7 +8,7 @@ import { redact } from '../security/redact.js';
8
8
  import { delegationState } from '../delegation.js';
9
9
  import { startProcess, terminateOwned } from '../antigravity/process.js';
10
10
  import { invocationFor, finalEnvelope } from '../antigravity/invocation.js';
11
- import { packageRoot } from '../paths.js';
11
+ import { helperDirectory } from '../paths.js';
12
12
  import { lowerLevel, permissionFlags, permissionState } from '../permissions.js';
13
13
  import { listModels, readModel } from '../models.js';
14
14
  import { pidAlive, recoverExecutionLock } from './execution-lock.js';
@@ -326,7 +326,7 @@ export class TaskManager {
326
326
  }
327
327
  /** Models offered by the installed Antigravity CLI (read on demand, never at startup). */
328
328
  availableModels() {
329
- return this.runtime.models ? this.runtime.models() : listModels(this.runtime.executable, packageRoot, this.config.extra_env_passthrough);
329
+ return this.runtime.models ? this.runtime.models() : listModels(this.runtime.executable, helperDirectory(), this.config.extra_env_passthrough);
330
330
  }
331
331
  currentModel() { return readModel(this.runtime.stateDirectory); }
332
332
  /** Full record for the web UI: the request, the exact prompt shape sent to the CLI (redacted), and the task with logs. */
@@ -139,6 +139,12 @@ export async function isGlobalInstall(root = paths.packageRoot) {
139
139
  }
140
140
  }
141
141
  export const installArgs = (name, version) => ['install', '-g', `${name}@${version}`];
142
+ /** Shown after a failed global install. On Windows the usual cause is something still holding the install folder (EBUSY). */
143
+ export function installFailureHint(name, platform = process.platform) {
144
+ return platform === 'win32'
145
+ ? `If npm reported EBUSY, something still uses the install folder: stop every running ${name} (Ctrl+C) and close Codex / Claude Code sessions connected to it, then run "npm install -g ${name}@latest" in a new terminal. Restarting the computer also releases the folder.`
146
+ : null;
147
+ }
142
148
  /** Runs `npm install -g <name>@<version>` in the foreground. Only called after the owner agreed or typed the update command. */
143
149
  export function runGlobalInstall(name, version) {
144
150
  if (!VERSION.test(version))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agy-mcp-bridge",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "description": "Local authenticated HTTP MCP bridge that lets Codex and Claude Code delegate bounded coding tasks to the Antigravity CLI (agy)",
5
5
  "license": "MIT",
6
6
  "keywords": [