botmux 3.18.6 → 3.18.7

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 (239) hide show
  1. package/dist/.runtime-build-id +1 -1
  2. package/dist/adapters/backend/riff-backend.d.ts +158 -0
  3. package/dist/adapters/backend/riff-backend.d.ts.map +1 -1
  4. package/dist/adapters/backend/riff-backend.js +330 -7
  5. package/dist/adapters/backend/riff-backend.js.map +1 -1
  6. package/dist/adapters/backend/sandbox.d.ts +42 -0
  7. package/dist/adapters/backend/sandbox.d.ts.map +1 -1
  8. package/dist/adapters/backend/sandbox.js +95 -5
  9. package/dist/adapters/backend/sandbox.js.map +1 -1
  10. package/dist/adapters/cli/codex-app.d.ts.map +1 -1
  11. package/dist/adapters/cli/codex-app.js +2 -1
  12. package/dist/adapters/cli/codex-app.js.map +1 -1
  13. package/dist/adapters/cli/dsh.d.ts.map +1 -1
  14. package/dist/adapters/cli/dsh.js +2 -1
  15. package/dist/adapters/cli/dsh.js.map +1 -1
  16. package/dist/adapters/cli/mir.d.ts.map +1 -1
  17. package/dist/adapters/cli/mir.js +2 -1
  18. package/dist/adapters/cli/mir.js.map +1 -1
  19. package/dist/adapters/cli/mira.d.ts.map +1 -1
  20. package/dist/adapters/cli/mira.js +2 -1
  21. package/dist/adapters/cli/mira.js.map +1 -1
  22. package/dist/adapters/hook-command.d.ts +3 -5
  23. package/dist/adapters/hook-command.d.ts.map +1 -1
  24. package/dist/adapters/hook-command.js +59 -13
  25. package/dist/adapters/hook-command.js.map +1 -1
  26. package/dist/autostart.d.ts +76 -0
  27. package/dist/autostart.d.ts.map +1 -1
  28. package/dist/autostart.js +105 -28
  29. package/dist/autostart.js.map +1 -1
  30. package/dist/bot-registry.d.ts +12 -0
  31. package/dist/bot-registry.d.ts.map +1 -1
  32. package/dist/bot-registry.js +43 -3
  33. package/dist/bot-registry.js.map +1 -1
  34. package/dist/cli/dashboard-command.d.ts +142 -0
  35. package/dist/cli/dashboard-command.d.ts.map +1 -1
  36. package/dist/cli/dashboard-command.js +160 -0
  37. package/dist/cli/dashboard-command.js.map +1 -1
  38. package/dist/cli/dashboard-endpoint.d.ts +66 -0
  39. package/dist/cli/dashboard-endpoint.d.ts.map +1 -1
  40. package/dist/cli/dashboard-endpoint.js +144 -30
  41. package/dist/cli/dashboard-endpoint.js.map +1 -1
  42. package/dist/cli/send-dispatch.d.ts +2 -0
  43. package/dist/cli/send-dispatch.d.ts.map +1 -1
  44. package/dist/cli/send-dispatch.js +8 -2
  45. package/dist/cli/send-dispatch.js.map +1 -1
  46. package/dist/cli.d.ts.map +1 -1
  47. package/dist/cli.js +270 -38
  48. package/dist/cli.js.map +1 -1
  49. package/dist/core/binary-self-update.d.ts +7 -0
  50. package/dist/core/binary-self-update.d.ts.map +1 -1
  51. package/dist/core/binary-self-update.js +17 -0
  52. package/dist/core/binary-self-update.js.map +1 -1
  53. package/dist/core/command-handler.d.ts.map +1 -1
  54. package/dist/core/command-handler.js +52 -1
  55. package/dist/core/command-handler.js.map +1 -1
  56. package/dist/core/cost-calculator.d.ts +9 -1
  57. package/dist/core/cost-calculator.d.ts.map +1 -1
  58. package/dist/core/cost-calculator.js +5 -0
  59. package/dist/core/cost-calculator.js.map +1 -1
  60. package/dist/core/passthrough-commands.d.ts.map +1 -1
  61. package/dist/core/passthrough-commands.js +1 -1
  62. package/dist/core/passthrough-commands.js.map +1 -1
  63. package/dist/core/self-spawn.d.ts +46 -1
  64. package/dist/core/self-spawn.d.ts.map +1 -1
  65. package/dist/core/self-spawn.js +57 -0
  66. package/dist/core/self-spawn.js.map +1 -1
  67. package/dist/core/worker-pool.d.ts.map +1 -1
  68. package/dist/core/worker-pool.js +81 -5
  69. package/dist/core/worker-pool.js.map +1 -1
  70. package/dist/daemon.d.ts.map +1 -1
  71. package/dist/daemon.js +93 -0
  72. package/dist/daemon.js.map +1 -1
  73. package/dist/dashboard/autostart-api.d.ts.map +1 -1
  74. package/dist/dashboard/autostart-api.js +16 -3
  75. package/dist/dashboard/autostart-api.js.map +1 -1
  76. package/dist/dashboard/bot-onboarding.d.ts +2 -1
  77. package/dist/dashboard/bot-onboarding.d.ts.map +1 -1
  78. package/dist/dashboard/bot-onboarding.js +22 -6
  79. package/dist/dashboard/bot-onboarding.js.map +1 -1
  80. package/dist/dashboard/bot-payload.d.ts +1 -0
  81. package/dist/dashboard/bot-payload.d.ts.map +1 -1
  82. package/dist/dashboard/bot-payload.js +3 -0
  83. package/dist/dashboard/bot-payload.js.map +1 -1
  84. package/dist/dashboard/connector-api.d.ts.map +1 -1
  85. package/dist/dashboard/connector-api.js +28 -0
  86. package/dist/dashboard/connector-api.js.map +1 -1
  87. package/dist/dashboard/trigger-api.d.ts.map +1 -1
  88. package/dist/dashboard/trigger-api.js +33 -21
  89. package/dist/dashboard/trigger-api.js.map +1 -1
  90. package/dist/dashboard/web/bot-defaults-page.d.ts.map +1 -1
  91. package/dist/dashboard/web/bot-defaults-page.js +12 -2
  92. package/dist/dashboard/web/bot-defaults-page.js.map +1 -1
  93. package/dist/dashboard/web/bot-defaults.d.ts +2 -0
  94. package/dist/dashboard/web/bot-defaults.d.ts.map +1 -1
  95. package/dist/dashboard/web/bot-defaults.js.map +1 -1
  96. package/dist/dashboard/web/bot-onboarding.d.ts +40 -1
  97. package/dist/dashboard/web/bot-onboarding.d.ts.map +1 -1
  98. package/dist/dashboard/web/bot-onboarding.js +52 -2
  99. package/dist/dashboard/web/bot-onboarding.js.map +1 -1
  100. package/dist/dashboard/web/i18n.d.ts.map +1 -1
  101. package/dist/dashboard/web/i18n.js +2 -0
  102. package/dist/dashboard/web/i18n.js.map +1 -1
  103. package/dist/dashboard/webhook-routes.d.ts.map +1 -1
  104. package/dist/dashboard/webhook-routes.js +272 -30
  105. package/dist/dashboard/webhook-routes.js.map +1 -1
  106. package/dist/dashboard-web/app.js +1 -1
  107. package/dist/dashboard-web/chunks/{agent-workbench-dock-page-XHJUYFGN.js → agent-workbench-dock-page-6LC422N6.js} +1 -1
  108. package/dist/dashboard-web/chunks/{agent-workbench-page-FLKTLIRM.js → agent-workbench-page-RSAWY7O2.js} +1 -1
  109. package/dist/dashboard-web/chunks/{bot-defaults-page-XMGLZZ2E.js → bot-defaults-page-67RAWCSQ.js} +1 -1
  110. package/dist/dashboard-web/chunks/{chunk-TLG45URB.js → chunk-IA5KMD5O.js} +1 -1
  111. package/dist/dashboard-web/chunks/{chunk-BU3Q6XC6.js → chunk-K232GT3M.js} +2 -2
  112. package/dist/dashboard-web/chunks/chunk-MMLTCXHP.js +10 -0
  113. package/dist/dashboard-web/chunks/{chunk-ECFC7UG2.js → chunk-R3LJUCEO.js} +1 -1
  114. package/dist/dashboard-web/chunks/{chunk-Z67OSM5P.js → chunk-YJA3KY3J.js} +1 -1
  115. package/dist/dashboard-web/chunks/{connectors-page-WDM4CEAU.js → connectors-page-DJCTHSFB.js} +1 -1
  116. package/dist/dashboard-web/chunks/{feedback-page-GMJ4FLJ4.js → feedback-page-O7SZRKNM.js} +1 -1
  117. package/dist/dashboard-web/chunks/{groups-page-L4ZJNWVR.js → groups-page-7PONUYHE.js} +1 -1
  118. package/dist/dashboard-web/chunks/{insights-page-7LUJU2CX.js → insights-page-J6DAAJ6D.js} +1 -1
  119. package/dist/dashboard-web/chunks/{monitor-room-7LZUJQPF.js → monitor-room-F3QNEW7N.js} +1 -1
  120. package/dist/dashboard-web/chunks/{monitoring-page-AUSXMPYO.js → monitoring-page-JHDD2VS2.js} +1 -1
  121. package/dist/dashboard-web/chunks/{office-page-6ZU6MAZN.js → office-page-MMTN4IKD.js} +1 -1
  122. package/dist/dashboard-web/chunks/{overview-page-QBC5CIYH.js → overview-page-IQ2UJAJP.js} +1 -1
  123. package/dist/dashboard-web/chunks/{roles-page-QO3YCA7D.js → roles-page-FNI4MGX6.js} +1 -1
  124. package/dist/dashboard-web/chunks/{schedules-page-YNGSKDQW.js → schedules-page-6PUU63KS.js} +1 -1
  125. package/dist/dashboard-web/chunks/{sessions-page-BWR4UB6X.js → sessions-page-O4N72EXT.js} +4 -4
  126. package/dist/dashboard-web/chunks/{settings-page-2IRIS3FP.js → settings-page-G7B3STUF.js} +1 -1
  127. package/dist/dashboard-web/chunks/{skills-page-5RZPM6HJ.js → skills-page-CEWKQOIG.js} +1 -1
  128. package/dist/dashboard-web/chunks/{team-federation-page-KERG6LKC.js → team-federation-page-NUP4VK4H.js} +1 -1
  129. package/dist/dashboard-web/chunks/{v3-page-766CBD7H.js → v3-page-M4XF6D5Z.js} +1 -1
  130. package/dist/dashboard-web/chunks/{whiteboards-page-2M6XZD5C.js → whiteboards-page-L755NZX6.js} +1 -1
  131. package/dist/dashboard-web/style.css +13 -0
  132. package/dist/dashboard.js +3 -0
  133. package/dist/dashboard.js.map +1 -1
  134. package/dist/global-config.d.ts +3 -0
  135. package/dist/global-config.d.ts.map +1 -1
  136. package/dist/global-config.js +10 -3
  137. package/dist/global-config.js.map +1 -1
  138. package/dist/i18n/en.d.ts.map +1 -1
  139. package/dist/i18n/en.js +19 -1
  140. package/dist/i18n/en.js.map +1 -1
  141. package/dist/i18n/zh.d.ts.map +1 -1
  142. package/dist/i18n/zh.js +19 -1
  143. package/dist/i18n/zh.js.map +1 -1
  144. package/dist/im/lark/api-gate.d.ts +53 -0
  145. package/dist/im/lark/api-gate.d.ts.map +1 -0
  146. package/dist/im/lark/api-gate.js +322 -0
  147. package/dist/im/lark/api-gate.js.map +1 -0
  148. package/dist/im/lark/audio-transcribe.d.ts +23 -0
  149. package/dist/im/lark/audio-transcribe.d.ts.map +1 -0
  150. package/dist/im/lark/audio-transcribe.js +126 -0
  151. package/dist/im/lark/audio-transcribe.js.map +1 -0
  152. package/dist/im/lark/card-builder.d.ts +6 -0
  153. package/dist/im/lark/card-builder.d.ts.map +1 -1
  154. package/dist/im/lark/card-builder.js +53 -1
  155. package/dist/im/lark/card-builder.js.map +1 -1
  156. package/dist/im/lark/card-handler.d.ts +10 -0
  157. package/dist/im/lark/card-handler.d.ts.map +1 -1
  158. package/dist/im/lark/card-handler.js +68 -1
  159. package/dist/im/lark/card-handler.js.map +1 -1
  160. package/dist/im/lark/client.d.ts.map +1 -1
  161. package/dist/im/lark/client.js +247 -224
  162. package/dist/im/lark/client.js.map +1 -1
  163. package/dist/im/lark/event-dispatcher.d.ts.map +1 -1
  164. package/dist/im/lark/event-dispatcher.js +34 -3
  165. package/dist/im/lark/event-dispatcher.js.map +1 -1
  166. package/dist/im/lark/message-parser.d.ts +16 -0
  167. package/dist/im/lark/message-parser.d.ts.map +1 -1
  168. package/dist/im/lark/message-parser.js +31 -0
  169. package/dist/im/lark/message-parser.js.map +1 -1
  170. package/dist/services/budget-tracker.d.ts +61 -0
  171. package/dist/services/budget-tracker.d.ts.map +1 -0
  172. package/dist/services/budget-tracker.js +306 -0
  173. package/dist/services/budget-tracker.js.map +1 -0
  174. package/dist/services/connector-store.d.ts +16 -0
  175. package/dist/services/connector-store.d.ts.map +1 -1
  176. package/dist/services/connector-store.js.map +1 -1
  177. package/dist/services/failed-turn-retry.d.ts +43 -0
  178. package/dist/services/failed-turn-retry.d.ts.map +1 -0
  179. package/dist/services/failed-turn-retry.js +50 -0
  180. package/dist/services/failed-turn-retry.js.map +1 -0
  181. package/dist/services/model-pricing.d.ts +80 -0
  182. package/dist/services/model-pricing.d.ts.map +1 -0
  183. package/dist/services/model-pricing.js +182 -0
  184. package/dist/services/model-pricing.js.map +1 -0
  185. package/dist/services/session-store.d.ts.map +1 -1
  186. package/dist/services/session-store.js +13 -3
  187. package/dist/services/session-store.js.map +1 -1
  188. package/dist/services/trigger-types.d.ts +10 -0
  189. package/dist/services/trigger-types.d.ts.map +1 -1
  190. package/dist/services/trigger-types.js.map +1 -1
  191. package/dist/services/usage-ledger.d.ts +10 -0
  192. package/dist/services/usage-ledger.d.ts.map +1 -1
  193. package/dist/services/usage-ledger.js +36 -0
  194. package/dist/services/usage-ledger.js.map +1 -1
  195. package/dist/services/voice/asr.d.ts +17 -0
  196. package/dist/services/voice/asr.d.ts.map +1 -0
  197. package/dist/services/voice/asr.js +64 -0
  198. package/dist/services/voice/asr.js.map +1 -0
  199. package/dist/services/voice/index.d.ts +17 -2
  200. package/dist/services/voice/index.d.ts.map +1 -1
  201. package/dist/services/voice/index.js +43 -0
  202. package/dist/services/voice/index.js.map +1 -1
  203. package/dist/services/voice/types.d.ts +15 -0
  204. package/dist/services/voice/types.d.ts.map +1 -1
  205. package/dist/services/webhook-idempotency.d.ts +134 -0
  206. package/dist/services/webhook-idempotency.d.ts.map +1 -0
  207. package/dist/services/webhook-idempotency.js +265 -0
  208. package/dist/services/webhook-idempotency.js.map +1 -0
  209. package/dist/setup/app-name.d.ts +1 -0
  210. package/dist/setup/app-name.d.ts.map +1 -1
  211. package/dist/setup/app-name.js +7 -0
  212. package/dist/setup/app-name.js.map +1 -1
  213. package/dist/setup/bot-config-editor.d.ts +28 -0
  214. package/dist/setup/bot-config-editor.d.ts.map +1 -1
  215. package/dist/setup/bot-config-editor.js +73 -0
  216. package/dist/setup/bot-config-editor.js.map +1 -1
  217. package/dist/setup/open-platform-automation.d.ts +26 -0
  218. package/dist/setup/open-platform-automation.d.ts.map +1 -1
  219. package/dist/setup/open-platform-automation.js +90 -1
  220. package/dist/setup/open-platform-automation.js.map +1 -1
  221. package/dist/setup/open-platform-outcome.d.ts.map +1 -1
  222. package/dist/setup/open-platform-outcome.js +8 -2
  223. package/dist/setup/open-platform-outcome.js.map +1 -1
  224. package/dist/types.d.ts +20 -1
  225. package/dist/types.d.ts.map +1 -1
  226. package/dist/utils/usage-limit-tracker.d.ts +29 -9
  227. package/dist/utils/usage-limit-tracker.d.ts.map +1 -1
  228. package/dist/utils/usage-limit-tracker.js +122 -14
  229. package/dist/utils/usage-limit-tracker.js.map +1 -1
  230. package/dist/worker.js +27 -6
  231. package/dist/worker.js.map +1 -1
  232. package/dist/workflows/definition.d.ts +56 -56
  233. package/dist/workflows/events/payloads.d.ts +2 -2
  234. package/dist/workflows/events/schema.d.ts +430 -430
  235. package/dist/workflows/migration/v2-run-archive-schema.d.ts +2 -2
  236. package/dist/workflows/v3/run-envelope.d.ts +56 -56
  237. package/package.json +9 -8
  238. package/scripts/postinstall-bin.mjs +25 -0
  239. package/dist/dashboard-web/chunks/chunk-NJCJR3U2.js +0 -10
@@ -33,6 +33,145 @@ export function formatDashboardSuccessLines(result) {
33
33
  lines.push(`本地直连(平台异常时可用): ${result.localUrl}`);
34
34
  return lines;
35
35
  }
36
+ /**
37
+ * How long `start`/`restart` should keep waiting for the dashboard to answer, and
38
+ * what to tell an operator who asks for the link while it is still coming up.
39
+ *
40
+ * SIZED FROM A REAL FLEET, not from how long a boot "should" take. The budget was
41
+ * 6s; MEASURED on a 13-member fleet the dashboard needed ~45s from supervisor
42
+ * start to answering (supervisor up at 14:23:04, `.dashboard-port` written at
43
+ * 14:23:49). So every `restart` there ended in the "still booting" fallback, and
44
+ * the operator's natural next step — `botmux dashboard` — printed
45
+ * "not reachable ... `botmux restart` will start it": advice that would restart a
46
+ * daemon which was in fact coming up fine, throwing away the boot about to
47
+ * succeed.
48
+ */
49
+ export const DASHBOARD_READY_WAIT_MS = 90_000;
50
+ /**
51
+ * How long to keep polling before the liveness gate may end the wait.
52
+ *
53
+ * A just-started supervisor has not written its dashboard row yet, so the very
54
+ * first observation can legitimately be "cannot tell" — which must not be read as
55
+ * "nothing is coming up". This is the old whole-budget value, so the previous
56
+ * behaviour is preserved for that initial stretch and the gate only starts cutting
57
+ * waits short once the state file has had time to appear.
58
+ */
59
+ export const DASHBOARD_LIVENESS_GRACE_MS = 6_000;
60
+ /**
61
+ * Failure reasons that prove we REACHED the dashboard, so waiting cannot change
62
+ * them. This is the "did we get an answer from the dashboard itself" question —
63
+ * NOT "is this backed by a file", which is the distinction an earlier version got
64
+ * wrong in both directions:
65
+ *
66
+ * • `no-secret` looks file-backed and permanent, but `.dashboard-secret` is
67
+ * created BY the dashboard during its own boot (`loadOrCreateSecret()`, called
68
+ * at module scope in dashboard.ts). On a fresh install the supervisor has a live
69
+ * dashboard pid well before that line runs, so the first poll legitimately sees
70
+ * `no-secret` and it resolves on its own moments later.
71
+ * • `wrong-service` is not permanent either: another service can hold the recorded
72
+ * port while the dashboard has not bound its own yet, which makes discovery fail
73
+ * now and succeed once it binds.
74
+ *
75
+ * Treating either as terminal ended the poll early and then told the operator to
76
+ * restart a dashboard that was coming up fine — the same misdiagnosis this module
77
+ * fixes for `unreachable`.
78
+ *
79
+ * Terminal is therefore "we got an answer FROM the dashboard": `no-active-token`
80
+ * (it is up, it just has no token yet) and `http-error`. The latter is exactly how
81
+ * `dashboard-endpoint.ts:reachedDashboard()` classifies it — a 500 or a malformed
82
+ * body means the dashboard replied, so waiting changes nothing, and leaving it out
83
+ * would spend the full 90s budget on a live dashboard that answers 500 forever.
84
+ */
85
+ export function dashboardFailureIsTerminal(failure) {
86
+ return failure.reason === 'no-active-token' || failure.reason === 'http-error';
87
+ }
88
+ /**
89
+ * Map an observed fleet state to "is a dashboard coming up?" — the OBSERVATION
90
+ * half of the readiness decision, kept pure so it is testable.
91
+ *
92
+ * This used to live inline in `cli.ts` where nothing could reach it, and the
93
+ * `launching` branch in particular is the whole point of the fix: the supervisor
94
+ * records `status='launching', pid=0` while a crashed member is in restart
95
+ * backoff, so a pid-based check called that "not live", ended the poll, and then
96
+ * advised restarting a dashboard the supervisor was already bringing back.
97
+ *
98
+ * Tri-state on purpose — `null` is "cannot tell yet", NOT "no":
99
+ * • no state file, or the dashboard row not written yet → null
100
+ * • no live supervisor → false (nobody left to start anything)
101
+ * • stopped / errored → false (the supervisor has given up)
102
+ * • launching → true (pid is 0 BY DESIGN here; never pid-check this state)
103
+ * • online → only true if the pid is actually alive
104
+ *
105
+ * @param state parsed fleet state, or null when absent/unreadable
106
+ * @param pidAlive liveness probe, injected so tests need no real processes
107
+ */
108
+ export function dashboardComingUpFromState(state, dashboardProcessName, pidAlive) {
109
+ if (!state)
110
+ return null;
111
+ const sup = state.supervisorPid;
112
+ const supervisorAlive = Number.isSafeInteger(sup) && sup > 1 && pidAlive(sup);
113
+ if (!supervisorAlive)
114
+ return false;
115
+ const proc = state.procs?.find((p) => p.name === dashboardProcessName);
116
+ if (!proc)
117
+ return null;
118
+ if (proc.status === 'stopped' || proc.status === 'errored')
119
+ return false;
120
+ if (proc.status === 'launching')
121
+ return true;
122
+ if (!Number.isSafeInteger(proc.pid) || proc.pid <= 1)
123
+ return false;
124
+ return pidAlive(proc.pid);
125
+ }
126
+ /**
127
+ * Should the readiness poll take another turn?
128
+ *
129
+ * Three independent bounds, and all of them matter:
130
+ * • the clock — liveness alone would spin forever on a member that is up but
131
+ * never binds its port;
132
+ * • whether the failure is terminal — no point polling an answer that will not
133
+ * change;
134
+ * • whether a dashboard is coming up — the clock alone would spend the (now much
135
+ * larger) budget in full on a fleet that has no dashboard member, or whose
136
+ * dashboard the supervisor has given up on.
137
+ *
138
+ * `comingUp` is deliberately TRI-STATE. `null` means "cannot tell yet" (no state
139
+ * file, or the supervisor has not written the dashboard row), which is normal in
140
+ * the first moments and must not end the wait; before
141
+ * DASHBOARD_LIVENESS_GRACE_MS it keeps waiting, after it stops rather than hold
142
+ * the full budget on a fleet whose state never appears.
143
+ */
144
+ export function shouldKeepWaitingForDashboard(input) {
145
+ if (input.elapsedMs >= (input.budgetMs ?? DASHBOARD_READY_WAIT_MS))
146
+ return false;
147
+ if (dashboardFailureIsTerminal(input.failure))
148
+ return false;
149
+ if (input.comingUp === null) {
150
+ return input.elapsedMs < (input.graceMs ?? DASHBOARD_LIVENESS_GRACE_MS);
151
+ }
152
+ return input.comingUp;
153
+ }
154
+ /**
155
+ * The message for a failure that may just mean "not up yet" — the one an operator
156
+ * sees from `botmux dashboard`.
157
+ *
158
+ * "Run restart" is right ONLY when nothing is coming up. With a live dashboard
159
+ * member, nothing is broken and a restart would throw away a boot that is about to
160
+ * succeed, so say "wait" instead. Covers every non-terminal shape, because they
161
+ * are all reachable while the dashboard is still booting: the port not listening
162
+ * yet (`unreachable`), the secret not written yet (`no-secret` — the dashboard
163
+ * creates it itself), and the port not bound yet so discovery finds someone else
164
+ * on the recorded one (`wrong-service`). See DASHBOARD_READY_WAIT_MS.
165
+ */
166
+ export function formatDashboardUnreachable(port, comingUp) {
167
+ // `null` ("cannot tell yet") is treated as coming up: the honest advice when we
168
+ // do not know is "wait and retry", never "restart".
169
+ if (comingUp !== false) {
170
+ return `dashboard 正在启动中,还没开始在 127.0.0.1:${port} 上应答(大 fleet 可能要几十秒)。`
171
+ + '稍等几秒后重新运行 `botmux dashboard` 即可,不需要 restart。';
172
+ }
173
+ return `dashboard process not reachable on 127.0.0.1:${port} — \`botmux restart\` will start it`;
174
+ }
36
175
  export function formatDashboardFallbackFailure(action, failure) {
37
176
  const operation = action === 'current' ? 'Dashboard lookup' : 'Rotation';
38
177
  return `${operation} failed: ${failure.detail ?? failure.reason}`;
@@ -80,4 +219,25 @@ export async function executeDashboardCommand(args, callEndpoint) {
80
219
  }
81
220
  return { kind: 'endpoint', action, result: ensured };
82
221
  }
222
+ /**
223
+ * `botmux dashboard`'s execution path, as ONE importable unit.
224
+ *
225
+ * Why this exists rather than inline wiring in `cli.ts`: the opt-in below is the
226
+ * whole fix for a dead `.dashboard-port`, and `cli.ts` exports nothing testable,
227
+ * so the only way to check it was a source-text assertion. Two such assertions
228
+ * were written and both were wrong — the first false-RED on a legitimate
229
+ * extract-to-local refactor, the second stayed GREEN when the flag-carrying call
230
+ * was fully disconnected from the caller actually passed down (flag present,
231
+ * command executed, wiring severed). A regex over nested callbacks cannot express
232
+ * "this options object reaches that caller"; a function can.
233
+ *
234
+ * `rescanWhenUnreachable: true` is correct HERE and only here: this is a one-shot
235
+ * human command, so at worst it scans the probe range once per invocation. The
236
+ * 500ms readiness poll must keep the default (false) or it would scan every tick.
237
+ *
238
+ * @param callEndpoint the raw endpoint caller; this wrapper is what adds the opt-in
239
+ */
240
+ export async function executeDashboardCliCommand(args, callEndpoint) {
241
+ return executeDashboardCommand(args, (path) => callEndpoint(path, { rescanWhenUnreachable: true }));
242
+ }
83
243
  //# sourceMappingURL=dashboard-command.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"dashboard-command.js","sourceRoot":"","sources":["../../src/cli/dashboard-command.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"dashboard-command.js","sourceRoot":"","sources":["../../src/cli/dashboard-command.ts"],"names":[],"mappings":"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"}
@@ -56,7 +56,45 @@ export declare function requestDashboardAt(opts: {
56
56
  path: DashboardEndpoint;
57
57
  secret: string;
58
58
  fetchImpl?: FetchImpl;
59
+ /**
60
+ * Abort the request after this long. REQUIRED for discovery: a local service
61
+ * that accepts the TCP connection but never sends HTTP headers would otherwise
62
+ * hang the whole serial probe loop forever (`loopbackFetch` sets no request
63
+ * timeout of its own), so a single stalled port could permanently wedge
64
+ * `botmux dashboard` before it ever reaches the real dashboard.
65
+ */
66
+ timeoutMs?: number;
59
67
  }): Promise<DashboardResult>;
68
+ /**
69
+ * Should a failure on the recorded port trigger a probe-range rescan?
70
+ *
71
+ * `wrong-service` / `auth-failed` mean SOMETHING answered but is not our
72
+ * dashboard, so the recorded port is provably wrong and scanning is safe.
73
+ *
74
+ * `unreachable` is ambiguous — it is BOTH "dashboard still booting" (retry the
75
+ * same port; scanning would be wasted work every tick) AND "the recorded port is
76
+ * a dead value nobody listens on" (retrying can never succeed, so without a scan
77
+ * the port file stays wrong forever). MEASURED on a box where `.dashboard-port`
78
+ * held 7893 while the live dashboard was on 7891 with 0 processes on 7893: every
79
+ * `botmux dashboard` failed, and the existing self-heal never ran because it is
80
+ * gated on someone answering.
81
+ *
82
+ * `allowUnreachableRescan` is how the caller separates the two: a one-shot human
83
+ * command passes true (at worst one scan per invocation); the 500ms readiness poll
84
+ * leaves it false. It is deliberately NOT derived from "is the dashboard coming
85
+ * up?" — that answers `true` for `online` + live pid too, which is exactly the
86
+ * measured failure, so such a gate would never fire on the real bug.
87
+ */
88
+ /**
89
+ * Per-probe cap. Loopback only, so a healthy dashboard answers in milliseconds;
90
+ * this exists purely to survive a port that accepts TCP and never replies.
91
+ */
92
+ export declare const DISCOVERY_PROBE_TIMEOUT_MS = 2000;
93
+ /**
94
+ * Cap for the WHOLE serial scan. Without it, `probeSpan × probeTimeout`
95
+ * (21 × 2s) would be the worst case on a host full of stalled loopback services.
96
+ */
97
+ export declare const DISCOVERY_TOTAL_BUDGET_MS = 8000;
60
98
  /**
61
99
  * Resolve the dashboard URL for `path`, trying the recorded port first and
62
100
  * self-healing the port file when it points at the wrong service or a loopback
@@ -71,6 +109,34 @@ export declare function callDashboard(opts: {
71
109
  persistPort?: boolean;
72
110
  path: DashboardEndpoint;
73
111
  fetchImpl?: FetchImpl;
112
+ /**
113
+ * Allow a rescan when the recorded port is simply not listening.
114
+ *
115
+ * Pass true for a ONE-SHOT human command (`botmux dashboard`), which is what
116
+ * `executeDashboardCliCommand` does. Leave it false for the 500ms readiness
117
+ * poll, where `unreachable` is the normal booting state and scanning the range
118
+ * every tick would be pure waste.
119
+ *
120
+ * NOT gated on "the dashboard is not coming up": that observation is `true` for
121
+ * both `launching` AND `online` + live pid, and the measured failure was the
122
+ * latter (dashboard healthy on another port), so such a gate would never fire
123
+ * on the bug this exists for.
124
+ */
125
+ rescanWhenUnreachable?: boolean;
126
+ /** Override the per-probe timeout (default DISCOVERY_PROBE_TIMEOUT_MS). */
127
+ probeTimeoutMs?: number;
128
+ /**
129
+ * Bound the FIRST (recorded-port) request even without opting into a rescan.
130
+ *
131
+ * The readiness poll needs this: its 90s budget is only consulted AFTER
132
+ * `await callDashboard(...)` returns, so a recorded port that accepts the
133
+ * connection and never answers makes the first await hang forever — the outer
134
+ * budget and the retry loop are both unreachable. Bounding the request is the
135
+ * only thing that can interrupt it.
136
+ */
137
+ requestTimeoutMs?: number;
138
+ /** Override the whole-scan budget (default DISCOVERY_TOTAL_BUDGET_MS). */
139
+ discoveryBudgetMs?: number;
74
140
  }): Promise<DashboardResult>;
75
141
  export {};
76
142
  //# sourceMappingURL=dashboard-endpoint.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"dashboard-endpoint.d.ts","sourceRoot":"","sources":["../../src/cli/dashboard-endpoint.ts"],"names":[],"mappings":"AAMA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,MAAM,MAAM,iBAAiB,GAAG,eAAe,GAAG,eAAe,GAAG,gBAAgB,GAAG,uBAAuB,CAAC;AAE/G,MAAM,MAAM,mBAAmB,GAC3B,WAAW,GACX,aAAa,GACb,aAAa,GACb,YAAY,GACZ,iBAAiB,GACjB,eAAe,CAAC;AAEpB,MAAM,MAAM,eAAe,GACvB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAC5C;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,mBAAmB,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEhE,KAAK,SAAS,GAAG,OAAO,KAAK,CAAC;AAE9B;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,GAAG,eAAe,CAY/F;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,eAAe,CAiBtE;AAED,gEAAgE;AAChE,wBAAsB,kBAAkB,CAAC,IAAI,EAAE;IAC7C,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,iBAAiB,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB,GAAG,OAAO,CAAC,eAAe,CAAC,CAoC3B;AAWD;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,IAAI,EAAE;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,IAAI,EAAE,iBAAiB,CAAC;IACxB,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB,GAAG,OAAO,CAAC,eAAe,CAAC,CAmD3B"}
1
+ {"version":3,"file":"dashboard-endpoint.d.ts","sourceRoot":"","sources":["../../src/cli/dashboard-endpoint.ts"],"names":[],"mappings":"AAMA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,MAAM,MAAM,iBAAiB,GAAG,eAAe,GAAG,eAAe,GAAG,gBAAgB,GAAG,uBAAuB,CAAC;AAE/G,MAAM,MAAM,mBAAmB,GAC3B,WAAW,GACX,aAAa,GACb,aAAa,GACb,YAAY,GACZ,iBAAiB,GACjB,eAAe,CAAC;AAEpB,MAAM,MAAM,eAAe,GACvB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAC5C;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,mBAAmB,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEhE,KAAK,SAAS,GAAG,OAAO,KAAK,CAAC;AAE9B;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,GAAG,eAAe,CAY/F;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,eAAe,CAiBtE;AAED,gEAAgE;AAChE,wBAAsB,kBAAkB,CAAC,IAAI,EAAE;IAC7C,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,iBAAiB,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,OAAO,CAAC,eAAe,CAAC,CA+D3B;AAOD;;;;;;;;;;;;;;;;;;;GAmBG;AACH;;;GAGG;AACH,eAAO,MAAM,0BAA0B,OAAQ,CAAC;AAChD;;;GAGG;AACH,eAAO,MAAM,yBAAyB,OAAQ,CAAC;AAQ/C;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,IAAI,EAAE;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,IAAI,EAAE,iBAAiB,CAAC;IACxB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB;;;;;;;;;;;;OAYG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,2EAA2E;IAC3E,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;;;;OAQG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,0EAA0E;IAC1E,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B,GAAG,OAAO,CAAC,eAAe,CAAC,CAiG3B"}
@@ -63,43 +63,111 @@ export async function requestDashboardAt(opts) {
63
63
  // the verifier reconstructs the bind from the port IT bound, so any forward
64
64
  // mismatches the signature (and the attacker can't re-sign without the secret).
65
65
  const { ts, nonce, sig } = signCliAuth(secret, cliAuthBind('POST', path, port));
66
- let res;
66
+ const ac = opts.timeoutMs === undefined ? null : new AbortController();
67
+ const timer = ac ? setTimeout(() => ac.abort(), opts.timeoutMs) : null;
67
68
  try {
68
- res = await fetchImpl(`http://${host}:${port}${path}`, {
69
+ // The timeout must span the WHOLE exchange, not just the headers: a fetch
70
+ // resolves its Response as soon as headers arrive, so a server that sends
71
+ // `200 application/json` and then stalls mid-body would hang forever in
72
+ // `.text()`/`.json()` below. MEASURED: with the timer cleared right after the
73
+ // fetch, exactly that shape wedged the CLI (outer timeout, rc=124).
74
+ const res = await fetchImpl(`http://${host}:${port}${path}`, {
69
75
  method: 'POST',
70
76
  headers: {
71
77
  'X-Botmux-Cli-Ts': ts,
72
78
  'X-Botmux-Cli-Nonce': nonce,
73
79
  'X-Botmux-Cli-Auth': sig,
74
80
  },
81
+ ...(ac ? { signal: ac.signal } : {}),
75
82
  });
83
+ // Read the body ONCE, and never swallow a failed read. Every status branch used
84
+ // to do `.text().catch(() => '')`, which turns an ABORTED body into a normal
85
+ // empty body — so a server answering `500 headers` + a body that never
86
+ // completes was classified `http-error`. That matters beyond the label:
87
+ // `reachedDashboard(http-error)` is true, so rediscovery STOPS and the stale
88
+ // port file is kept, letting one stalled service permanently block self-heal.
89
+ // MEASURED: recorded port returning `500` + partial body → `http-error` in
90
+ // 305ms, port file unchanged, real dashboard never probed.
91
+ //
92
+ // A COMPLETE body still classifies normally even when malformed; only an
93
+ // aborted/failed read escapes to the catch below as `unreachable`.
94
+ const raw = await res.text();
95
+ if (res.status === 404)
96
+ return classifyDashboard404(path, raw);
97
+ if (res.status === 401)
98
+ return classifyDashboard401(raw);
99
+ if (!res.ok) {
100
+ return { ok: false, reason: 'http-error', detail: `${res.status} ${raw}` };
101
+ }
102
+ // reload-binding 不返回 url,200 即成功(仅用于「捅一下 daemon 重连」)
103
+ if (path === '/__cli/reload-binding')
104
+ return { ok: true, url: '' };
105
+ let body = {};
106
+ try {
107
+ body = JSON.parse(raw);
108
+ }
109
+ catch {
110
+ body = {};
111
+ }
112
+ if (!body.url)
113
+ return { ok: false, reason: 'http-error', detail: 'malformed response (no url)' };
114
+ // localUrl is present only when the dashboard link routes through the central
115
+ // platform — a direct host:port fallback for when the platform is down.
116
+ return { ok: true, url: body.url, localUrl: body.localUrl };
76
117
  }
77
118
  catch {
119
+ // Includes the abort and a body that never completes: for our purposes a
120
+ // stalled port is indistinguishable from a dead one, and both must let the
121
+ // probe loop move on. A malformed-but-COMPLETE body never lands here — it is
122
+ // classified above, because only the `.text()` read itself can reject.
78
123
  return { ok: false, reason: 'unreachable' };
79
124
  }
80
- if (res.status === 404)
81
- return classifyDashboard404(path, await res.text().catch(() => ''));
82
- if (res.status === 401)
83
- return classifyDashboard401(await res.text().catch(() => ''));
84
- if (!res.ok) {
85
- return { ok: false, reason: 'http-error', detail: `${res.status} ${await res.text().catch(() => '')}` };
125
+ finally {
126
+ // Always clear it a live timer would keep the CLI's event loop alive.
127
+ if (timer)
128
+ clearTimeout(timer);
86
129
  }
87
- // reload-binding 不返回 url,200 即成功(仅用于「捅一下 daemon 重连」)
88
- if (path === '/__cli/reload-binding')
89
- return { ok: true, url: '' };
90
- const body = await res.json().catch(() => ({}));
91
- if (!body.url)
92
- return { ok: false, reason: 'http-error', detail: 'malformed response (no url)' };
93
- // localUrl is present only when the dashboard link routes through the central
94
- // platform — a direct host:port fallback for when the platform is down.
95
- return { ok: true, url: body.url, localUrl: body.localUrl };
96
130
  }
97
131
  /** A result that proves we actually reached the dashboard (vs. wrong port). */
98
132
  function reachedDashboard(r) {
99
133
  return r.ok || (!r.ok && (r.reason === 'no-active-token' || r.reason === 'http-error'));
100
134
  }
101
- function shouldRediscover(r) {
102
- return !r.ok && (r.reason === 'wrong-service' || r.reason === 'auth-failed');
135
+ /**
136
+ * Should a failure on the recorded port trigger a probe-range rescan?
137
+ *
138
+ * `wrong-service` / `auth-failed` mean SOMETHING answered but is not our
139
+ * dashboard, so the recorded port is provably wrong and scanning is safe.
140
+ *
141
+ * `unreachable` is ambiguous — it is BOTH "dashboard still booting" (retry the
142
+ * same port; scanning would be wasted work every tick) AND "the recorded port is
143
+ * a dead value nobody listens on" (retrying can never succeed, so without a scan
144
+ * the port file stays wrong forever). MEASURED on a box where `.dashboard-port`
145
+ * held 7893 while the live dashboard was on 7891 with 0 processes on 7893: every
146
+ * `botmux dashboard` failed, and the existing self-heal never ran because it is
147
+ * gated on someone answering.
148
+ *
149
+ * `allowUnreachableRescan` is how the caller separates the two: a one-shot human
150
+ * command passes true (at worst one scan per invocation); the 500ms readiness poll
151
+ * leaves it false. It is deliberately NOT derived from "is the dashboard coming
152
+ * up?" — that answers `true` for `online` + live pid too, which is exactly the
153
+ * measured failure, so such a gate would never fire on the real bug.
154
+ */
155
+ /**
156
+ * Per-probe cap. Loopback only, so a healthy dashboard answers in milliseconds;
157
+ * this exists purely to survive a port that accepts TCP and never replies.
158
+ */
159
+ export const DISCOVERY_PROBE_TIMEOUT_MS = 2_000;
160
+ /**
161
+ * Cap for the WHOLE serial scan. Without it, `probeSpan × probeTimeout`
162
+ * (21 × 2s) would be the worst case on a host full of stalled loopback services.
163
+ */
164
+ export const DISCOVERY_TOTAL_BUDGET_MS = 8_000;
165
+ function shouldRediscover(r, allowUnreachableRescan = false) {
166
+ if (r.ok)
167
+ return false;
168
+ if (r.reason === 'wrong-service' || r.reason === 'auth-failed')
169
+ return true;
170
+ return allowUnreachableRescan && r.reason === 'unreachable';
103
171
  }
104
172
  /**
105
173
  * Resolve the dashboard URL for `path`, trying the recorded port first and
@@ -127,26 +195,67 @@ export async function callDashboard(opts) {
127
195
  || opts.envPort
128
196
  || String(opts.defaultPort);
129
197
  const candidate = Number(recorded);
198
+ const probeTimeoutMs = opts.probeTimeoutMs ?? DISCOVERY_PROBE_TIMEOUT_MS;
130
199
  // 1. Try the recorded port. A success — or any state that proves we reached
131
200
  // the dashboard (no-active-token / http-error) — is returned as-is.
132
- const first = await requestDashboardAt({ host, port: candidate, path: opts.path, secret, fetchImpl });
201
+ //
202
+ // This hop must be bounded whenever the caller can't otherwise interrupt it.
203
+ // An opted-in one-shot command gets `probeTimeoutMs`; the readiness poll
204
+ // passes `requestTimeoutMs` explicitly, because its own 90s budget is only
205
+ // checked AFTER this await returns — so a recorded port that accepts and never
206
+ // answers would hang the first iteration forever, with the outer budget and
207
+ // the retry loop both unreachable. Callers that pass neither stay unbounded.
208
+ const firstTimeoutMs = opts.requestTimeoutMs
209
+ ?? (opts.rescanWhenUnreachable ? probeTimeoutMs : undefined);
210
+ const first = await requestDashboardAt({
211
+ host, port: candidate, path: opts.path, secret, fetchImpl,
212
+ ...(firstTimeoutMs === undefined ? {} : { timeoutMs: firstTimeoutMs }),
213
+ });
133
214
  if (reachedDashboard(first))
134
215
  return first;
135
- // 2. Rediscover only when some server answered on the recorded loopback port
136
- // but failed dashboard identity checks: explicit wrong-service 404, or a
137
- // sig_mismatch from a shadow/stale dashboard. (`unreachable` during boot
138
- // resolves by retrying the same port, not by scanning so we leave it to
139
- // the caller's retry loop.)
140
- if (!shouldRediscover(first))
216
+ // 2. Rediscover when the recorded port provably cannot be the dashboard:
217
+ // something answered but failed identity checks (wrong-service 404 /
218
+ // sig_mismatch), or when the caller opted in, i.e. a one-shot human
219
+ // command nothing is listening there at all (a dead recorded port, which
220
+ // retrying the same port can never fix).
221
+ if (!shouldRediscover(first, opts.rescanWhenUnreachable))
141
222
  return first;
142
223
  const base = Number(opts.envPort || opts.defaultPort);
224
+ // TWO bounds, and both are needed. Per-probe alone degrades to
225
+ // `probeSpan × timeout` (21 × 2s ≈ 42s) because the loop is serial; a total
226
+ // deadline alone would let one stalled port consume the entire budget before
227
+ // any other candidate is tried. MEASURED without either: a local service that
228
+ // accepts TCP and never answers made `callDashboard` hang forever.
229
+ const deadline = Date.now() + (opts.discoveryBudgetMs ?? DISCOVERY_TOTAL_BUDGET_MS);
143
230
  for (let p = base; p <= base + probeSpan; p++) {
144
231
  if (p === candidate)
145
232
  continue;
233
+ // Out of budget: stop and report the ORIGINAL failure. Never invent a reason,
234
+ // and never rewrite the port file on the way out.
235
+ //
236
+ // This `break` and the `Math.min` clamp below have DISTINCT jobs:
237
+ // • the break stops ISSUING probes once the budget is gone — after the
238
+ // deadline no further connection or HMAC probe may be attempted at all;
239
+ // • the clamp bounds the DURATION of a probe that is still allowed to start,
240
+ // so the last one cannot overrun the budget by a full probeTimeoutMs.
241
+ // Wall-clock alone cannot tell them apart (deleting either leaves a 900ms
242
+ // budget at ~910ms, because a negative `remaining` clamps to a ~0ms timeout and
243
+ // probes then fail instantly). Each is pinned by its own test with a criterion
244
+ // that DOES discriminate: call-count for the break, and `budget <
245
+ // probeTimeoutMs` for the clamp. See dashboard-endpoint.test.ts.
246
+ const remaining = deadline - Date.now();
247
+ if (remaining <= 0)
248
+ break;
146
249
  // Probe read-only (`/__cli/current`) so discovery never mints a token on a
147
250
  // server we're merely identifying. Only the real dashboard can answer the
148
251
  // HMAC-gated route as `ok` or `no-active-token`.
149
- const probe = await requestDashboardAt({ host, port: p, path: '/__cli/current', secret, fetchImpl });
252
+ // Clamp to what is LEFT, or the last probe could overrun the budget by a full
253
+ // probeTimeoutMs (checking the deadline before the probe bounds when we start,
254
+ // not when we finish) — making the "total budget" a soft target rather than a cap.
255
+ const probe = await requestDashboardAt({
256
+ host, port: p, path: '/__cli/current', secret, fetchImpl,
257
+ timeoutMs: Math.min(probeTimeoutMs, remaining),
258
+ });
150
259
  if (probe.ok || (!probe.ok && probe.reason === 'no-active-token')) {
151
260
  if (persistPort) {
152
261
  try {
@@ -154,11 +263,16 @@ export async function callDashboard(opts) {
154
263
  }
155
264
  catch { /* best-effort self-heal */ }
156
265
  }
157
- // Found the dashboard — perform the actually-requested op on its port.
158
- return requestDashboardAt({ host, port: p, path: opts.path, secret, fetchImpl });
266
+ // Found the dashboard — perform the actually-requested op on its port. The
267
+ // real request gets its own fresh timeout: it is not discovery, and it must
268
+ // not inherit whatever the scan already spent.
269
+ return requestDashboardAt({
270
+ host, port: p, path: opts.path, secret, fetchImpl, timeoutMs: probeTimeoutMs,
271
+ });
159
272
  }
160
273
  }
161
- // No dashboard found in the probe range; surface the original wrong-service.
274
+ // No dashboard found in the probe range; surface the original failure
275
+ // (wrong-service, auth-failed, or unreachable) rather than inventing one.
162
276
  return first;
163
277
  }
164
278
  //# sourceMappingURL=dashboard-endpoint.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"dashboard-endpoint.js","sourceRoot":"","sources":["../../src/cli/dashboard-endpoint.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"dashboard-endpoint.js","sourceRoot":"","sources":["../../src/cli/dashboard-endpoint.ts"],"names":[],"mappings":"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"}
@@ -13,6 +13,8 @@ export type DispatchPrimaryDeps = {
13
13
  sendMessage: SendMessageFn;
14
14
  replyMessage: ReplyMessageFn;
15
15
  };
16
+ /** Keep provider details visible without leaking Axios config or headers. */
17
+ export declare function describeSendFailure(err: unknown): string;
16
18
  /** First attachment path that aliases stdin, or null if none do. */
17
19
  export declare function findStdinAliasAttachment(paths: readonly string[]): string | null;
18
20
  export type SlashSendValidation = {
@@ -1 +1 @@
1
- {"version":3,"file":"send-dispatch.d.ts","sourceRoot":"","sources":["../../src/cli/send-dispatch.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"send-dispatch.d.ts","sourceRoot":"","sources":["../../src/cli/send-dispatch.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,10 @@
1
1
  import { extname } from 'node:path';
2
+ import { formatLarkError } from '../bot-registry.js';
3
+ /** Keep provider details visible without leaking Axios config or headers. */
4
+ export function describeSendFailure(err) {
5
+ return formatLarkError(err)
6
+ ?? (err instanceof Error && err.message ? err.message : String(err));
7
+ }
2
8
  /**
3
9
  * Paths that resolve to the process's own stdin. `botmux send` reads stdin for
4
10
  * the message body (the documented `echo "msg" | botmux send` form), so passing
@@ -66,7 +72,7 @@ export async function sendFileAttachments(deps, appId, files) {
66
72
  sent.push(await deps.dispatch(JSON.stringify({ file_key: fileKey }), 'file'));
67
73
  }
68
74
  catch (err) {
69
- failed.push({ path: fp, error: err?.message ?? String(err) });
75
+ failed.push({ path: fp, error: describeSendFailure(err) });
70
76
  }
71
77
  }
72
78
  return { sent, failed };
@@ -308,7 +314,7 @@ export async function sendVideoAttachments(deps, appId, videos) {
308
314
  failed.push({
309
315
  path: video.videoPath,
310
316
  coverPath: video.coverPath,
311
- error: err?.message ?? String(err),
317
+ error: describeSendFailure(err),
312
318
  });
313
319
  }
314
320
  }