botmux 3.18.0 → 3.18.1-canary.2

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.
@@ -1 +1 @@
1
- dee42b7568bfaa29896b1b763f12f3e1020cae4f4a0be0fb78af7a8f1b8605e8
1
+ 0b8be9043c07b1df66f6cb5da350502c10659cba98c32c50f8e513cb67d24f4d
package/dist/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AA8BA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AA6KhD,OAAO,EAAE,KAAK,KAAK,EAA0C,MAAM,yBAAyB,CAAC;AAujB7F;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,iBAAiB,CAAC,EAAE,EAAE,UAAU,CAAC,OAAO,eAAe,CAAC,GAAG,OAAO,CACpF;IACE,EAAE,EAAE,IAAI,CAAC;IACT,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,KAAK,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,oDAAoD;IACpD,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B,GACD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,WAAW,CAAA;CAAE,CACrC,CA6LA;AAykDD,MAAM,MAAM,kBAAkB,GAC1B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,SAAS,GAAG,gBAAgB,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GACtE;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,WAAW,GAAG,WAAW,GAAG,YAAY,GAAG,SAAS,GAAG,kBAAkB,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtH,MAAM,MAAM,iBAAiB,GACzB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,SAAS,GAAG,iBAAiB,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GACvE;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,WAAW,GAAG,YAAY,GAAG,SAAS,GAAG,kBAAkB,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AA6jQxG;;;;;;;;;;;GAWG;AACH,wBAAsB,OAAO,CAC3B,OAAO,EAAE,OAAO,EAChB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,EACvC,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,OAAO,qBAAqB,EAAE,SAAS,CAAC,EAC9F,KAAK,EAAE,MAAM,EACb,mBAAmB,CAAC,EAAE,MAAM,OAAO,CAAC,OAAO,2BAA2B,EAAE,UAAU,GAAG,IAAI,CAAC;AAC1F;qDACqD;AACrD,wBAAwB,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,2BAA2B,EAAE,UAAU,GAAG,IAAI,CAAC,GAClH,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAuL7B"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AA8BA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AA6KhD,OAAO,EAAE,KAAK,KAAK,EAA0C,MAAM,yBAAyB,CAAC;AAujB7F;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,iBAAiB,CAAC,EAAE,EAAE,UAAU,CAAC,OAAO,eAAe,CAAC,GAAG,OAAO,CACpF;IACE,EAAE,EAAE,IAAI,CAAC;IACT,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,KAAK,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,oDAAoD;IACpD,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B,GACD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,WAAW,CAAA;CAAE,CACrC,CA6LA;AAmlDD,MAAM,MAAM,kBAAkB,GAC1B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,SAAS,GAAG,gBAAgB,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GACtE;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,WAAW,GAAG,WAAW,GAAG,YAAY,GAAG,SAAS,GAAG,kBAAkB,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtH,MAAM,MAAM,iBAAiB,GACzB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,SAAS,GAAG,iBAAiB,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GACvE;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,WAAW,GAAG,YAAY,GAAG,SAAS,GAAG,kBAAkB,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAmjQxG;;;;;;;;;;;GAWG;AACH,wBAAsB,OAAO,CAC3B,OAAO,EAAE,OAAO,EAChB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,EACvC,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,OAAO,qBAAqB,EAAE,SAAS,CAAC,EAC9F,KAAK,EAAE,MAAM,EACb,mBAAmB,CAAC,EAAE,MAAM,OAAO,CAAC,OAAO,2BAA2B,EAAE,UAAU,GAAG,IAAI,CAAC;AAC1F;qDACqD;AACrD,wBAAwB,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,2BAA2B,EAAE,UAAU,GAAG,IAAI,CAAC,GAClH,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAuL7B"}
package/dist/cli.js CHANGED
@@ -55,7 +55,7 @@ import { buildPreset, serializePreset, presetFilename } from './setup/agent-pres
55
55
  import { validateCodexAppManagedSendOrigin, } from './utils/codex-app-dispatch-ledger.js';
56
56
  import { hasProtectedSessionMutationOwnership } from './core/session-mutation-guard.js';
57
57
  import { logger } from './utils/logger.js';
58
- import { reapLegacyPm2 } from './core/legacy-pm2-reaper.js';
58
+ import { reapLegacyPm2, liveGodAt } from './core/legacy-pm2-reaper.js';
59
59
  import { withFileLock, withFileLockSync } from './utils/file-lock.js';
60
60
  import { scheduleTimeZone } from './utils/timezone.js';
61
61
  import { expandHomePath, invalidWorkingDirs } from './utils/working-dir.js';
@@ -2155,12 +2155,22 @@ function sleepSyncMs(ms) {
2155
2155
  * double-run alongside the supervisor. This detects that stale God and stops it
2156
2156
  * (delegated to the self-contained `reapLegacyPm2`), so the operator never has
2157
2157
  * to `pm2 kill` by hand. Fail-safe + no-op on fresh installs / when pm2 is
2158
- * absent (always the case for the compiled single binary). The `_op` parameter
2159
- * is retained for call-site compatibility but no longer changes behavior — the
2160
- * reaper is a single idempotent operation.
2158
+ * absent. The `_op` parameter is retained for call-site compatibility but no
2159
+ * longer changes behavior the reaper is a single idempotent operation.
2160
+ *
2161
+ * A reap that finds a God but cannot confirm it is down is reported on STDERR,
2162
+ * not just through `logger`: CLI mode runs with `logger.setSilent(true)`, so the
2163
+ * reaper's own notes are invisible without DEBUG. That silence is how a
2164
+ * double-run started unnoticed — both fleets live, two processes consuming the
2165
+ * same Feishu events and the same session sqlite. The operator needs to see it.
2161
2166
  */
2162
2167
  function cleanupLegacyPm2(_op) {
2163
2168
  const r = reapLegacyPm2(CONFIG_DIR, PKG_ROOT, (m) => logger.info(`[legacy-pm2] ${m}`));
2169
+ if (r.unresolved) {
2170
+ console.warn(`⚠️ 检测到迁移前的 pm2 守护进程,但未能确认其已停止:${r.note}`);
2171
+ console.warn(' 旧 fleet 可能仍在消费同一批飞书事件(消息重复、会话存储争用)。');
2172
+ console.warn(' 请手动确认:ps -ef | grep index-daemon 然后停掉旧进程后重试。');
2173
+ }
2164
2174
  return r.found;
2165
2175
  }
2166
2176
  async function cmdStop() {
@@ -2515,14 +2525,18 @@ async function ensureSystemDependencies() {
2515
2525
  * supervisor view while old pm2-managed daemons keep running. Self-contained:
2516
2526
  * no pm2 CLI call. `botmux start`/`restart` will reap it (reapLegacyPm2).
2517
2527
  *
2518
- * TWO SIGNALS, deliberately different per home this must agree with
2519
- * reapLegacyPm2's detection or the warning lies in one direction or the other:
2528
+ * TWO SIGNALS, deliberately different per home. Both go through the reaper's own
2529
+ * `liveGodAt` so the warning and the reaper cannot disagree this used to be a
2530
+ * second, hand-kept copy of that logic, and it drifted: it trusted a bare
2531
+ * `kill(pid, 0)` (true for the ZOMBIE a fresh reap leaves behind) and a bare
2532
+ * `existsSync(rpc.sock)` (which outlives `pm2 kill`), so the warning survived a
2533
+ * SUCCESSFUL migration and no amount of re-running `restart` could clear it.
2520
2534
  *
2521
2535
  * • The botmux-dedicated home (~/.botmux/pm2) is exclusively ours, so ANY live
2522
- * God there is a migration leftover. Detect it by pm2.pid OR rpc.sock: a real
2523
- * God was observed supervising 50 daemons with NO pm2.pid at all, and a
2524
- * pid-file-only probe stayed silent through exactly the situation this warning
2525
- * exists for.
2536
+ * God there is a migration leftover. `liveGodAt` detects it by pm2.pid OR a
2537
+ * held rpc.sock: a real God was observed supervising 50 daemons with NO
2538
+ * pm2.pid at all, and a pid-file-only probe stayed silent through exactly the
2539
+ * situation this warning exists for.
2526
2540
  *
2527
2541
  * • The shared default (~/.pm2) may be the user's own pm2 running unrelated
2528
2542
  * apps. A live God there means nothing by itself — MEASURED on this box: the
@@ -2533,32 +2547,10 @@ async function ensureSystemDependencies() {
2533
2547
  */
2534
2548
  function legacyBotmuxGodAlive() {
2535
2549
  const dedicated = join(CONFIG_DIR, 'pm2');
2536
- if (pm2GodAlive(dedicated))
2550
+ if (liveGodAt(dedicated) !== null)
2537
2551
  return true;
2538
2552
  const shared = join(homedir(), '.pm2');
2539
- return pm2GodAlive(shared) && sharedHomeHasBotmuxRows(shared);
2540
- }
2541
- /** A God is alive at `home` if its pid file points at a live process, or (when
2542
- * the file is missing/stale) its RPC socket is still there. */
2543
- function pm2GodAlive(home) {
2544
- const pidFile = join(home, 'pm2.pid');
2545
- if (existsSync(pidFile)) {
2546
- let pid = 0;
2547
- try {
2548
- pid = parseInt(readFileSync(pidFile, 'utf-8').trim(), 10);
2549
- }
2550
- catch {
2551
- pid = 0;
2552
- }
2553
- if (Number.isSafeInteger(pid) && pid > 1) {
2554
- try {
2555
- process.kill(pid, 0);
2556
- return true;
2557
- }
2558
- catch { /* stale — try the socket */ }
2559
- }
2560
- }
2561
- return existsSync(join(home, 'rpc.sock'));
2553
+ return liveGodAt(shared) !== null && sharedHomeHasBotmuxRows(shared);
2562
2554
  }
2563
2555
  /** Does the SHARED pm2 home actually hold botmux apps? pm2 writes one pid file
2564
2556
  * per app as `pids/<name>-<id>.pid`, so this answers it without running pm2.