@raysonmeng/agentbridge 0.1.14 → 0.1.16

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.
@@ -12,7 +12,7 @@
12
12
  {
13
13
  "name": "agentbridge",
14
14
  "description": "Bridge Claude Code and Codex through a shared daemon, push channel delivery, and reply/get_messages tools.",
15
- "version": "0.1.14",
15
+ "version": "0.1.16",
16
16
  "author": {
17
17
  "name": "AgentBridge Contributors",
18
18
  "email": "raysonmeng@qq.com"
package/README.md CHANGED
@@ -266,6 +266,7 @@ agent_bridge/
266
266
  | `AGENTBRIDGE_DAEMON_ENTRY` | `./daemon.ts` | Override daemon entry point (used by plugin bundles) |
267
267
  | `NO_UPDATE_NOTIFIER` | unset | Set to any value to disable the "update available" notice (ecosystem-standard opt-out) |
268
268
  | `AGENTBRIDGE_NO_UPDATE_NOTIFIER` | unset | Namespaced opt-out for the update notice (same effect as `NO_UPDATE_NOTIFIER`) |
269
+ | `AGENTBRIDGE_UPDATE_PROMPT` | unset | Set to `0` to disable the interactive update prompt and keep pure notice-only behavior |
269
270
  | `AGENTBRIDGE_UPDATE_CHECK_INTERVAL_MS` | `86400000` | How often `abg claude`/`abg codex` may check npm for a newer version (default once/day). The notice is otherwise printed from cache — zero network on most runs |
270
271
 
271
272
  ### Update notifications
@@ -278,7 +279,7 @@ agent_bridge/
278
279
  Plugin: /plugin marketplace update agentbridge (then /reload-plugins)
279
280
  ```
280
281
 
281
- The check is best-effort and never blocks, delays, or fails your command: the notice is printed from a cached result, the npm check runs at most once per day in the background, and any network/registry failure is silently ignored. It is suppressed automatically for non-interactive (piped) output and in CI, and can be disabled with `NO_UPDATE_NOTIFIER=1`. The notifier never installs anything — it only shows you the command.
282
+ The check is best-effort: the notice is printed from a cached result, the npm check runs at most once per day in the background, and any network/registry failure is silently ignored. On an interactive TTY, a cached update prompts before launch; answering `y` runs `npm install -g @raysonmeng/agentbridge@latest`, while `N` (or no answer within 15 seconds) records that version as dismissed and continues launching. Non-interactive output and CI never prompt, and the notice can be disabled with `NO_UPDATE_NOTIFIER=1` or kept notice-only with `AGENTBRIDGE_UPDATE_PROMPT=0`.
282
283
 
283
284
  ### State Directory
284
285
 
package/README.zh-CN.md CHANGED
@@ -253,6 +253,7 @@ agent_bridge/
253
253
  | `AGENTBRIDGE_DAEMON_ENTRY` | `./daemon.ts` | 覆盖 daemon 入口(插件包使用) |
254
254
  | `NO_UPDATE_NOTIFIER` | 未设置 | 设为任意值即关闭「有新版本」提示(生态通用 opt-out) |
255
255
  | `AGENTBRIDGE_NO_UPDATE_NOTIFIER` | 未设置 | 命名空间化的关闭开关(效果同 `NO_UPDATE_NOTIFIER`) |
256
+ | `AGENTBRIDGE_UPDATE_PROMPT` | 未设置 | 设为 `0` 可关闭交互询问,恢复纯打印提示 |
256
257
  | `AGENTBRIDGE_UPDATE_CHECK_INTERVAL_MS` | `86400000` | `abg claude`/`abg codex` 多久查一次 npm 新版本(默认每天一次)。其余时候只读缓存打印,大多数调用零网络 |
257
258
 
258
259
  ### 更新提示
@@ -265,7 +266,7 @@ agent_bridge/
265
266
  Plugin: /plugin marketplace update agentbridge (then /reload-plugins)
266
267
  ```
267
268
 
268
- 该检查是 best-effort,绝不阻塞/拖慢/弄坏你的命令:提示从缓存打印,npm 检查每天最多在后台跑一次,任何网络/registry 失败都静默忽略。非交互(管道)输出和 CI 下自动抑制,可用 `NO_UPDATE_NOTIFIER=1` 关闭。notifier 永远不会自动安装任何东西——只告诉你升级命令。
269
+ 该检查是 best-effort:提示从缓存打印,npm 检查每天最多在后台跑一次,任何网络/registry 失败都静默忽略。交互式 TTY 下,命中缓存更新会在启动前询问;输入 `y` 会运行 `npm install -g @raysonmeng/agentbridge@latest`,输入 `N`(或 15 秒内无应答)会记住本版本已拒绝并继续启动。非交互(管道)输出和 CI 下绝不询问,可用 `NO_UPDATE_NOTIFIER=1` 关闭提示,或用 `AGENTBRIDGE_UPDATE_PROMPT=0` 保持纯打印。
269
270
 
270
271
  ### 状态目录
271
272
 
package/dist/cli.js CHANGED
@@ -176,7 +176,7 @@ function parsePositiveIntEnv(name, fallback, log = () => {}, env = process.env)
176
176
  var require_package = __commonJS((exports, module) => {
177
177
  module.exports = {
178
178
  name: "@raysonmeng/agentbridge",
179
- version: "0.1.14",
179
+ version: "0.1.16",
180
180
  description: "Bridge between Claude Code and Codex \u2014 bidirectional agent communication via MCP Channel + JSON-RPC",
181
181
  type: "module",
182
182
  packageManager: "bun@1.3.11",
@@ -255,9 +255,13 @@ __export(exports_update_notifier, {
255
255
  isUpdateCheckSuppressed: () => isUpdateCheckSuppressed,
256
256
  getCurrentVersion: () => getCurrentVersion,
257
257
  buildUpdateNotice: () => buildUpdateNotice,
258
- PACKAGE_NAME: () => PACKAGE_NAME
258
+ buildDismissedUpdateNotice: () => buildDismissedUpdateNotice,
259
+ PACKAGE_NAME: () => PACKAGE_NAME,
260
+ DEFAULT_UPDATE_PROMPT_TIMEOUT_MS: () => DEFAULT_UPDATE_PROMPT_TIMEOUT_MS
259
261
  });
260
262
  import { readFileSync } from "fs";
263
+ import { spawnSync } from "child_process";
264
+ import { createInterface } from "readline";
261
265
  function getCurrentVersion() {
262
266
  try {
263
267
  return require_package().version;
@@ -285,7 +289,8 @@ function readCache(stateDir) {
285
289
  return null;
286
290
  return {
287
291
  lastCheckMs: parsed.lastCheckMs,
288
- latest: typeof parsed.latest === "string" ? parsed.latest : null
292
+ latest: typeof parsed.latest === "string" ? parsed.latest : null,
293
+ dismissedVersion: typeof parsed.dismissedVersion === "string" ? parsed.dismissedVersion : undefined
289
294
  };
290
295
  } catch {
291
296
  return null;
@@ -327,7 +332,11 @@ async function refreshUpdateCache(deps = {}) {
327
332
  try {
328
333
  const latest = await fetchLatest(fetchImpl);
329
334
  const prev = readCache(stateDir);
330
- writeCache(stateDir, { lastCheckMs: now(), latest: latest ?? prev?.latest ?? null });
335
+ writeCache(stateDir, {
336
+ lastCheckMs: now(),
337
+ latest: latest ?? prev?.latest ?? null,
338
+ dismissedVersion: prev?.dismissedVersion
339
+ });
331
340
  } catch {}
332
341
  }
333
342
  function buildUpdateNotice(current, latest, isTTY) {
@@ -342,30 +351,109 @@ function buildUpdateNotice(current, latest, isTTY) {
342
351
  ].join(`
343
352
  `);
344
353
  }
354
+ function buildDismissedUpdateNotice(current, latest, isTTY) {
355
+ const yellow = isTTY ? "\x1B[33m" : "";
356
+ const bold = isTTY ? "\x1B[1m" : "";
357
+ const reset = isTTY ? "\x1B[0m" : "";
358
+ return `${yellow}\u26A0 AgentBridge update available: ${bold}${current}${reset}${yellow} \u2192 ${bold}${latest}${reset} (previously dismissed)`;
359
+ }
345
360
  function checkIntervalMs(env) {
346
361
  return parsePositiveIntEnv(CHECK_INTERVAL_ENV, DEFAULT_CHECK_INTERVAL_MS, undefined, env);
347
362
  }
348
- function maybeNotifyUpdate(deps = {}) {
363
+ function updatePromptDisabled(env) {
364
+ return env.AGENTBRIDGE_UPDATE_PROMPT === "0";
365
+ }
366
+ function defaultInstallUpdate(cmd, args) {
367
+ const res = spawnSync(cmd, args, { stdio: "inherit" });
368
+ if (res.error)
369
+ return { ok: false, status: res.status, error: res.error };
370
+ return { ok: res.status === 0, status: res.status };
371
+ }
372
+ function defaultPromptUpdate(opts) {
373
+ return new Promise((resolve) => {
374
+ const rl = createInterface({ input: process.stdin, output: process.stderr });
375
+ let settled = false;
376
+ let timer;
377
+ const finish = (answer) => {
378
+ if (settled)
379
+ return;
380
+ settled = true;
381
+ clearTimeout(timer);
382
+ rl.close();
383
+ resolve(answer);
384
+ };
385
+ timer = setTimeout(() => {
386
+ process.stderr.write(`
387
+ `);
388
+ finish(false);
389
+ }, opts.timeoutMs);
390
+ timer.unref?.();
391
+ rl.question(`Update AgentBridge now? [y/N] `, (answer) => {
392
+ finish(/^y(?:es)?$/i.test(answer.trim()));
393
+ });
394
+ });
395
+ }
396
+ function recordDismissal(stateDir, cache, latest) {
397
+ writeCache(stateDir, {
398
+ ...cache,
399
+ latest,
400
+ dismissedVersion: latest
401
+ });
402
+ }
403
+ async function maybeNotifyUpdate(deps = {}) {
349
404
  try {
350
405
  const env = deps.env ?? process.env;
351
406
  const isTTY = deps.isTTY ?? Boolean(process.stderr.isTTY);
352
407
  if (isUpdateCheckSuppressed(env, isTTY))
353
- return;
408
+ return "continue";
354
409
  const current = deps.current ?? getCurrentVersion();
355
410
  const stateDir = deps.stateDir ?? new StateDirResolver;
356
411
  const now = deps.now ?? Date.now;
357
412
  const print = deps.print ?? ((m) => process.stderr.write(m + `
358
413
  `));
414
+ const inputIsTTY = deps.inputIsTTY ?? Boolean(process.stdin.isTTY);
415
+ const promptTimeoutMs = deps.promptTimeoutMs ?? DEFAULT_UPDATE_PROMPT_TIMEOUT_MS;
359
416
  const cache = readCache(stateDir);
360
417
  if (cache?.latest && isStableUpgrade(current, cache.latest)) {
361
- print(buildUpdateNotice(current, cache.latest, isTTY));
418
+ if (cache.dismissedVersion === cache.latest) {
419
+ print(buildDismissedUpdateNotice(current, cache.latest, isTTY));
420
+ } else {
421
+ print(buildUpdateNotice(current, cache.latest, isTTY));
422
+ if (!updatePromptDisabled(env) && inputIsTTY) {
423
+ const promptUpdate = deps.promptUpdate ?? defaultPromptUpdate;
424
+ let accepted = false;
425
+ try {
426
+ accepted = await promptUpdate({ current, latest: cache.latest, timeoutMs: promptTimeoutMs });
427
+ } catch {
428
+ accepted = false;
429
+ }
430
+ if (accepted) {
431
+ const installUpdate = deps.installUpdate ?? defaultInstallUpdate;
432
+ const cmd = "npm";
433
+ const args = ["install", "-g", `${PACKAGE_NAME}@latest`];
434
+ const result = installUpdate(cmd, args);
435
+ if (result.ok) {
436
+ print("AgentBridge CLI updated. \u8BF7\u91CD\u65B0\u8FD0\u884C\u547D\u4EE4\u3002");
437
+ print("Plugin: in Claude, run `/plugin marketplace update agentbridge` and then `/reload-plugins`.");
438
+ return "updated";
439
+ }
440
+ const detail = result.error?.message ? ` (${result.error.message})` : typeof result.status === "number" ? ` (exit ${result.status})` : "";
441
+ print(`\u26A0 AgentBridge update failed${detail}; continuing with the current command.`);
442
+ } else {
443
+ recordDismissal(stateDir, cache, cache.latest);
444
+ }
445
+ }
446
+ }
362
447
  }
363
448
  if (deps.refresh && (!cache || now() - cache.lastCheckMs >= checkIntervalMs(env))) {
364
449
  refreshUpdateCache({ stateDir, now, fetchImpl: deps.fetchImpl }).catch(() => {});
365
450
  }
366
- } catch {}
451
+ return "continue";
452
+ } catch {
453
+ return "continue";
454
+ }
367
455
  }
368
- var PACKAGE_NAME = "@raysonmeng/agentbridge", REGISTRY_URL, ABBREVIATED_ACCEPT = "application/vnd.npm.install-v1+json", DEFAULT_CHECK_INTERVAL_MS, FETCH_TIMEOUT_MS = 2500, CHECK_INTERVAL_ENV = "AGENTBRIDGE_UPDATE_CHECK_INTERVAL_MS";
456
+ var PACKAGE_NAME = "@raysonmeng/agentbridge", REGISTRY_URL, ABBREVIATED_ACCEPT = "application/vnd.npm.install-v1+json", DEFAULT_CHECK_INTERVAL_MS, FETCH_TIMEOUT_MS = 2500, DEFAULT_UPDATE_PROMPT_TIMEOUT_MS = 15000, CHECK_INTERVAL_ENV = "AGENTBRIDGE_UPDATE_CHECK_INTERVAL_MS";
369
457
  var init_update_notifier = __esm(() => {
370
458
  init_atomic_json();
371
459
  init_state_dir();
@@ -1037,7 +1125,7 @@ var exports_dev = {};
1037
1125
  __export(exports_dev, {
1038
1126
  runDev: () => runDev
1039
1127
  });
1040
- import { execFileSync as execFileSync3, spawnSync } from "child_process";
1128
+ import { execFileSync as execFileSync3, spawnSync as spawnSync2 } from "child_process";
1041
1129
  import { resolve as resolve2 } from "path";
1042
1130
  import { existsSync as existsSync5, cpSync, rmSync } from "fs";
1043
1131
  async function runDev(args = []) {
@@ -1063,7 +1151,7 @@ async function runDev(args = []) {
1063
1151
  `);
1064
1152
  } else {
1065
1153
  console.log("Building CLI from source...");
1066
- const cliBuild = spawnSync("bun", ["run", "build:cli"], {
1154
+ const cliBuild = spawnSync2("bun", ["run", "build:cli"], {
1067
1155
  cwd: projectRoot,
1068
1156
  stdio: "inherit"
1069
1157
  });
@@ -1074,7 +1162,7 @@ async function runDev(args = []) {
1074
1162
  console.log(` \u2713 CLI built successfully
1075
1163
  `);
1076
1164
  console.log("Building plugin from source...");
1077
- const buildResult = spawnSync("bun", ["run", "build:plugin"], {
1165
+ const buildResult = spawnSync2("bun", ["run", "build:plugin"], {
1078
1166
  cwd: projectRoot,
1079
1167
  stdio: "inherit"
1080
1168
  });
@@ -1497,11 +1585,11 @@ function formatBuildInfo(build) {
1497
1585
  var CODE_HASH_SENTINEL = "source", BUILD_INFO;
1498
1586
  var init_build_info = __esm(() => {
1499
1587
  BUILD_INFO = Object.freeze({
1500
- version: defineString("0.1.14", "0.0.0-source"),
1501
- commit: defineString("f5a9562", "source"),
1588
+ version: defineString("0.1.16", "0.0.0-source"),
1589
+ commit: defineString("1dc5e4f", "source"),
1502
1590
  bundle: defineBundle("dist"),
1503
1591
  contractVersion: defineNumber(1, CONTRACT_VERSION),
1504
- codeHash: defineString("e05d18c3cc72", "source")
1592
+ codeHash: defineString("1fc975838e46", "source")
1505
1593
  });
1506
1594
  });
1507
1595
 
@@ -6161,7 +6249,9 @@ async function main(command, restArgs) {
6161
6249
  if (command && NOTIFY_COMMANDS.has(command)) {
6162
6250
  try {
6163
6251
  const { maybeNotifyUpdate: maybeNotifyUpdate2 } = await Promise.resolve().then(() => (init_update_notifier(), exports_update_notifier));
6164
- maybeNotifyUpdate2({ refresh: REFRESH_COMMANDS.has(command) });
6252
+ const decision = await maybeNotifyUpdate2({ refresh: REFRESH_COMMANDS.has(command) });
6253
+ if (decision === "updated")
6254
+ process.exit(0);
6165
6255
  } catch {}
6166
6256
  }
6167
6257
  switch (command) {
package/dist/daemon.js CHANGED
@@ -26,11 +26,11 @@ function defineNumber(value, fallback) {
26
26
  return typeof value === "number" && Number.isFinite(value) ? value : fallback;
27
27
  }
28
28
  var BUILD_INFO = Object.freeze({
29
- version: defineString("0.1.14", "0.0.0-source"),
30
- commit: defineString("f5a9562", "source"),
29
+ version: defineString("0.1.16", "0.0.0-source"),
30
+ commit: defineString("1dc5e4f", "source"),
31
31
  bundle: defineBundle("dist"),
32
32
  contractVersion: defineNumber(1, CONTRACT_VERSION),
33
- codeHash: defineString("e05d18c3cc72", "source")
33
+ codeHash: defineString("1fc975838e46", "source")
34
34
  });
35
35
  function daemonStatusBuildInfo() {
36
36
  return { ...BUILD_INFO };
@@ -4741,12 +4741,12 @@ class QuotaSource {
4741
4741
  return candidates;
4742
4742
  }
4743
4743
  const binDir = join5(this.homeDir, ".budget-guard/bin");
4744
- const installedBudgetProbe = join5(binDir, "budget-probe");
4745
- if (existsSync5(installedBudgetProbe))
4746
- add(installedBudgetProbe, "budget-probe");
4747
4744
  const installedProbeMjs = join5(binDir, "probe.mjs");
4748
4745
  if (existsSync5(installedProbeMjs))
4749
4746
  add(installedProbeMjs, "probe-mjs");
4747
+ const installedBudgetProbe = join5(binDir, "budget-probe");
4748
+ if (existsSync5(installedBudgetProbe))
4749
+ add(installedBudgetProbe, "budget-probe");
4750
4750
  return candidates;
4751
4751
  }
4752
4752
  async fetchAgent(candidates, agent) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@raysonmeng/agentbridge",
3
- "version": "0.1.14",
3
+ "version": "0.1.16",
4
4
  "description": "Bridge between Claude Code and Codex — bidirectional agent communication via MCP Channel + JSON-RPC",
5
5
  "type": "module",
6
6
  "packageManager": "bun@1.3.11",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentbridge",
3
- "version": "0.1.14",
3
+ "version": "0.1.16",
4
4
  "description": "Bridge Claude Code and Codex with a shared daemon, push channel delivery, and bidirectional reply tooling.",
5
5
  "author": {
6
6
  "name": "AgentBridge Contributors",
@@ -14511,11 +14511,11 @@ function defineNumber(value, fallback) {
14511
14511
  return typeof value === "number" && Number.isFinite(value) ? value : fallback;
14512
14512
  }
14513
14513
  var BUILD_INFO = Object.freeze({
14514
- version: defineString("0.1.14", "0.0.0-source"),
14515
- commit: defineString("f5a9562", "source"),
14514
+ version: defineString("0.1.16", "0.0.0-source"),
14515
+ commit: defineString("1dc5e4f", "source"),
14516
14516
  bundle: defineBundle("plugin"),
14517
14517
  contractVersion: defineNumber(1, CONTRACT_VERSION),
14518
- codeHash: defineString("e05d18c3cc72", "source")
14518
+ codeHash: defineString("1fc975838e46", "source")
14519
14519
  });
14520
14520
  function sameRuntimeContract(a, b) {
14521
14521
  if (!a || !b)
@@ -26,11 +26,11 @@ function defineNumber(value, fallback) {
26
26
  return typeof value === "number" && Number.isFinite(value) ? value : fallback;
27
27
  }
28
28
  var BUILD_INFO = Object.freeze({
29
- version: defineString("0.1.14", "0.0.0-source"),
30
- commit: defineString("f5a9562", "source"),
29
+ version: defineString("0.1.16", "0.0.0-source"),
30
+ commit: defineString("1dc5e4f", "source"),
31
31
  bundle: defineBundle("plugin"),
32
32
  contractVersion: defineNumber(1, CONTRACT_VERSION),
33
- codeHash: defineString("e05d18c3cc72", "source")
33
+ codeHash: defineString("1fc975838e46", "source")
34
34
  });
35
35
  function daemonStatusBuildInfo() {
36
36
  return { ...BUILD_INFO };
@@ -4741,12 +4741,12 @@ class QuotaSource {
4741
4741
  return candidates;
4742
4742
  }
4743
4743
  const binDir = join5(this.homeDir, ".budget-guard/bin");
4744
- const installedBudgetProbe = join5(binDir, "budget-probe");
4745
- if (existsSync5(installedBudgetProbe))
4746
- add(installedBudgetProbe, "budget-probe");
4747
4744
  const installedProbeMjs = join5(binDir, "probe.mjs");
4748
4745
  if (existsSync5(installedProbeMjs))
4749
4746
  add(installedProbeMjs, "probe-mjs");
4747
+ const installedBudgetProbe = join5(binDir, "budget-probe");
4748
+ if (existsSync5(installedBudgetProbe))
4749
+ add(installedBudgetProbe, "budget-probe");
4750
4750
  return candidates;
4751
4751
  }
4752
4752
  async fetchAgent(candidates, agent) {