botmux 3.18.1-canary.2 → 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.
Files changed (42) hide show
  1. package/dist/.runtime-build-id +1 -1
  2. package/dist/cli/daemon-lifecycle-env.d.ts +1 -1
  3. package/dist/cli/daemon-lifecycle-env.d.ts.map +1 -1
  4. package/dist/cli/daemon-lifecycle-env.js +6 -0
  5. package/dist/cli/daemon-lifecycle-env.js.map +1 -1
  6. package/dist/cli.d.ts.map +1 -1
  7. package/dist/cli.js +49 -0
  8. package/dist/cli.js.map +1 -1
  9. package/dist/core/current-actor-attestation.js +2 -2
  10. package/dist/core/current-actor-attestation.js.map +1 -1
  11. package/dist/core/dashboard-url.d.ts.map +1 -1
  12. package/dist/core/dashboard-url.js +9 -1
  13. package/dist/core/dashboard-url.js.map +1 -1
  14. package/dist/core/legacy-pm2-reaper.d.ts +7 -0
  15. package/dist/core/legacy-pm2-reaper.d.ts.map +1 -1
  16. package/dist/core/legacy-pm2-reaper.js +153 -15
  17. package/dist/core/legacy-pm2-reaper.js.map +1 -1
  18. package/dist/core/maintenance.d.ts.map +1 -1
  19. package/dist/core/maintenance.js +2 -0
  20. package/dist/core/maintenance.js.map +1 -1
  21. package/dist/core/terminal-url.d.ts.map +1 -1
  22. package/dist/core/terminal-url.js +11 -0
  23. package/dist/core/terminal-url.js.map +1 -1
  24. package/dist/dashboard/control-csrf.d.ts.map +1 -1
  25. package/dist/dashboard/control-csrf.js +21 -0
  26. package/dist/dashboard/control-csrf.js.map +1 -1
  27. package/dist/i18n/en.js +3 -3
  28. package/dist/i18n/en.js.map +1 -1
  29. package/dist/i18n/zh.js +3 -3
  30. package/dist/i18n/zh.js.map +1 -1
  31. package/dist/im/lark/card-handler.d.ts.map +1 -1
  32. package/dist/im/lark/card-handler.js +20 -9
  33. package/dist/im/lark/card-handler.js.map +1 -1
  34. package/dist/platform/devbox-dashboard-export.d.ts +32 -0
  35. package/dist/platform/devbox-dashboard-export.d.ts.map +1 -0
  36. package/dist/platform/devbox-dashboard-export.js +320 -0
  37. package/dist/platform/devbox-dashboard-export.js.map +1 -0
  38. package/dist/utils/dashboard-env.d.ts +1 -1
  39. package/dist/utils/dashboard-env.d.ts.map +1 -1
  40. package/dist/worker.js +5 -0
  41. package/dist/worker.js.map +1 -1
  42. package/package.json +7 -7
@@ -1 +1 @@
1
- 0b8be9043c07b1df66f6cb5da350502c10659cba98c32c50f8e513cb67d24f4d
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,+RAuBlB,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"}
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;CAClC,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"}
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;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"}
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
@@ -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';
@@ -2778,6 +2781,22 @@ async function callDashboardEndpoint(path) {
2778
2781
  path,
2779
2782
  });
2780
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
+ }
2781
2800
  /**
2782
2801
  * Best-effort dashboard hint printed after start/restart. Reads the LIVE link
2783
2802
  * via /__cli/current (non-rotating) so an already-shared URL is preserved.
@@ -2789,6 +2808,10 @@ async function printDashboardHintWithRetry() {
2789
2808
  const stepMs = 500;
2790
2809
  const started = Date.now();
2791
2810
  let last = null;
2811
+ // 只在轮询之前做一次:导出结果与「dashboard 起没起来」无关,放在循环体里每轮都会
2812
+ // 重新 spawn 一次 merlin-cli,而失败路径最坏每轮付满 5s 超时——本函数自己的预算
2813
+ // 才 6s,实测会把 start/restart 的这段拖到近两倍。
2814
+ await ensureDevboxDashboardExportForCurrentPort();
2792
2815
  while (Date.now() - started < maxWaitMs) {
2793
2816
  last = await callDashboardEndpoint('/__cli/current');
2794
2817
  if (last.ok) {
@@ -2824,6 +2847,12 @@ async function printDashboardHintWithRetry() {
2824
2847
  * `dashboard` is the non-rotating get-or-create form; help and invalid
2825
2848
  * subcommands never call either credential endpoint. */
2826
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();
2827
2856
  const execution = await executeDashboardCommand(args, callDashboardEndpoint);
2828
2857
  if (execution.kind === 'help') {
2829
2858
  console.log(DASHBOARD_COMMAND_USAGE);
@@ -6252,6 +6281,25 @@ async function cmdHistory(rest) {
6252
6281
  ...(cardJson !== undefined ? { cardJson } : {}),
6253
6282
  };
6254
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`(默认即本话题)。';
6255
6303
  console.log(JSON.stringify({
6256
6304
  sessionId: sid,
6257
6305
  chatId: s.chatId,
@@ -6267,6 +6315,7 @@ async function cmdHistory(rest) {
6267
6315
  } : {}),
6268
6316
  messages,
6269
6317
  total: messages.length,
6318
+ rangeHint,
6270
6319
  // Discoverability: agents reading history often need the actual image
6271
6320
  // bytes (alert charts) or the raw card JSON — both live one command away.
6272
6321
  ...(messages.some(m => m.resources?.length || m.msgType === 'interactive') ? {