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.
- package/dist/.runtime-build-id +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +26 -34
- package/dist/cli.js.map +1 -1
- package/dist/core/legacy-pm2-reaper.d.ts +61 -3
- package/dist/core/legacy-pm2-reaper.d.ts.map +1 -1
- package/dist/core/legacy-pm2-reaper.js +318 -27
- package/dist/core/legacy-pm2-reaper.js.map +1 -1
- package/package.json +7 -7
package/dist/.runtime-build-id
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
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;
|
|
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
|
|
2159
|
-
*
|
|
2160
|
-
*
|
|
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
|
|
2519
|
-
*
|
|
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.
|
|
2523
|
-
* God was observed supervising 50 daemons with NO
|
|
2524
|
-
* pid-file-only probe stayed silent through exactly the
|
|
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 (
|
|
2550
|
+
if (liveGodAt(dedicated) !== null)
|
|
2537
2551
|
return true;
|
|
2538
2552
|
const shared = join(homedir(), '.pm2');
|
|
2539
|
-
return
|
|
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.
|