botmux 3.18.1-canary.1 → 3.18.1
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/daemon-lifecycle-env.d.ts +1 -1
- package/dist/cli/daemon-lifecycle-env.d.ts.map +1 -1
- package/dist/cli/daemon-lifecycle-env.js +6 -0
- package/dist/cli/daemon-lifecycle-env.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +62 -31
- package/dist/cli.js.map +1 -1
- package/dist/core/current-actor-attestation.js +2 -2
- package/dist/core/current-actor-attestation.js.map +1 -1
- package/dist/core/dashboard-url.d.ts.map +1 -1
- package/dist/core/dashboard-url.js +9 -1
- package/dist/core/dashboard-url.js.map +1 -1
- package/dist/core/legacy-pm2-reaper.d.ts +51 -0
- package/dist/core/legacy-pm2-reaper.d.ts.map +1 -1
- package/dist/core/legacy-pm2-reaper.js +247 -17
- package/dist/core/legacy-pm2-reaper.js.map +1 -1
- package/dist/core/maintenance.d.ts.map +1 -1
- package/dist/core/maintenance.js +2 -0
- package/dist/core/maintenance.js.map +1 -1
- package/dist/core/terminal-url.d.ts.map +1 -1
- package/dist/core/terminal-url.js +11 -0
- package/dist/core/terminal-url.js.map +1 -1
- package/dist/dashboard/control-csrf.d.ts.map +1 -1
- package/dist/dashboard/control-csrf.js +21 -0
- package/dist/dashboard/control-csrf.js.map +1 -1
- package/dist/i18n/en.js +3 -3
- package/dist/i18n/en.js.map +1 -1
- package/dist/i18n/zh.js +3 -3
- package/dist/i18n/zh.js.map +1 -1
- package/dist/im/lark/card-handler.d.ts.map +1 -1
- package/dist/im/lark/card-handler.js +20 -9
- package/dist/im/lark/card-handler.js.map +1 -1
- package/dist/platform/devbox-dashboard-export.d.ts +32 -0
- package/dist/platform/devbox-dashboard-export.d.ts.map +1 -0
- package/dist/platform/devbox-dashboard-export.js +320 -0
- package/dist/platform/devbox-dashboard-export.js.map +1 -0
- package/dist/utils/dashboard-env.d.ts +1 -1
- package/dist/utils/dashboard-env.d.ts.map +1 -1
- package/dist/worker.js +5 -0
- package/dist/worker.js.map +1 -1
- package/package.json +7 -7
package/dist/.runtime-build-id
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
fe18e71ce88eb4d7f499718feca364ab691a40844341131b1eb806a5b2802e46
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const DAEMON_ENV_KEYS: readonly ["WEB_EXTERNAL_HOST", "BOTMUX_DASHBOARD_EXTERNAL_HOST", "BOTMUX_DASHBOARD_HOST", "BOTMUX_DASHBOARD_PORT", "BOTMUX_DAEMON_IPC_BASE_PORT", "BOTMUX_DASHBOARD_PUBLIC_READONLY", "BOTMUX_PUBLIC_URL", "BOTMUX_DASHBOARD_CONTROL_AUDIT_PATH", "BOTMUX_DASHBOARD_TERMINAL_CONTROL_TTL_MS"];
|
|
1
|
+
export declare const DAEMON_ENV_KEYS: readonly ["WEB_EXTERNAL_HOST", "BOTMUX_DASHBOARD_EXTERNAL_HOST", "BOTMUX_DASHBOARD_HOST", "BOTMUX_DASHBOARD_PORT", "BOTMUX_DAEMON_IPC_BASE_PORT", "BOTMUX_DASHBOARD_PUBLIC_READONLY", "BOTMUX_PUBLIC_URL", "BOTMUX_DASHBOARD_CONTROL_AUDIT_PATH", "BOTMUX_DASHBOARD_TERMINAL_CONTROL_TTL_MS", "BOTMUX_DEVBOX_AUTO_EXPORT"];
|
|
2
2
|
export type DaemonEnvKey = (typeof DAEMON_ENV_KEYS)[number];
|
|
3
3
|
/**
|
|
4
4
|
* Pin both PM2 apps to one deterministic ~/.botmux/.env snapshot. A restart
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"daemon-lifecycle-env.d.ts","sourceRoot":"","sources":["../../src/cli/daemon-lifecycle-env.ts"],"names":[],"mappings":"AAqBA,eAAO,MAAM,eAAe
|
|
1
|
+
{"version":3,"file":"daemon-lifecycle-env.d.ts","sourceRoot":"","sources":["../../src/cli/daemon-lifecycle-env.ts"],"names":[],"mappings":"AAqBA,eAAO,MAAM,eAAe,4TA6BlB,CAAC;AAEX,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;AAE5D;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAC9B,YAAY,EAAE,MAAM,CAAC,UAAU,EAC/B,WAAW,CAAC,EAAE,MAAM,GACnB,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,CAe9B"}
|
|
@@ -41,6 +41,12 @@ export const DAEMON_ENV_KEYS = [
|
|
|
41
41
|
// keeps them on the deterministic resolveDaemonEnv snapshot semantics.
|
|
42
42
|
'BOTMUX_DASHBOARD_CONTROL_AUDIT_PATH',
|
|
43
43
|
'BOTMUX_DASHBOARD_TERMINAL_CONTROL_TTL_MS',
|
|
44
|
+
// Merlin Devbox auto-export switch (platform/devbox-dashboard-export.ts).
|
|
45
|
+
// The dashboard resolves it (dashboard-url / control-csrf run there), so it
|
|
46
|
+
// has to survive the allowlist copy — same reason BOTMUX_PUBLIC_URL is here.
|
|
47
|
+
// The CLI, which is the side that spawns merlin-cli, has no dotenv step at
|
|
48
|
+
// all and reads the key straight from ~/.botmux/.env instead.
|
|
49
|
+
'BOTMUX_DEVBOX_AUTO_EXPORT',
|
|
44
50
|
];
|
|
45
51
|
/**
|
|
46
52
|
* Pin both PM2 apps to one deterministic ~/.botmux/.env snapshot. A restart
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"daemon-lifecycle-env.js","sourceRoot":"","sources":["../../src/cli/daemon-lifecycle-env.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAE/B,+EAA+E;AAC/E,iFAAiF;AACjF,6EAA6E;AAC7E,gFAAgF;AAChF,0EAA0E;AAC1E,0CAA0C;AAC1C,EAAE;AACF,8EAA8E;AAC9E,iEAAiE;AACjE,yEAAyE;AACzE,EAAE;AACF,gFAAgF;AAChF,+EAA+E;AAC/E,gFAAgF;AAChF,gFAAgF;AAChF,gFAAgF;AAChF,+EAA+E;AAC/E,4EAA4E;AAC5E,+BAA+B;AAC/B,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,mBAAmB;IACnB,gCAAgC;IAChC,uBAAuB;IACvB,uBAAuB;IACvB,6BAA6B;IAC7B,kCAAkC;IAClC,8DAA8D;IAC9D,yEAAyE;IACzE,yEAAyE;IACzE,2EAA2E;IAC3E,8CAA8C;IAC9C,mBAAmB;IACnB,qEAAqE;IACrE,wEAAwE;IACxE,gFAAgF;IAChF,6EAA6E;IAC7E,2EAA2E;IAC3E,sEAAsE;IACtE,4EAA4E;IAC5E,uEAAuE;IACvE,qCAAqC;IACrC,0CAA0C;
|
|
1
|
+
{"version":3,"file":"daemon-lifecycle-env.js","sourceRoot":"","sources":["../../src/cli/daemon-lifecycle-env.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAE/B,+EAA+E;AAC/E,iFAAiF;AACjF,6EAA6E;AAC7E,gFAAgF;AAChF,0EAA0E;AAC1E,0CAA0C;AAC1C,EAAE;AACF,8EAA8E;AAC9E,iEAAiE;AACjE,yEAAyE;AACzE,EAAE;AACF,gFAAgF;AAChF,+EAA+E;AAC/E,gFAAgF;AAChF,gFAAgF;AAChF,gFAAgF;AAChF,+EAA+E;AAC/E,4EAA4E;AAC5E,+BAA+B;AAC/B,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,mBAAmB;IACnB,gCAAgC;IAChC,uBAAuB;IACvB,uBAAuB;IACvB,6BAA6B;IAC7B,kCAAkC;IAClC,8DAA8D;IAC9D,yEAAyE;IACzE,yEAAyE;IACzE,2EAA2E;IAC3E,8CAA8C;IAC9C,mBAAmB;IACnB,qEAAqE;IACrE,wEAAwE;IACxE,gFAAgF;IAChF,6EAA6E;IAC7E,2EAA2E;IAC3E,sEAAsE;IACtE,4EAA4E;IAC5E,uEAAuE;IACvE,qCAAqC;IACrC,0CAA0C;IAC1C,0EAA0E;IAC1E,4EAA4E;IAC5E,6EAA6E;IAC7E,2EAA2E;IAC3E,8DAA8D;IAC9D,2BAA2B;CACnB,CAAC;AAIX;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,gBAAgB,CAC9B,YAA+B,EAC/B,WAAoB;IAEpB,MAAM,OAAO,GAAG,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IACpE,MAAM,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC,iBAAiB,EAAE,IAAI,EAAE,CAAC,CAAC;IACtE,MAAM,OAAO,GAAG,CAAC,GAAiB,EAAU,EAAE;QAC5C,MAAM,KAAK,GAAG,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC;QAC/E,OAAO,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IAC7B,CAAC,CAAC;IAEF,6EAA6E;IAC7E,oDAAoD;IACpD,MAAM,QAAQ,GAAG,MAAM,CAAC,WAAW,CACjC,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAChB,CAAC;IAClC,QAAQ,CAAC,qBAAqB,KAAK,SAAS,CAAC;IAC7C,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
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;
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AA8BA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAgLhD,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;AAmmQxG;;;;;;;;;;;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';
|
|
@@ -72,6 +72,9 @@ import { buildCardPatchSuccessOutput, CARD_COMMAND_USAGE, CARD_PATCH_USAGE, card
|
|
|
72
72
|
import { dispatchDeferredTopicSend, reusableDeferredTopicRoot } from './cli/deferred-topic-send.js';
|
|
73
73
|
import { readDeferredTopicBinding } from './core/deferred-topic-binding.js';
|
|
74
74
|
import { callDashboard } from './cli/dashboard-endpoint.js';
|
|
75
|
+
import { ensureDevboxDashboardExport } from './platform/devbox-dashboard-export.js';
|
|
76
|
+
import { platformMachineBaseUrl, publicReverseProxyBaseUrl } from './platform/binding.js';
|
|
77
|
+
import { isRemoteAccessEnabled } from './global-config.js';
|
|
75
78
|
import { DASHBOARD_COMMAND_USAGE, executeDashboardCommand, formatDashboardFallbackFailure, formatDashboardSuccessLines, } from './cli/dashboard-command.js';
|
|
76
79
|
import { globalInstallUpdateLockTarget, globalInstallUpdateLockTargetIn, installLatestBotmuxSync } from './core/maintenance.js';
|
|
77
80
|
import { formatGlobalInstallCommand, resolveGlobalInstallPlan, UnsupportedGlobalInstallError, } from './utils/global-install.js';
|
|
@@ -2525,14 +2528,18 @@ async function ensureSystemDependencies() {
|
|
|
2525
2528
|
* supervisor view while old pm2-managed daemons keep running. Self-contained:
|
|
2526
2529
|
* no pm2 CLI call. `botmux start`/`restart` will reap it (reapLegacyPm2).
|
|
2527
2530
|
*
|
|
2528
|
-
* TWO SIGNALS, deliberately different per home
|
|
2529
|
-
*
|
|
2531
|
+
* TWO SIGNALS, deliberately different per home. Both go through the reaper's own
|
|
2532
|
+
* `liveGodAt` so the warning and the reaper cannot disagree — this used to be a
|
|
2533
|
+
* second, hand-kept copy of that logic, and it drifted: it trusted a bare
|
|
2534
|
+
* `kill(pid, 0)` (true for the ZOMBIE a fresh reap leaves behind) and a bare
|
|
2535
|
+
* `existsSync(rpc.sock)` (which outlives `pm2 kill`), so the warning survived a
|
|
2536
|
+
* SUCCESSFUL migration and no amount of re-running `restart` could clear it.
|
|
2530
2537
|
*
|
|
2531
2538
|
* • The botmux-dedicated home (~/.botmux/pm2) is exclusively ours, so ANY live
|
|
2532
|
-
* God there is a migration leftover.
|
|
2533
|
-
* God was observed supervising 50 daemons with NO
|
|
2534
|
-
* pid-file-only probe stayed silent through exactly the
|
|
2535
|
-
* exists for.
|
|
2539
|
+
* God there is a migration leftover. `liveGodAt` detects it by pm2.pid OR a
|
|
2540
|
+
* held rpc.sock: a real God was observed supervising 50 daemons with NO
|
|
2541
|
+
* pm2.pid at all, and a pid-file-only probe stayed silent through exactly the
|
|
2542
|
+
* situation this warning exists for.
|
|
2536
2543
|
*
|
|
2537
2544
|
* • The shared default (~/.pm2) may be the user's own pm2 running unrelated
|
|
2538
2545
|
* apps. A live God there means nothing by itself — MEASURED on this box: the
|
|
@@ -2543,32 +2550,10 @@ async function ensureSystemDependencies() {
|
|
|
2543
2550
|
*/
|
|
2544
2551
|
function legacyBotmuxGodAlive() {
|
|
2545
2552
|
const dedicated = join(CONFIG_DIR, 'pm2');
|
|
2546
|
-
if (
|
|
2553
|
+
if (liveGodAt(dedicated) !== null)
|
|
2547
2554
|
return true;
|
|
2548
2555
|
const shared = join(homedir(), '.pm2');
|
|
2549
|
-
return
|
|
2550
|
-
}
|
|
2551
|
-
/** A God is alive at `home` if its pid file points at a live process, or (when
|
|
2552
|
-
* the file is missing/stale) its RPC socket is still there. */
|
|
2553
|
-
function pm2GodAlive(home) {
|
|
2554
|
-
const pidFile = join(home, 'pm2.pid');
|
|
2555
|
-
if (existsSync(pidFile)) {
|
|
2556
|
-
let pid = 0;
|
|
2557
|
-
try {
|
|
2558
|
-
pid = parseInt(readFileSync(pidFile, 'utf-8').trim(), 10);
|
|
2559
|
-
}
|
|
2560
|
-
catch {
|
|
2561
|
-
pid = 0;
|
|
2562
|
-
}
|
|
2563
|
-
if (Number.isSafeInteger(pid) && pid > 1) {
|
|
2564
|
-
try {
|
|
2565
|
-
process.kill(pid, 0);
|
|
2566
|
-
return true;
|
|
2567
|
-
}
|
|
2568
|
-
catch { /* stale — try the socket */ }
|
|
2569
|
-
}
|
|
2570
|
-
}
|
|
2571
|
-
return existsSync(join(home, 'rpc.sock'));
|
|
2556
|
+
return liveGodAt(shared) !== null && sharedHomeHasBotmuxRows(shared);
|
|
2572
2557
|
}
|
|
2573
2558
|
/** Does the SHARED pm2 home actually hold botmux apps? pm2 writes one pid file
|
|
2574
2559
|
* per app as `pids/<name>-<id>.pid`, so this answers it without running pm2.
|
|
@@ -2796,6 +2781,22 @@ async function callDashboardEndpoint(path) {
|
|
|
2796
2781
|
path,
|
|
2797
2782
|
});
|
|
2798
2783
|
}
|
|
2784
|
+
/**
|
|
2785
|
+
* Merlin Devbox 上为当前 dashboard 端口创建(或复用)私有短链。
|
|
2786
|
+
*
|
|
2787
|
+
* 端口取 dashboard 落盘的 `.dashboard-port`(端口探测可能落在 7891 之外),与
|
|
2788
|
+
* `devboxDashboardBaseUrl()` 读侧用的是同一份判据,避免写 9002、读 9001。
|
|
2789
|
+
* 非 Devbox / 已配置中心平台或自建反代 / `merlin-cli` 不可用时全部静默 no-op。
|
|
2790
|
+
*/
|
|
2791
|
+
async function ensureDevboxDashboardExportForCurrentPort() {
|
|
2792
|
+
const portFile = join(CONFIG_DIR, '.dashboard-port');
|
|
2793
|
+
const port = Number((existsSync(portFile) ? readFileSync(portFile, 'utf8').trim() : '')
|
|
2794
|
+
|| process.env.BOTMUX_DASHBOARD_PORT || '7891');
|
|
2795
|
+
await ensureDevboxDashboardExport({
|
|
2796
|
+
port,
|
|
2797
|
+
remoteBaseConfigured: Boolean((isRemoteAccessEnabled() && platformMachineBaseUrl()) || publicReverseProxyBaseUrl()),
|
|
2798
|
+
});
|
|
2799
|
+
}
|
|
2799
2800
|
/**
|
|
2800
2801
|
* Best-effort dashboard hint printed after start/restart. Reads the LIVE link
|
|
2801
2802
|
* via /__cli/current (non-rotating) so an already-shared URL is preserved.
|
|
@@ -2807,6 +2808,10 @@ async function printDashboardHintWithRetry() {
|
|
|
2807
2808
|
const stepMs = 500;
|
|
2808
2809
|
const started = Date.now();
|
|
2809
2810
|
let last = null;
|
|
2811
|
+
// 只在轮询之前做一次:导出结果与「dashboard 起没起来」无关,放在循环体里每轮都会
|
|
2812
|
+
// 重新 spawn 一次 merlin-cli,而失败路径最坏每轮付满 5s 超时——本函数自己的预算
|
|
2813
|
+
// 才 6s,实测会把 start/restart 的这段拖到近两倍。
|
|
2814
|
+
await ensureDevboxDashboardExportForCurrentPort();
|
|
2810
2815
|
while (Date.now() - started < maxWaitMs) {
|
|
2811
2816
|
last = await callDashboardEndpoint('/__cli/current');
|
|
2812
2817
|
if (last.ok) {
|
|
@@ -2842,6 +2847,12 @@ async function printDashboardHintWithRetry() {
|
|
|
2842
2847
|
* `dashboard` is the non-rotating get-or-create form; help and invalid
|
|
2843
2848
|
* subcommands never call either credential endpoint. */
|
|
2844
2849
|
async function cmdDashboard(args) {
|
|
2850
|
+
const rawAction = args[0]?.toLowerCase();
|
|
2851
|
+
const resolvesEndpoint = args.length <= 1
|
|
2852
|
+
&& !args.some(arg => ['--help', '-h', 'help'].includes(arg.toLowerCase()))
|
|
2853
|
+
&& (rawAction === undefined || rawAction === 'current' || rawAction === 'rotate');
|
|
2854
|
+
if (resolvesEndpoint)
|
|
2855
|
+
await ensureDevboxDashboardExportForCurrentPort();
|
|
2845
2856
|
const execution = await executeDashboardCommand(args, callDashboardEndpoint);
|
|
2846
2857
|
if (execution.kind === 'help') {
|
|
2847
2858
|
console.log(DASHBOARD_COMMAND_USAGE);
|
|
@@ -6270,6 +6281,25 @@ async function cmdHistory(rest) {
|
|
|
6270
6281
|
...(cardJson !== undefined ? { cardJson } : {}),
|
|
6271
6282
|
};
|
|
6272
6283
|
}));
|
|
6284
|
+
// Range guidance, emitted at the moment the model is actually reading
|
|
6285
|
+
// history. The decisive fact is `sessionScope` (this session's own scope),
|
|
6286
|
+
// NOT the chat's `chat_mode`: a thread opened inside a 普通群 keeps
|
|
6287
|
+
// chat_mode='group' while its session is thread-scope, so reasoning from the
|
|
6288
|
+
// group type would wrongly conclude "I may search the whole chat". Both
|
|
6289
|
+
// `--scope` gates above key on isChatScope for exactly that reason.
|
|
6290
|
+
//
|
|
6291
|
+
// Wording note: describe only what the model can OBSERVE. Daemon-side
|
|
6292
|
+
// invocations (`/t` and friends) are stripped before the prompt is built, so
|
|
6293
|
+
// the model never sees them — naming them here would be an instruction it
|
|
6294
|
+
// cannot act on. Describe the symptom instead: the topic starts mid-discussion
|
|
6295
|
+
// and its own history looks too short to explain the task.
|
|
6296
|
+
const rangeHint = isChatScope
|
|
6297
|
+
? '范围:本次返回当前群整群最近 N 条(不限于 session 创建之后)。需要更早的消息就把 `--limit` 调大。当前是 chat-scope 会话,没有话题边界,`--scope thread` / `--scope ambient` 在此不适用。'
|
|
6298
|
+
: effectiveScope === 'thread'
|
|
6299
|
+
? '范围:本次只返回当前话题内的消息。如果话题内的内容不足以说明任务背景(例如任务像是延续话题之外的讨论、出现没有出处的指代或结论),说明上下文在话题外的群聊里:用 `botmux history --scope ambient --limit 20` 读取本话题之外、话题根之前的群聊消息(自动排除本话题)。注意隐私边界:ambient 会读到话题外的群聊内容,仅在确实需要群聊背景时使用,并优先用较小的 limit。'
|
|
6300
|
+
: effectiveScope === 'ambient'
|
|
6301
|
+
? '范围:本次返回的是话题之外的群聊消息(话题根之前,已排除本话题)。要回到本话题内的消息用 `botmux history`(默认即本话题)。'
|
|
6302
|
+
: '范围:本次按 `--scope chat` 返回整群最近 N 条(含本话题内的消息)。只要本话题内的用 `botmux history`(默认即本话题)。';
|
|
6273
6303
|
console.log(JSON.stringify({
|
|
6274
6304
|
sessionId: sid,
|
|
6275
6305
|
chatId: s.chatId,
|
|
@@ -6285,6 +6315,7 @@ async function cmdHistory(rest) {
|
|
|
6285
6315
|
} : {}),
|
|
6286
6316
|
messages,
|
|
6287
6317
|
total: messages.length,
|
|
6318
|
+
rangeHint,
|
|
6288
6319
|
// Discoverability: agents reading history often need the actual image
|
|
6289
6320
|
// bytes (alert charts) or the raw card JSON — both live one command away.
|
|
6290
6321
|
...(messages.some(m => m.resources?.length || m.msgType === 'interactive') ? {
|