botmux 2.96.1 → 2.97.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.
- package/dist/adapters/backend/session-backend-selector.d.ts +32 -0
- package/dist/adapters/backend/session-backend-selector.d.ts.map +1 -1
- package/dist/adapters/backend/session-backend-selector.js +41 -0
- package/dist/adapters/backend/session-backend-selector.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +32 -6
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +11 -8
- package/dist/config.js.map +1 -1
- package/dist/core/command-handler.d.ts.map +1 -1
- package/dist/core/command-handler.js +6 -1
- package/dist/core/command-handler.js.map +1 -1
- package/dist/core/persistent-backend.d.ts +18 -5
- package/dist/core/persistent-backend.d.ts.map +1 -1
- package/dist/core/persistent-backend.js +21 -10
- package/dist/core/persistent-backend.js.map +1 -1
- package/dist/core/worker-pool.d.ts.map +1 -1
- package/dist/core/worker-pool.js +11 -0
- package/dist/core/worker-pool.js.map +1 -1
- package/dist/platform/bind.d.ts.map +1 -1
- package/dist/platform/bind.js +6 -1
- package/dist/platform/bind.js.map +1 -1
- package/dist/platform/tunnel-client.d.ts.map +1 -1
- package/dist/platform/tunnel-client.js +7 -2
- package/dist/platform/tunnel-client.js.map +1 -1
- package/dist/setup/ensure-tmux.d.ts +9 -0
- package/dist/setup/ensure-tmux.d.ts.map +1 -1
- package/dist/setup/ensure-tmux.js +7 -2
- package/dist/setup/ensure-tmux.js.map +1 -1
- package/dist/setup/ensure-zellij.d.ts.map +1 -1
- package/dist/setup/ensure-zellij.js +4 -3
- package/dist/setup/ensure-zellij.js.map +1 -1
- package/dist/setup/index.d.ts +25 -0
- package/dist/setup/index.d.ts.map +1 -1
- package/dist/setup/index.js +52 -8
- package/dist/setup/index.js.map +1 -1
- package/dist/types.d.ts +12 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/worker.js +83 -22
- package/dist/worker.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,4 +1,36 @@
|
|
|
1
1
|
import type { BackendType, SessionBackend } from './types.js';
|
|
2
|
+
export type BackendGateDecision = {
|
|
3
|
+
action: 'spawn';
|
|
4
|
+
} | {
|
|
5
|
+
action: 'gate';
|
|
6
|
+
reason: string;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Hard gate (PTY 退役): a requested *persistent* backend (tmux/herdr/zellij)
|
|
10
|
+
* that isn't functional on this host no longer silently degrades to raw PTY.
|
|
11
|
+
* That silent fallback was the root of the "secretly running on PTY, then
|
|
12
|
+
* hitting all of PTY's problems (no survival across daemon restart, etc.)"
|
|
13
|
+
* bug class. Instead the worker refuses to spawn and posts an actionable card.
|
|
14
|
+
*
|
|
15
|
+
* PTY stays reachable ONLY as an explicit opt-in — `BACKEND_TYPE=pty` or a
|
|
16
|
+
* per-bot `backendType: 'pty'` — which arrives here as `requested === 'pty'`
|
|
17
|
+
* and is always allowed straight through.
|
|
18
|
+
*
|
|
19
|
+
* `hasExistingSession` lets an already-running persistent session reattach
|
|
20
|
+
* regardless of a transient probe failure (a disposable "can we start a new
|
|
21
|
+
* server?" probe is far less authoritative than a live session — see PR#249):
|
|
22
|
+
* abandoning it would spawn a duplicate CLI and orphan the real conversation.
|
|
23
|
+
* The caller computes it only for backends whose probe is a disposable
|
|
24
|
+
* session (tmux, zellij); herdr's probe is a cheap non-destructive
|
|
25
|
+
* `herdr --version`, so it passes `hasExistingSession: false`.
|
|
26
|
+
*/
|
|
27
|
+
export declare function decideBackendGate(opts: {
|
|
28
|
+
requested: BackendType;
|
|
29
|
+
available: boolean;
|
|
30
|
+
hasExistingSession: boolean;
|
|
31
|
+
}): BackendGateDecision;
|
|
32
|
+
/** User-facing card shown when {@link decideBackendGate} gates a session. */
|
|
33
|
+
export declare function backendGateUserMessage(backend: BackendType, reason: string): string;
|
|
2
34
|
export interface SelectedSessionBackend {
|
|
3
35
|
backend: SessionBackend;
|
|
4
36
|
isTmuxMode: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-backend-selector.d.ts","sourceRoot":"","sources":["../../../src/adapters/backend/session-backend-selector.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE9D,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,cAAc,CAAC;IACxB,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;IACpB;;mFAE+E;IAC/E,YAAY,EAAE,OAAO,CAAC;CACvB;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,WAAW,CAAA;CAAE,GAAG,sBAAsB,CAwDlH"}
|
|
1
|
+
{"version":3,"file":"session-backend-selector.d.ts","sourceRoot":"","sources":["../../../src/adapters/backend/session-backend-selector.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE9D,MAAM,MAAM,mBAAmB,GAC3B;IAAE,MAAM,EAAE,OAAO,CAAA;CAAE,GACnB;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvC;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE;IACtC,SAAS,EAAE,WAAW,CAAC;IACvB,SAAS,EAAE,OAAO,CAAC;IACnB,kBAAkB,EAAE,OAAO,CAAC;CAC7B,GAAG,mBAAmB,CAKtB;AAED,6EAA6E;AAC7E,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAYnF;AAED,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,cAAc,CAAC;IACxB,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;IACpB;;mFAE+E;IAC/E,YAAY,EAAE,OAAO,CAAC;CACvB;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,WAAW,CAAA;CAAE,GAAG,sBAAsB,CAwDlH"}
|
|
@@ -3,6 +3,47 @@ import { PtyBackend } from './pty-backend.js';
|
|
|
3
3
|
import { TmuxBackend } from './tmux-backend.js';
|
|
4
4
|
import { TmuxPipeBackend } from './tmux-pipe-backend.js';
|
|
5
5
|
import { ZellijBackend } from './zellij-backend.js';
|
|
6
|
+
/**
|
|
7
|
+
* Hard gate (PTY 退役): a requested *persistent* backend (tmux/herdr/zellij)
|
|
8
|
+
* that isn't functional on this host no longer silently degrades to raw PTY.
|
|
9
|
+
* That silent fallback was the root of the "secretly running on PTY, then
|
|
10
|
+
* hitting all of PTY's problems (no survival across daemon restart, etc.)"
|
|
11
|
+
* bug class. Instead the worker refuses to spawn and posts an actionable card.
|
|
12
|
+
*
|
|
13
|
+
* PTY stays reachable ONLY as an explicit opt-in — `BACKEND_TYPE=pty` or a
|
|
14
|
+
* per-bot `backendType: 'pty'` — which arrives here as `requested === 'pty'`
|
|
15
|
+
* and is always allowed straight through.
|
|
16
|
+
*
|
|
17
|
+
* `hasExistingSession` lets an already-running persistent session reattach
|
|
18
|
+
* regardless of a transient probe failure (a disposable "can we start a new
|
|
19
|
+
* server?" probe is far less authoritative than a live session — see PR#249):
|
|
20
|
+
* abandoning it would spawn a duplicate CLI and orphan the real conversation.
|
|
21
|
+
* The caller computes it only for backends whose probe is a disposable
|
|
22
|
+
* session (tmux, zellij); herdr's probe is a cheap non-destructive
|
|
23
|
+
* `herdr --version`, so it passes `hasExistingSession: false`.
|
|
24
|
+
*/
|
|
25
|
+
export function decideBackendGate(opts) {
|
|
26
|
+
if (opts.requested === 'pty')
|
|
27
|
+
return { action: 'spawn' };
|
|
28
|
+
if (opts.hasExistingSession)
|
|
29
|
+
return { action: 'spawn' };
|
|
30
|
+
if (opts.available)
|
|
31
|
+
return { action: 'spawn' };
|
|
32
|
+
return { action: 'gate', reason: `${opts.requested} 后端在本机不可用` };
|
|
33
|
+
}
|
|
34
|
+
/** User-facing card shown when {@link decideBackendGate} gates a session. */
|
|
35
|
+
export function backendGateUserMessage(backend, reason) {
|
|
36
|
+
const installHint = backend === 'tmux'
|
|
37
|
+
? 'macOS: brew install tmux | Debian/Ubuntu: sudo apt-get install -y tmux | 其它发行版用对应包管理器安装 tmux'
|
|
38
|
+
: `请确认 ${backend} 已正确安装并可用`;
|
|
39
|
+
return [
|
|
40
|
+
`⚠️ 本机 ${backend} 不可用,无法启动会话。`,
|
|
41
|
+
`原因:${reason}`,
|
|
42
|
+
`请安装/修复后重试 —— ${installHint}`,
|
|
43
|
+
`(如确需在没有 ${backend} 的环境运行,可显式设置环境变量 BACKEND_TYPE=pty 用 PTY 后端兜底;` +
|
|
44
|
+
`但 PTY 会话不跨 daemon 重启存活,仅作应急。)`,
|
|
45
|
+
].join('\n');
|
|
46
|
+
}
|
|
6
47
|
export function selectSessionBackend(opts) {
|
|
7
48
|
if (opts.backendType === 'zellij') {
|
|
8
49
|
const sessionName = ZellijBackend.sessionName(opts.sessionId);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-backend-selector.js","sourceRoot":"","sources":["../../../src/adapters/backend/session-backend-selector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"session-backend-selector.js","sourceRoot":"","sources":["../../../src/adapters/backend/session-backend-selector.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAq5JA;;;;;;;;;;;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,GACzF,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CA8F7B"}
|
package/dist/cli.js
CHANGED
|
@@ -1376,18 +1376,44 @@ async function cmdRestart() {
|
|
|
1376
1376
|
}
|
|
1377
1377
|
await printDashboardHintWithRetry();
|
|
1378
1378
|
}
|
|
1379
|
-
/** Wraps `ensureDependencies()`.
|
|
1380
|
-
*
|
|
1381
|
-
*
|
|
1379
|
+
/** Wraps `ensureDependencies()`. Fonts are nice-to-have (warn only). tmux is
|
|
1380
|
+
* required since PTY 退役: if it's GENUINELY ABSENT and a bot wants the tmux
|
|
1381
|
+
* backend (and the operator hasn't opted into BACKEND_TYPE=pty), we hard-fail
|
|
1382
|
+
* here — non-zero exit, no pm2 spawn — so an unattended `start`/`restart`
|
|
1383
|
+
* surfaces the failure instead of bringing up a daemon whose every session
|
|
1384
|
+
* would gate at first message. A present-but-broken tmux (functional probe
|
|
1385
|
+
* flaked) is NOT fatal: the daemon still starts and degrades per-session, so a
|
|
1386
|
+
* transient probe failure can't block reattaching live sessions (PR#249). An
|
|
1387
|
+
* unexpected exception in the probe itself is non-fatal for the same reason. */
|
|
1382
1388
|
async function ensureSystemDependencies() {
|
|
1383
|
-
const { ensureDependencies } = await import('./setup/index.js');
|
|
1389
|
+
const { ensureDependencies, shouldHardFailStartupForMissingTmux } = await import('./setup/index.js');
|
|
1390
|
+
let report;
|
|
1384
1391
|
try {
|
|
1385
|
-
await ensureDependencies();
|
|
1392
|
+
report = await ensureDependencies();
|
|
1386
1393
|
}
|
|
1387
1394
|
catch (err) {
|
|
1388
1395
|
console.error('');
|
|
1389
1396
|
console.error(`依赖检测内部错误: ${err?.message ?? String(err)}`);
|
|
1390
|
-
// Don't exit —
|
|
1397
|
+
// Don't exit — a probe-internal error is not a confirmed "tmux missing".
|
|
1398
|
+
return;
|
|
1399
|
+
}
|
|
1400
|
+
// loadBotsJson() returns [] when bots.json is absent (→ no bot wants tmux) and
|
|
1401
|
+
// hard-exits on a malformed file (existing fast-fail) — it never throws here.
|
|
1402
|
+
const anyBotWantsTmux = loadBotsJson().some(b => (b?.backendType ?? config.daemon.backendType) === 'tmux');
|
|
1403
|
+
const ptyOptIn = (process.env.BACKEND_TYPE ?? '').toLowerCase() === 'pty';
|
|
1404
|
+
if (shouldHardFailStartupForMissingTmux({
|
|
1405
|
+
tmuxInstalled: report.tmux.installed,
|
|
1406
|
+
tmuxBinaryPresent: report.tmux.binaryPresent === true,
|
|
1407
|
+
anyBotWantsTmux,
|
|
1408
|
+
ptyOptIn,
|
|
1409
|
+
})) {
|
|
1410
|
+
console.error('');
|
|
1411
|
+
console.error('❌ tmux 未安装,已中止 daemon 启动 —— 默认走 tmux 后端的会话将全部无法运行。');
|
|
1412
|
+
console.error(' 请按上方指引安装 tmux 后重试。');
|
|
1413
|
+
console.error(' 如确需在没有 tmux 的环境运行,可显式用 PTY 兜底:BACKEND_TYPE=pty botmux start');
|
|
1414
|
+
console.error(' (注意:PTY 会话不跨 daemon 重启存活,仅作应急。)');
|
|
1415
|
+
console.error('');
|
|
1416
|
+
process.exit(1);
|
|
1391
1417
|
}
|
|
1392
1418
|
}
|
|
1393
1419
|
/**
|