botmux 2.67.0 → 2.68.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.
Files changed (71) hide show
  1. package/dist/adapters/backend/tmux-pipe-backend.d.ts +7 -2
  2. package/dist/adapters/backend/tmux-pipe-backend.d.ts.map +1 -1
  3. package/dist/adapters/backend/tmux-pipe-backend.js +12 -5
  4. package/dist/adapters/backend/tmux-pipe-backend.js.map +1 -1
  5. package/dist/adapters/cli/codex-app.d.ts.map +1 -1
  6. package/dist/adapters/cli/codex-app.js +5 -17
  7. package/dist/adapters/cli/codex-app.js.map +1 -1
  8. package/dist/adapters/cli/mira.d.ts.map +1 -1
  9. package/dist/adapters/cli/mira.js +4 -17
  10. package/dist/adapters/cli/mira.js.map +1 -1
  11. package/dist/adapters/cli/pi.d.ts.map +1 -1
  12. package/dist/adapters/cli/pi.js +0 -1
  13. package/dist/adapters/cli/pi.js.map +1 -1
  14. package/dist/adapters/cli/runner-input.d.ts +66 -0
  15. package/dist/adapters/cli/runner-input.d.ts.map +1 -0
  16. package/dist/adapters/cli/runner-input.js +125 -0
  17. package/dist/adapters/cli/runner-input.js.map +1 -0
  18. package/dist/adapters/cli/types.d.ts +8 -4
  19. package/dist/adapters/cli/types.d.ts.map +1 -1
  20. package/dist/cli.d.ts.map +1 -1
  21. package/dist/cli.js +79 -17
  22. package/dist/cli.js.map +1 -1
  23. package/dist/core/auto-start.d.ts +23 -0
  24. package/dist/core/auto-start.d.ts.map +1 -1
  25. package/dist/core/auto-start.js +30 -0
  26. package/dist/core/auto-start.js.map +1 -1
  27. package/dist/core/command-handler.d.ts +9 -9
  28. package/dist/core/command-handler.d.ts.map +1 -1
  29. package/dist/core/command-handler.js +23 -16
  30. package/dist/core/command-handler.js.map +1 -1
  31. package/dist/core/cost-calculator.d.ts +27 -0
  32. package/dist/core/cost-calculator.d.ts.map +1 -1
  33. package/dist/core/cost-calculator.js +483 -27
  34. package/dist/core/cost-calculator.js.map +1 -1
  35. package/dist/core/dashboard-rows.d.ts +3 -0
  36. package/dist/core/dashboard-rows.d.ts.map +1 -1
  37. package/dist/core/dashboard-rows.js +11 -0
  38. package/dist/core/dashboard-rows.js.map +1 -1
  39. package/dist/core/worker-pool.d.ts.map +1 -1
  40. package/dist/core/worker-pool.js +22 -1
  41. package/dist/core/worker-pool.js.map +1 -1
  42. package/dist/daemon.d.ts.map +1 -1
  43. package/dist/daemon.js +15 -6
  44. package/dist/daemon.js.map +1 -1
  45. package/dist/dashboard/web/i18n.d.ts.map +1 -1
  46. package/dist/dashboard/web/i18n.js +4 -0
  47. package/dist/dashboard/web/i18n.js.map +1 -1
  48. package/dist/dashboard/web/sessions.d.ts.map +1 -1
  49. package/dist/dashboard/web/sessions.js +16 -1
  50. package/dist/dashboard/web/sessions.js.map +1 -1
  51. package/dist/dashboard-web/app.js +120 -116
  52. package/dist/dashboard-web/style.css +4 -0
  53. package/dist/dashboard.js +41 -13
  54. package/dist/dashboard.js.map +1 -1
  55. package/dist/i18n/en.js +2 -2
  56. package/dist/i18n/en.js.map +1 -1
  57. package/dist/i18n/zh.js +2 -2
  58. package/dist/i18n/zh.js.map +1 -1
  59. package/dist/services/aiden-checkpoints.d.ts +5 -0
  60. package/dist/services/aiden-checkpoints.d.ts.map +1 -0
  61. package/dist/services/aiden-checkpoints.js +91 -0
  62. package/dist/services/aiden-checkpoints.js.map +1 -0
  63. package/dist/services/codex-transcript.d.ts +7 -0
  64. package/dist/services/codex-transcript.d.ts.map +1 -1
  65. package/dist/services/codex-transcript.js +60 -1
  66. package/dist/services/codex-transcript.js.map +1 -1
  67. package/dist/services/usage-ledger.d.ts +81 -0
  68. package/dist/services/usage-ledger.d.ts.map +1 -0
  69. package/dist/services/usage-ledger.js +353 -0
  70. package/dist/services/usage-ledger.js.map +1 -0
  71. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -1131,6 +1131,7 @@ async function cmdStart() {
1131
1131
  if (refreshAutostart({ pkgRoot: PKG_ROOT, configDir: CONFIG_DIR, logDir: LOG_DIR })) {
1132
1132
  console.log(` autostart unit 已同步到当前 Node/cli.js 路径`);
1133
1133
  }
1134
+ await printDashboardHintWithRetry();
1134
1135
  }
1135
1136
  /**
1136
1137
  * Wipe stale dashboard-daemon descriptors (mtime older than 5 minutes).
@@ -1270,6 +1271,7 @@ async function cmdRestart() {
1270
1271
  if (refreshAutostart({ pkgRoot: PKG_ROOT, configDir: CONFIG_DIR, logDir: LOG_DIR })) {
1271
1272
  console.log(`autostart unit 已同步到当前 Node/cli.js 路径`);
1272
1273
  }
1274
+ await printDashboardHintWithRetry();
1273
1275
  }
1274
1276
  /** Wraps `ensureDependencies()`. Neither tmux nor fonts are load-bearing —
1275
1277
  * ensureDependencies surfaces failures as warnings and the daemon continues
@@ -1380,30 +1382,29 @@ function cmdUpgrade() {
1380
1382
  }
1381
1383
  }
1382
1384
  /**
1383
- * Print a fresh dashboard URL by HMAC-authing to the dashboard process's
1384
- * loopback rotation endpoint. Each call invalidates the previously-issued
1385
- * token, so sharing a URL is the same as sharing a one-shot session.
1385
+ * Call one of the dashboard's loopback HMAC `/__cli/*` endpoints.
1386
+ * - `/__cli/rotate` mints a fresh token and returns its URL, invalidating the
1387
+ * previously-issued link.
1388
+ * - `/__cli/current` returns the existing token's URL WITHOUT rotating (404 →
1389
+ * no token has ever been minted → `no-active-token`).
1390
+ * Returns { ok: true, url } on success, or { ok: false, reason } so callers can
1391
+ * decide how to surface the failure (hard error vs soft hint).
1386
1392
  */
1387
- async function cmdDashboard() {
1393
+ async function callDashboardEndpoint(path) {
1388
1394
  const SECRET_PATH = join(CONFIG_DIR, '.dashboard-secret');
1389
- if (!existsSync(SECRET_PATH)) {
1390
- console.error('Dashboard not initialised. Run `botmux restart` first.');
1391
- process.exit(1);
1392
- }
1395
+ if (!existsSync(SECRET_PATH))
1396
+ return { ok: false, reason: 'no-secret' };
1393
1397
  const secret = readFileSync(SECRET_PATH, 'utf8').trim();
1394
1398
  const ts = Math.floor(Date.now() / 1000).toString();
1395
1399
  const nonce = randomBytes(8).toString('hex');
1396
1400
  const sig = createHmac('sha256', secret).update(`${ts}:${nonce}`).digest('base64url');
1397
- // Prefer the port the dashboard actually bound (it probes upward on
1398
- // EADDRINUSE, so the live port can differ from the configured default). The
1399
- // running dashboard refreshes this file on every successful bind.
1400
1401
  const portFile = join(CONFIG_DIR, '.dashboard-port');
1401
1402
  const port = (existsSync(portFile) ? readFileSync(portFile, 'utf8').trim() : '')
1402
1403
  || process.env.BOTMUX_DASHBOARD_PORT
1403
1404
  || '7891';
1404
1405
  let res;
1405
1406
  try {
1406
- res = await fetch(`http://127.0.0.1:${port}/__cli/rotate`, {
1407
+ res = await fetch(`http://127.0.0.1:${port}${path}`, {
1407
1408
  method: 'POST',
1408
1409
  headers: {
1409
1410
  'X-Botmux-Cli-Ts': ts,
@@ -1413,15 +1414,76 @@ async function cmdDashboard() {
1413
1414
  });
1414
1415
  }
1415
1416
  catch {
1416
- console.error(`dashboard process not reachable on 127.0.0.1:${port} \`botmux restart\` will start it`);
1417
- process.exit(1);
1417
+ return { ok: false, reason: 'unreachable' };
1418
1418
  }
1419
+ if (res.status === 404)
1420
+ return { ok: false, reason: 'no-active-token' };
1419
1421
  if (!res.ok) {
1420
- console.error('Rotation failed:', res.status, await res.text());
1421
- process.exit(1);
1422
+ return { ok: false, reason: 'http-error', detail: `${res.status} ${await res.text()}` };
1422
1423
  }
1423
1424
  const body = await res.json();
1424
- console.log(body.url);
1425
+ return { ok: true, url: body.url };
1426
+ }
1427
+ /**
1428
+ * Best-effort dashboard hint printed after start/restart. Reads the LIVE link
1429
+ * via /__cli/current (non-rotating) so an already-shared URL is preserved.
1430
+ * Retries for a few seconds since the dashboard process boots after the daemon;
1431
+ * if it still isn't ready, prints a soft fallback so the user isn't blocked.
1432
+ */
1433
+ async function printDashboardHintWithRetry() {
1434
+ const maxWaitMs = 6000;
1435
+ const stepMs = 500;
1436
+ const started = Date.now();
1437
+ let last = null;
1438
+ while (Date.now() - started < maxWaitMs) {
1439
+ last = await callDashboardEndpoint('/__cli/current');
1440
+ if (last.ok) {
1441
+ console.log(` 面板: botmux dashboard (${last.url})`);
1442
+ return;
1443
+ }
1444
+ // Terminal states — file-backed secret/token won't appear mid-poll, unlike
1445
+ // a not-yet-listening port. Don't spin on them.
1446
+ if (last.reason === 'no-secret' || last.reason === 'no-active-token')
1447
+ break;
1448
+ await new Promise(r => setTimeout(r, stepMs));
1449
+ }
1450
+ // Soft fallback
1451
+ if (last?.reason === 'no-active-token') {
1452
+ console.log(' 面板: 运行 `botmux dashboard` 获取链接');
1453
+ }
1454
+ else if (last?.reason === 'no-secret') {
1455
+ console.log(' 面板: dashboard 凭证未就绪,启动后可用 `botmux dashboard` 获取链接');
1456
+ }
1457
+ else {
1458
+ console.log(' 面板: `botmux dashboard`(daemon 启动中,稍后可获取链接)');
1459
+ }
1460
+ }
1461
+ /**
1462
+ * Print a fresh dashboard URL by HMAC-authing to the dashboard process's
1463
+ * loopback rotation endpoint. Each call invalidates the previously-issued
1464
+ * token, so sharing a URL is the same as sharing a one-shot session.
1465
+ */
1466
+ async function cmdDashboard() {
1467
+ const r = await callDashboardEndpoint('/__cli/rotate');
1468
+ if (r.ok) {
1469
+ console.log(r.url);
1470
+ return;
1471
+ }
1472
+ if (r.reason === 'no-secret') {
1473
+ console.error('Dashboard not initialised. Run `botmux restart` first.');
1474
+ }
1475
+ else if (r.reason === 'unreachable') {
1476
+ const portFile = join(CONFIG_DIR, '.dashboard-port');
1477
+ const port = (existsSync(portFile) ? readFileSync(portFile, 'utf8').trim() : '')
1478
+ || process.env.BOTMUX_DASHBOARD_PORT
1479
+ || '7891';
1480
+ console.error(`dashboard process not reachable on 127.0.0.1:${port} — \`botmux restart\` will start it`);
1481
+ }
1482
+ else {
1483
+ // `no-active-token` can't occur on rotate (it always mints); fall through.
1484
+ console.error('Rotation failed:', r.detail ?? r.reason);
1485
+ }
1486
+ process.exit(1);
1425
1487
  }
1426
1488
  /**
1427
1489
  * Resolve the session data directory.