@ashx-j/lunr 0.2.24 → 0.2.26

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 (254) hide show
  1. package/CHANGELOG.md +24 -1
  2. package/dist/builtin-extensions/index.d.ts.map +1 -1
  3. package/dist/builtin-extensions/index.js +1 -0
  4. package/dist/builtin-extensions/index.js.map +1 -1
  5. package/dist/builtin-extensions/lunr-computer-use.d.ts +3 -0
  6. package/dist/builtin-extensions/lunr-computer-use.d.ts.map +1 -0
  7. package/dist/builtin-extensions/lunr-computer-use.js +179 -0
  8. package/dist/builtin-extensions/lunr-computer-use.js.map +1 -0
  9. package/dist/builtin-extensions/pi-subagents/src/extension/schemas.d.ts.map +1 -1
  10. package/dist/builtin-extensions/pi-subagents/src/extension/schemas.js +1 -1
  11. package/dist/builtin-extensions/pi-subagents/src/extension/schemas.js.map +1 -1
  12. package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.d.ts +4 -4
  13. package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.d.ts.map +1 -1
  14. package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.js +8 -5
  15. package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.js.map +1 -1
  16. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-runner.d.ts +1 -0
  17. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-runner.d.ts.map +1 -1
  18. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-runner.js +11 -2
  19. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-runner.js.map +1 -1
  20. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-execution.d.ts.map +1 -1
  21. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-execution.js +3 -3
  22. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-execution.js.map +1 -1
  23. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/execution.d.ts.map +1 -1
  24. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/execution.js +15 -1
  25. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/execution.js.map +1 -1
  26. package/dist/builtin-extensions/pi-subagents/src/runs/shared/chain-outputs.d.ts +1 -0
  27. package/dist/builtin-extensions/pi-subagents/src/runs/shared/chain-outputs.d.ts.map +1 -1
  28. package/dist/builtin-extensions/pi-subagents/src/runs/shared/chain-outputs.js +5 -0
  29. package/dist/builtin-extensions/pi-subagents/src/runs/shared/chain-outputs.js.map +1 -1
  30. package/dist/builtin-extensions/pi-subagents/src/runs/shared/child-tools.d.ts +1 -1
  31. package/dist/builtin-extensions/pi-subagents/src/runs/shared/child-tools.d.ts.map +1 -1
  32. package/dist/builtin-extensions/pi-subagents/src/runs/shared/child-tools.js +2 -0
  33. package/dist/builtin-extensions/pi-subagents/src/runs/shared/child-tools.js.map +1 -1
  34. package/dist/builtin-extensions/pi-subagents/src/tui/communication.d.ts.map +1 -1
  35. package/dist/builtin-extensions/pi-subagents/src/tui/communication.js +1 -1
  36. package/dist/builtin-extensions/pi-subagents/src/tui/communication.js.map +1 -1
  37. package/dist/builtin-extensions/pi-subagents/src/tui/render.d.ts +1 -0
  38. package/dist/builtin-extensions/pi-subagents/src/tui/render.d.ts.map +1 -1
  39. package/dist/builtin-extensions/pi-subagents/src/tui/render.js +5 -3
  40. package/dist/builtin-extensions/pi-subagents/src/tui/render.js.map +1 -1
  41. package/dist/core/computer-use/adapter.d.ts +28 -0
  42. package/dist/core/computer-use/adapter.d.ts.map +1 -0
  43. package/dist/core/computer-use/adapter.js +133 -0
  44. package/dist/core/computer-use/adapter.js.map +1 -0
  45. package/dist/core/computer-use/image.d.ts +27 -0
  46. package/dist/core/computer-use/image.d.ts.map +1 -0
  47. package/dist/core/computer-use/image.js +72 -0
  48. package/dist/core/computer-use/image.js.map +1 -0
  49. package/dist/core/computer-use/lease.d.ts +18 -0
  50. package/dist/core/computer-use/lease.d.ts.map +1 -0
  51. package/dist/core/computer-use/lease.js +129 -0
  52. package/dist/core/computer-use/lease.js.map +1 -0
  53. package/dist/core/computer-use/macos-runtime.d.ts +14 -0
  54. package/dist/core/computer-use/macos-runtime.d.ts.map +1 -0
  55. package/dist/core/computer-use/macos-runtime.js +148 -0
  56. package/dist/core/computer-use/macos-runtime.js.map +1 -0
  57. package/dist/core/computer-use/policy.d.ts +19 -0
  58. package/dist/core/computer-use/policy.d.ts.map +1 -0
  59. package/dist/core/computer-use/policy.js +67 -0
  60. package/dist/core/computer-use/policy.js.map +1 -0
  61. package/dist/core/computer-use/release.generated.d.ts +31 -0
  62. package/dist/core/computer-use/release.generated.d.ts.map +1 -0
  63. package/dist/core/computer-use/release.generated.js +36 -0
  64. package/dist/core/computer-use/release.generated.js.map +1 -0
  65. package/dist/core/computer-use/runtime.d.ts +13 -0
  66. package/dist/core/computer-use/runtime.d.ts.map +1 -0
  67. package/dist/core/computer-use/runtime.js +158 -0
  68. package/dist/core/computer-use/runtime.js.map +1 -0
  69. package/dist/core/computer-use/schemas.d.ts +100 -0
  70. package/dist/core/computer-use/schemas.d.ts.map +1 -0
  71. package/dist/core/computer-use/schemas.js +79 -0
  72. package/dist/core/computer-use/schemas.js.map +1 -0
  73. package/dist/core/computer-use/windows-desktop.d.ts +3 -0
  74. package/dist/core/computer-use/windows-desktop.d.ts.map +1 -0
  75. package/dist/core/computer-use/windows-desktop.js +48 -0
  76. package/dist/core/computer-use/windows-desktop.js.map +1 -0
  77. package/dist/core/computer-use/workflow.d.ts +38 -0
  78. package/dist/core/computer-use/workflow.d.ts.map +1 -0
  79. package/dist/core/computer-use/workflow.js +560 -0
  80. package/dist/core/computer-use/workflow.js.map +1 -0
  81. package/dist/core/extensions/loader.d.ts.map +1 -1
  82. package/dist/core/extensions/loader.js +4 -0
  83. package/dist/core/extensions/loader.js.map +1 -1
  84. package/dist/core/permissions.d.ts +1 -1
  85. package/dist/core/permissions.d.ts.map +1 -1
  86. package/dist/core/permissions.js +14 -3
  87. package/dist/core/permissions.js.map +1 -1
  88. package/dist/core/plan-mode.d.ts.map +1 -1
  89. package/dist/core/plan-mode.js +9 -0
  90. package/dist/core/plan-mode.js.map +1 -1
  91. package/dist/core/settings-manager.d.ts +6 -0
  92. package/dist/core/settings-manager.d.ts.map +1 -1
  93. package/dist/core/settings-manager.js +19 -0
  94. package/dist/core/settings-manager.js.map +1 -1
  95. package/dist/core/subagent-event-transport.d.ts +3 -0
  96. package/dist/core/subagent-event-transport.d.ts.map +1 -0
  97. package/dist/core/subagent-event-transport.js +61 -0
  98. package/dist/core/subagent-event-transport.js.map +1 -0
  99. package/dist/gateway/adapters/discord.d.ts.map +1 -1
  100. package/dist/gateway/adapters/discord.js +4 -9
  101. package/dist/gateway/adapters/discord.js.map +1 -1
  102. package/dist/gateway/adapters/telegram.d.ts.map +1 -1
  103. package/dist/gateway/adapters/telegram.js +7 -0
  104. package/dist/gateway/adapters/telegram.js.map +1 -1
  105. package/dist/gateway/agent-bridge.d.ts +4 -1
  106. package/dist/gateway/agent-bridge.d.ts.map +1 -1
  107. package/dist/gateway/agent-bridge.js +57 -17
  108. package/dist/gateway/agent-bridge.js.map +1 -1
  109. package/dist/gateway/approval.d.ts.map +1 -1
  110. package/dist/gateway/approval.js +3 -3
  111. package/dist/gateway/approval.js.map +1 -1
  112. package/dist/gateway/authz.d.ts +4 -4
  113. package/dist/gateway/authz.d.ts.map +1 -1
  114. package/dist/gateway/authz.js +8 -12
  115. package/dist/gateway/authz.js.map +1 -1
  116. package/dist/gateway/buttons.d.ts.map +1 -1
  117. package/dist/gateway/buttons.js +29 -19
  118. package/dist/gateway/buttons.js.map +1 -1
  119. package/dist/gateway/commands.d.ts +2 -0
  120. package/dist/gateway/commands.d.ts.map +1 -1
  121. package/dist/gateway/commands.js +35 -18
  122. package/dist/gateway/commands.js.map +1 -1
  123. package/dist/gateway/config.d.ts +1 -0
  124. package/dist/gateway/config.d.ts.map +1 -1
  125. package/dist/gateway/config.js +2 -0
  126. package/dist/gateway/config.js.map +1 -1
  127. package/dist/gateway/cron.d.ts +1 -1
  128. package/dist/gateway/cron.d.ts.map +1 -1
  129. package/dist/gateway/cron.js +22 -8
  130. package/dist/gateway/cron.js.map +1 -1
  131. package/dist/gateway/index.d.ts.map +1 -1
  132. package/dist/gateway/index.js +26 -26
  133. package/dist/gateway/index.js.map +1 -1
  134. package/dist/gateway/mobile-commands.d.ts.map +1 -1
  135. package/dist/gateway/mobile-commands.js +11 -11
  136. package/dist/gateway/mobile-commands.js.map +1 -1
  137. package/dist/gateway/presenter.d.ts +12 -1
  138. package/dist/gateway/presenter.d.ts.map +1 -1
  139. package/dist/gateway/presenter.js +148 -50
  140. package/dist/gateway/presenter.js.map +1 -1
  141. package/dist/gateway/router.d.ts +5 -5
  142. package/dist/gateway/router.d.ts.map +1 -1
  143. package/dist/gateway/router.js +95 -43
  144. package/dist/gateway/router.js.map +1 -1
  145. package/dist/gateway/service.d.ts.map +1 -1
  146. package/dist/gateway/service.js +13 -4
  147. package/dist/gateway/service.js.map +1 -1
  148. package/dist/gateway/setup.d.ts +5 -0
  149. package/dist/gateway/setup.d.ts.map +1 -1
  150. package/dist/gateway/setup.js +101 -43
  151. package/dist/gateway/setup.js.map +1 -1
  152. package/dist/gateway/stream.d.ts +6 -5
  153. package/dist/gateway/stream.d.ts.map +1 -1
  154. package/dist/gateway/stream.js +24 -11
  155. package/dist/gateway/stream.js.map +1 -1
  156. package/dist/modes/interactive/components/settings-selector.d.ts +4 -0
  157. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  158. package/dist/modes/interactive/components/settings-selector.js +20 -0
  159. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  160. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  161. package/dist/modes/interactive/interactive-mode.js +8 -0
  162. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  163. package/dist/modes/print-mode.d.ts.map +1 -1
  164. package/dist/modes/print-mode.js +9 -1
  165. package/dist/modes/print-mode.js.map +1 -1
  166. package/dist/node-runtime/adapter-VFG7WNPX.js +17 -0
  167. package/dist/node-runtime/{agent-session-services-IEF7LQWD.js → agent-session-services-5YXS2PLF.js} +13 -10
  168. package/dist/node-runtime/{builtin-extensions-EBAWTH4M.js → builtin-extensions-I2HIFEMY.js} +3 -2
  169. package/dist/node-runtime/{chunk-K5AGHH57.js → chunk-2CFDTH5B.js} +7 -3
  170. package/dist/node-runtime/{chunk-VWCE2HSZ.js → chunk-2HMIRK7W.js} +4 -4
  171. package/dist/node-runtime/chunk-2IDTZAG5.js +1415 -0
  172. package/dist/node-runtime/{chunk-IGV54Q5V.js → chunk-3MISGG4S.js} +137 -76
  173. package/dist/node-runtime/chunk-4SBQAI4T.js +2185 -0
  174. package/dist/node-runtime/{chunk-WHLRAGUQ.js → chunk-5B5QN3ZQ.js} +16 -16
  175. package/dist/node-runtime/chunk-5B6VKFEV.js +180 -0
  176. package/dist/node-runtime/{chunk-AD6VXAO7.js → chunk-5Q4A37RB.js} +15 -104
  177. package/dist/node-runtime/{chunk-4TLO4PO2.js → chunk-7IQGBKBJ.js} +7 -1401
  178. package/dist/node-runtime/{chunk-R3K2F5GI.js → chunk-B4HP6ZWM.js} +2 -0
  179. package/dist/node-runtime/{chunk-OCVIXVTZ.js → chunk-D5UCKPBQ.js} +12 -1
  180. package/dist/node-runtime/chunk-DVQSHCVP.js +97 -0
  181. package/dist/node-runtime/{chunk-HFVZUPFJ.js → chunk-E75WFZ33.js} +2 -2
  182. package/dist/node-runtime/chunk-FY4A63RK.js +73 -0
  183. package/dist/node-runtime/{chunk-RORY2HMJ.js → chunk-I74LN5JG.js} +16 -1
  184. package/dist/node-runtime/chunk-IKU6Y7DL.js +287 -0
  185. package/dist/node-runtime/{chunk-QM43FEAE.js → chunk-L24TPBS4.js} +6 -5
  186. package/dist/node-runtime/{chunk-DE2JB6J5.js → chunk-LJTIVM7I.js} +7 -7
  187. package/dist/node-runtime/{chunk-DSIKTUPW.js → chunk-LWJXTA6Z.js} +274 -2433
  188. package/dist/node-runtime/{chunk-YVI6L6LU.js → chunk-P7XBVXGT.js} +36 -21
  189. package/dist/node-runtime/{chunk-OVX6X377.js → chunk-PTFBPO3C.js} +1 -1
  190. package/dist/node-runtime/{chunk-F4FLTQKV.js → chunk-RAK2QA2B.js} +186 -1529
  191. package/dist/node-runtime/{chunk-L3LX4SNR.js → chunk-RCR3XAQY.js} +36 -8
  192. package/dist/node-runtime/chunk-RGQAEOM5.js +81 -0
  193. package/dist/node-runtime/{chunk-UWPJL22I.js → chunk-SLVOAQOY.js} +15 -4
  194. package/dist/node-runtime/chunk-SN2KSMPQ.js +1364 -0
  195. package/dist/node-runtime/{chunk-FU6OODRZ.js → chunk-SPVDBUOS.js} +1 -1
  196. package/dist/node-runtime/{chunk-5Q3EHOHI.js → chunk-T4DA4XE7.js} +19 -17
  197. package/dist/node-runtime/chunk-U5F4IC7R.js +53 -0
  198. package/dist/node-runtime/{chunk-UP2XBVH5.js → chunk-UOEDI7RP.js} +1 -1
  199. package/dist/node-runtime/{chunk-Y73WPE6S.js → chunk-UVWCDQYF.js} +79 -44
  200. package/dist/node-runtime/{chunk-ZXSGTGJ6.js → chunk-WIF24I7G.js} +21 -5
  201. package/dist/node-runtime/{chunk-OF7PWMG4.js → chunk-X3PGBLQ7.js} +3 -87
  202. package/dist/node-runtime/chunk-XHIRAZ26.js +108 -0
  203. package/dist/node-runtime/{chunk-YDO2F2IA.js → chunk-YWOJIGFY.js} +1 -1
  204. package/dist/node-runtime/{command-7BG7VVTS.js → command-FSBU2EVZ.js} +5 -5
  205. package/dist/node-runtime/{commands-NZLSOHPE.js → commands-EMBQQVVT.js} +4 -2
  206. package/dist/node-runtime/{commands-QFDKNQTL.js → commands-NAAL7KNT.js} +7 -6
  207. package/dist/node-runtime/{config-RORQUQFG.js → config-D4QUPAHX.js} +1 -1
  208. package/dist/node-runtime/{direct-tool-executor-77GW4F5P.js → direct-tool-executor-4D7UXYU4.js} +7 -4
  209. package/dist/node-runtime/{gateway-TWR3N65G.js → gateway-DQM333YV.js} +140 -85
  210. package/dist/node-runtime/index.js +28 -21
  211. package/dist/node-runtime/{init-HS6NQXSK.js → init-P5AUV77I.js} +4 -2
  212. package/dist/node-runtime/{install-cli-VAP6KBFN.js → install-cli-NN4YAU44.js} +3 -3
  213. package/dist/node-runtime/{interactive-mode-6J5VZ2TT.js → interactive-mode-YOHZVMKX.js} +14 -11
  214. package/dist/node-runtime/{lunr-browser-J5ZZYVGM.js → lunr-browser-IR7TL3J7.js} +3 -3
  215. package/dist/node-runtime/lunr-computer-use-Y23CCDIJ.js +158 -0
  216. package/dist/node-runtime/{lunr-cron-CXOL37AL.js → lunr-cron-USHC4LXH.js} +9 -7
  217. package/dist/node-runtime/main.js +19 -15
  218. package/dist/node-runtime/{mcp-auth-flow-QIXHW6QN.js → mcp-auth-flow-QVLFVLEO.js} +2 -1
  219. package/dist/node-runtime/{mobile-commands-VTBM5DSZ.js → mobile-commands-O5LCHL32.js} +6 -5
  220. package/dist/node-runtime/{package-manager-cli-ZLW5DZXF.js → package-manager-cli-Q7BL6KZO.js} +12 -8
  221. package/dist/node-runtime/{pi-mcp-adapter-5UKBZP44.js → pi-mcp-adapter-3PHF4KZ4.js} +5 -5
  222. package/dist/node-runtime/{pi-subagents-XPCLLKIM.js → pi-subagents-7IBSSGEW.js} +27 -21
  223. package/dist/node-runtime/{print-mode-XSFM26EL.js → print-mode-XQ76CYMT.js} +2 -1
  224. package/dist/node-runtime/{proxy-modes-LGEUYD7R.js → proxy-modes-5FAPSZEZ.js} +7 -4
  225. package/dist/node-runtime/rpc-entry.js +19 -15
  226. package/dist/node-runtime/runtime-EFPPD2UW.js +21 -0
  227. package/dist/node-runtime/{runtime-bridges-QYXUX2TG.js → runtime-bridges-7WVCLI76.js} +6 -5
  228. package/dist/node-runtime/{service-ISSP6VHE.js → service-MDQIPQ26.js} +1 -1
  229. package/dist/node-runtime/{settings-manager-WCQDUVQB.js → settings-manager-DJDM5AHM.js} +5 -4
  230. package/dist/node-runtime/setup-PFBWRNUI.js +215 -0
  231. package/dist/node-runtime/{subagent-executor-OTNISDQU.js → subagent-executor-LPZ4BHWE.js} +32 -14
  232. package/dist/node-runtime/{update-cli-VBR2777K.js → update-cli-HNMOTNGX.js} +5 -4
  233. package/dist/node-runtime/workflow-OHPBEFO4.js +637 -0
  234. package/dist/utils/image-resize-core.d.ts +2 -0
  235. package/dist/utils/image-resize-core.d.ts.map +1 -1
  236. package/dist/utils/image-resize-core.js +10 -0
  237. package/dist/utils/image-resize-core.js.map +1 -1
  238. package/docs/computer-use.md +362 -0
  239. package/docs/features.md +9 -7
  240. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  241. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  242. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  243. package/examples/extensions/gondolin/package-lock.json +2 -2
  244. package/examples/extensions/gondolin/package.json +1 -1
  245. package/examples/extensions/sandbox/package-lock.json +2 -2
  246. package/examples/extensions/sandbox/package.json +1 -1
  247. package/examples/extensions/with-deps/package-lock.json +2 -2
  248. package/examples/extensions/with-deps/package.json +1 -1
  249. package/install-lock/package-lock.json +3841 -0
  250. package/install-lock/package.json +18 -0
  251. package/native/computer-use/LICENSE.md +21 -0
  252. package/npm-shrinkwrap.json +3822 -0
  253. package/package.json +15 -9
  254. package/dist/node-runtime/setup-YRBKH2LD.js +0 -155
@@ -3,7 +3,7 @@ import { basename, dirname, isAbsolute, join, relative, resolve } from "node:pat
3
3
  import { getPermissionMode, PERMISSION_MODES, setPermissionMode } from "../core/permissions.js";
4
4
  import { SessionManager } from "../core/session-manager.js";
5
5
  import { getSubagentCancellation } from "../core/subagent-cancellation.js";
6
- import { isGatewayOwner, requireGatewayOwner } from "./authz.js";
6
+ import { isAuthorized, requireAuthorized } from "./authz.js";
7
7
  import { createPicker } from "./buttons.js";
8
8
  import { loadGatewayConfig } from "./config.js";
9
9
  import { bindConversation, conversationBinding } from "./conversations.js";
@@ -113,9 +113,9 @@ async function browseProject(ctx, initialPath) {
113
113
  sessionKey: key,
114
114
  invokerId: event.source.userId,
115
115
  ...initial,
116
- validate: () => isGatewayOwner(event.source, loadGatewayConfig()),
116
+ validate: () => isAuthorized(event.source, loadGatewayConfig()),
117
117
  resolve: async (item) => {
118
- requireGatewayOwner(event.source);
118
+ requireAuthorized(event.source);
119
119
  if (item.value === "use" && current) {
120
120
  const cwd = resolveWithinRoots(current, loadGatewayConfig().projectRoots ?? []);
121
121
  if (bridge.getStatus(key).busy)
@@ -155,10 +155,10 @@ async function continueSession(ctx, file) {
155
155
  }
156
156
  }
157
157
  async function performContinue(ctx, file, signal) {
158
- requireGatewayOwner(ctx.event.source);
158
+ requireAuthorized(ctx.event.source);
159
159
  const { requestSessionTransfer, SessionTransferError } = await import("../core/session-handoff.js");
160
160
  const { key, bridge } = ctx;
161
- const current = await bridge.getSession(key);
161
+ const current = bridge.peekSession?.(key);
162
162
  if (current?.sessionManager?.getSessionFile() === file) {
163
163
  await ctx.adapter.send(ctx.event.source.chatId, "This session is already open here.");
164
164
  return;
@@ -169,7 +169,7 @@ async function performContinue(ctx, file, signal) {
169
169
  await requestSessionTransfer(file, { timeoutMs: 3000, signal });
170
170
  }
171
171
  catch (error) {
172
- if (!(error instanceof SessionTransferError) || error.code !== "busy")
172
+ if (!(error instanceof SessionTransferError) || !["busy", "timeout"].includes(error.code))
173
173
  throw error;
174
174
  const choice = await gatewaySelect(key, `${error instanceof Error ? error.message : "Session is in use"}\nHow should lunR continue?`, ["Wait until idle", "Stop and continue", "Cancel"], { signal });
175
175
  if (!choice || choice === "Cancel")
@@ -180,14 +180,14 @@ async function performContinue(ctx, file, signal) {
180
180
  const deadline = Date.now() + 120_000;
181
181
  for (;;) {
182
182
  signal.throwIfAborted();
183
- requireGatewayOwner(ctx.event.source);
183
+ requireAuthorized(ctx.event.source);
184
184
  try {
185
185
  await requestSessionTransfer(file, { timeoutMs: 3000, signal });
186
186
  break;
187
187
  }
188
188
  catch (retryError) {
189
189
  if (!(retryError instanceof SessionTransferError) ||
190
- retryError.code !== "busy" ||
190
+ !["busy", "timeout"].includes(retryError.code) ||
191
191
  Date.now() >= deadline)
192
192
  throw retryError;
193
193
  }
@@ -196,7 +196,7 @@ async function performContinue(ctx, file, signal) {
196
196
  }
197
197
  }
198
198
  signal.throwIfAborted();
199
- requireGatewayOwner(ctx.event.source);
199
+ requireAuthorized(ctx.event.source);
200
200
  await bridge.switchSession(key, file);
201
201
  const session = await bridge.getSession(key);
202
202
  const cwd = session?.sessionManager?.getCwd();
@@ -271,7 +271,7 @@ async function sessionPicker(ctx, items) {
271
271
  invokerId: ctx.event.source.userId,
272
272
  title: "Choose a session. Use /sessions <search> to filter.",
273
273
  items,
274
- validate: () => isGatewayOwner(ctx.event.source, loadGatewayConfig()),
274
+ validate: () => isAuthorized(ctx.event.source, loadGatewayConfig()),
275
275
  resolve: async (item) => {
276
276
  await continueSession(ctx, item.value);
277
277
  return { done: true, text: "Session selection finished." };
@@ -281,7 +281,7 @@ async function sessionPicker(ctx, items) {
281
281
  export async function handleMobileCommand(ctx, command, args) {
282
282
  if (!MOBILE_COMMANDS.some((c) => c.name === command) && command !== "resume")
283
283
  return false;
284
- requireGatewayOwner(ctx.event.source, ctx.cfg);
284
+ requireAuthorized(ctx.event.source, ctx.cfg);
285
285
  bindConversation(ctx.key, ctx.event.source, { owner: ctx.event.source.userId });
286
286
  if (command === "project") {
287
287
  await browseProject(ctx, args.trim() || undefined);
@@ -1 +1 @@
1
- {"version":3,"file":"mobile-commands.js","sourceRoot":"","sources":["../../src/gateway/mobile-commands.ts"],"names":[],"mappings":"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","sourcesContent":["import { mkdirSync, readdirSync, realpathSync, statSync } from \"node:fs\";\nimport { basename, dirname, isAbsolute, join, relative, resolve } from \"node:path\";\nimport { getPermissionMode, PERMISSION_MODES, setPermissionMode } from \"../core/permissions.ts\";\nimport { SessionManager } from \"../core/session-manager.ts\";\nimport { getSubagentCancellation } from \"../core/subagent-cancellation.ts\";\nimport { isGatewayOwner, requireGatewayOwner } from \"./authz.ts\";\nimport { createPicker, type PickerItem, type PickerResolveResult } from \"./buttons.ts\";\nimport { type GatewayConfig, loadGatewayConfig } from \"./config.ts\";\nimport { bindConversation, conversationBinding } from \"./conversations.ts\";\nimport { gatewayInput, gatewaySelect } from \"./presenter.ts\";\nimport type { BridgeLike } from \"./router.ts\";\nimport type { MessageEvent, PlatformAdapter } from \"./types.ts\";\n\nexport const MOBILE_COMMANDS = [\n\t{ name: \"project\", description: \"Browse folders and choose a project\" },\n\t{ name: \"continue\", description: \"Continue a handoff or the latest TUI session\" },\n\t{ name: \"sessions\", description: \"Browse saved sessions across projects\" },\n\t{ name: \"mode\", description: \"Choose yolo, auto, or read-only permissions\" },\n\t{ name: \"plan\", description: \"Plan work and approve it from this chat\" },\n\t{ name: \"settings\", description: \"Change this session's model, thinking, or permissions\" },\n\t{ name: \"stopall\", description: \"Stop this session and its background subagents\" },\n\t{ name: \"download\", description: \"Send a file from the current project\" },\n\t{ name: \"usage\", description: \"Show session tokens and subscription usage\" },\n\t{ name: \"processes\", description: \"List or stop this session's shell processes\" },\n\t{ name: \"refresh\", description: \"Refresh available models\" },\n\t{ name: \"skill\", description: \"Choose a skill and send it a task\" },\n\t{ name: \"fast\", description: \"Toggle OpenAI Codex fast mode\" },\n];\n\nexport const FORWARDED_COMMANDS = [\n\t{ name: \"goal\", description: \"Set or manage the session goal\" },\n\t{ name: \"cron\", description: \"Schedule prompts and manage scheduled jobs\" },\n\t{ name: \"run\", description: \"Launch a subagent task\" },\n\t{ name: \"chain\", description: \"Run a sequence of subagent tasks\" },\n\t{ name: \"parallel\", description: \"Run independent subagent tasks\" },\n\t{ name: \"mcp\", description: \"Show configured MCP servers\" },\n\t{ name: \"lsp\", description: \"Show language server status\" },\n];\n\nexport function resolveWithinRoots(path: string, roots: string[]): string {\n\tconst actual = realpathSync(resolve(path));\n\tif (\n\t\t!roots.some((root) => {\n\t\t\ttry {\n\t\t\t\tconst rel = relative(realpathSync(root), actual);\n\t\t\t\treturn (\n\t\t\t\t\trel === \"\" ||\n\t\t\t\t\t(!rel.startsWith(`..${process.platform === \"win32\" ? \"\\\\\" : \"/\"}`) && rel !== \"..\" && !isAbsolute(rel))\n\t\t\t\t);\n\t\t\t} catch {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t})\n\t)\n\t\tthrow new Error(\"That path is outside the approved folders.\");\n\treturn actual;\n}\n\nexport function createProjectFolder(parent: string, name: string, roots: string[]): string {\n\tif (\n\t\t!name ||\n\t\tname === \".\" ||\n\t\tname === \"..\" ||\n\t\t/[\\\\/\\x00-\\x1f<>:\"|?*]/.test(name) ||\n\t\t/[. ]$/.test(name) ||\n\t\t/^(con|prn|aux|nul|com\\d|lpt\\d)(\\.|$)/i.test(name)\n\t)\n\t\tthrow new Error(\"Use a simple folder name without slashes or reserved characters.\");\n\tconst actual = resolveWithinRoots(parent, roots);\n\tmkdirSync(join(actual, name));\n\treturn resolveWithinRoots(join(actual, name), roots);\n}\n\ninterface MobileContext {\n\tkey: string;\n\tevent: MessageEvent;\n\tadapter: PlatformAdapter;\n\tbridge: BridgeLike;\n\tcfg: GatewayConfig;\n}\n\nasync function browseProject(ctx: MobileContext, initialPath?: string): Promise<void> {\n\tconst { key, event, adapter, bridge } = ctx;\n\tconst roots = ctx.cfg.projectRoots ?? [];\n\tif (!roots.length) throw new Error(\"Add approved project folders with lunr gateway setup first.\");\n\tlet current: string | undefined = initialPath\n\t\t? resolveWithinRoots(initialPath, ctx.cfg.projectRoots ?? [])\n\t\t: undefined;\n\tconst view = (): { title: string; items: PickerItem[] } => {\n\t\tif (!current)\n\t\t\treturn {\n\t\t\t\ttitle: \"Choose a project folder\",\n\t\t\t\titems: [...new Set([...(conversationBinding(key)?.recentProjects ?? []), ...roots])]\n\t\t\t\t\t.filter((p) => {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tresolveWithinRoots(p, roots);\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t})\n\t\t\t\t\t.map((p) => ({ label: p, value: p })),\n\t\t\t};\n\t\tcurrent = resolveWithinRoots(current, roots);\n\t\tconst items: PickerItem[] = [\n\t\t\t{ label: \"Use this folder\", value: \"use\" },\n\t\t\t{ label: \"New folder\", value: \"new\" },\n\t\t\t{ label: \"Recent and roots\", value: \"roots\" },\n\t\t];\n\t\ttry {\n\t\t\tconst up = resolveWithinRoots(dirname(current), roots);\n\t\t\tif (up !== current) items.push({ label: \"Up\", value: up });\n\t\t} catch {}\n\t\tfor (const item of readdirSync(current, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {\n\t\t\tif (!item.isDirectory() && !item.isSymbolicLink()) continue;\n\t\t\ttry {\n\t\t\t\tconst path = resolveWithinRoots(join(current, item.name), roots);\n\t\t\t\tif (statSync(path).isDirectory()) items.push({ label: item.name, value: path });\n\t\t\t} catch {}\n\t\t}\n\t\treturn { title: current, items };\n\t};\n\tconst initial = view();\n\tawait createPicker(\n\t\tadapter,\n\t\tevent.source,\n\t\t{\n\t\t\tkind: \"project\",\n\t\t\tsessionKey: key,\n\t\t\tinvokerId: event.source.userId,\n\t\t\t...initial,\n\t\t\tvalidate: () => isGatewayOwner(event.source, loadGatewayConfig()),\n\t\t\tresolve: async (item): Promise<PickerResolveResult> => {\n\t\t\t\trequireGatewayOwner(event.source);\n\t\t\t\tif (item.value === \"use\" && current) {\n\t\t\t\t\tconst cwd = resolveWithinRoots(current, loadGatewayConfig().projectRoots ?? []);\n\t\t\t\t\tif (bridge.getStatus(key).busy)\n\t\t\t\t\t\tthrow new Error(\"Stop the current turn or wait before switching projects.\");\n\t\t\t\t\tawait bridge.reset(key);\n\t\t\t\t\tbindConversation(key, event.source, { cwd, owner: event.source.userId });\n\t\t\t\t\treturn {\n\t\t\t\t\t\tdone: true,\n\t\t\t\t\t\ttext: `Project selected: ${cwd}\\nSend a task to begin. Existing sessions are still available through /sessions.`,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tif (item.value === \"new\" && current) {\n\t\t\t\t\tconst name = await gatewayInput(key, \"New folder name\");\n\t\t\t\t\tif (name) current = createProjectFolder(current, name, loadGatewayConfig().projectRoots ?? []);\n\t\t\t\t} else current = item.value === \"roots\" ? undefined : item.value;\n\t\t\t\treturn { done: false, ...view() };\n\t\t\t},\n\t\t},\n\t\t{ threadId: event.source.threadId },\n\t);\n}\n\nconst transfers = new Map<string, AbortController>();\nexport function cancelMobileTransfer(key: string): void {\n\ttransfers.get(key)?.abort();\n}\n\nasync function continueSession(ctx: MobileContext, file: string): Promise<void> {\n\tif (transfers.has(ctx.key)) throw new Error(\"A session transfer is already pending. Use /stop to cancel it.\");\n\tconst controller = new AbortController();\n\ttransfers.set(ctx.key, controller);\n\ttry {\n\t\tawait performContinue(ctx, file, controller.signal);\n\t} finally {\n\t\ttransfers.delete(ctx.key);\n\t}\n}\n\nasync function performContinue(ctx: MobileContext, file: string, signal: AbortSignal): Promise<void> {\n\trequireGatewayOwner(ctx.event.source);\n\tconst { requestSessionTransfer, SessionTransferError } = await import(\"../core/session-handoff.ts\");\n\tconst { key, bridge } = ctx;\n\tconst current = await bridge.getSession(key);\n\tif (current?.sessionManager?.getSessionFile() === file) {\n\t\tawait ctx.adapter.send(ctx.event.source.chatId, \"This session is already open here.\");\n\t\treturn;\n\t}\n\tif (bridge.getStatus(key).busy) throw new Error(\"Stop the current phone session before switching.\");\n\ttry {\n\t\tawait requestSessionTransfer(file, { timeoutMs: 3000, signal });\n\t} catch (error) {\n\t\tif (!(error instanceof SessionTransferError) || error.code !== \"busy\") throw error;\n\t\tconst choice = await gatewaySelect(\n\t\t\tkey,\n\t\t\t`${error instanceof Error ? error.message : \"Session is in use\"}\\nHow should lunR continue?`,\n\t\t\t[\"Wait until idle\", \"Stop and continue\", \"Cancel\"],\n\t\t\t{ signal },\n\t\t);\n\t\tif (!choice || choice === \"Cancel\") return;\n\t\tif (choice === \"Stop and continue\") await requestSessionTransfer(file, { stop: true, timeoutMs: 30_000, signal });\n\t\telse {\n\t\t\tconst deadline = Date.now() + 120_000;\n\t\t\tfor (;;) {\n\t\t\t\tsignal.throwIfAborted();\n\t\t\t\trequireGatewayOwner(ctx.event.source);\n\t\t\t\ttry {\n\t\t\t\t\tawait requestSessionTransfer(file, { timeoutMs: 3000, signal });\n\t\t\t\t\tbreak;\n\t\t\t\t} catch (retryError) {\n\t\t\t\t\tif (\n\t\t\t\t\t\t!(retryError instanceof SessionTransferError) ||\n\t\t\t\t\t\tretryError.code !== \"busy\" ||\n\t\t\t\t\t\tDate.now() >= deadline\n\t\t\t\t\t)\n\t\t\t\t\t\tthrow retryError;\n\t\t\t\t}\n\t\t\t\tawait new Promise((resolve) => setTimeout(resolve, 500));\n\t\t\t}\n\t\t}\n\t}\n\tsignal.throwIfAborted();\n\trequireGatewayOwner(ctx.event.source);\n\tawait bridge.switchSession(key, file);\n\tconst session = await bridge.getSession(key);\n\tconst cwd = session?.sessionManager?.getCwd();\n\tbindConversation(key, ctx.event.source, { cwd, owner: ctx.event.source.userId });\n\tconst id = session?.sessionManager?.getSessionId();\n\tif (id && [\"auto\", \"yolo\"].includes(getPermissionMode(id))) {\n\t\tconst requested = getPermissionMode(id);\n\t\tsetPermissionMode(\"read-only\", id);\n\t\tsession?.sessionManager?.setPermissionMode?.(\"read-only\");\n\t\tif (\n\t\t\t(await gatewaySelect(\n\t\t\t\tkey,\n\t\t\t\t`Continue with ${requested} permissions? Tools can change files and run commands without individual approval.`,\n\t\t\t\t[\"Keep read-only\", `Use ${requested}`],\n\t\t\t)) === `Use ${requested}`\n\t\t) {\n\t\t\tsetPermissionMode(requested, id);\n\t\t\tsession?.sessionManager?.setPermissionMode?.(requested);\n\t\t}\n\t}\n\tawait ctx.adapter.send(\n\t\tctx.event.source.chatId,\n\t\t`Continuing ${session?.sessionManager?.getSessionName() ?? basename(file)}\\nProject: ${cwd}\\nSend your next instruction.`,\n\t\t{ threadId: ctx.event.source.threadId },\n\t);\n}\n\nasync function browseSessions(ctx: MobileContext, args: string, quick: boolean): Promise<void> {\n\tconst handoff = await import(\"../core/session-handoff.ts\");\n\tif (quick) {\n\t\tconst candidates = handoff.listHandoffCandidates();\n\t\tif (!candidates.length) {\n\t\t\tconst latest = handoff.latestTuiSession();\n\t\t\tif (!latest)\n\t\t\t\tthrow new Error(\"No recent TUI session found. Use /sessions or mark one in the terminal with /handoff.\");\n\t\t\tawait continueSession(ctx, latest.sessionFile);\n\t\t\treturn;\n\t\t}\n\t\tif (candidates.length === 1) {\n\t\t\tawait continueSession(ctx, candidates[0].sessionFile);\n\t\t\treturn;\n\t\t}\n\t\tawait sessionPicker(\n\t\t\tctx,\n\t\t\tcandidates.map((s) => ({ label: `${s.cwd} · ${basename(s.sessionFile)}`, value: s.sessionFile })),\n\t\t);\n\t\treturn;\n\t}\n\tconst sessions = await SessionManager.listAll();\n\tconst known = new Set(sessions.map((s) => s.path));\n\tfor (const file of handoff.listRegisteredSessionPaths()) {\n\t\tif (known.has(file)) continue;\n\t\ttry {\n\t\t\tconst manager = SessionManager.openReadOnly(file);\n\t\t\tconst header = manager.getHeader();\n\t\t\tif (header)\n\t\t\t\tsessions.push({\n\t\t\t\t\tid: header.id,\n\t\t\t\t\tpath: file,\n\t\t\t\t\tcwd: manager.getCwd(),\n\t\t\t\t\tname: manager.getSessionName(),\n\t\t\t\t\tcreated: new Date(header.timestamp),\n\t\t\t\t\tmodified: statSync(file).mtime,\n\t\t\t\t\tmessageCount: manager.getEntries().length,\n\t\t\t\t\tfirstMessage: \"\",\n\t\t\t\t\tallMessagesText: \"\",\n\t\t\t\t});\n\t\t} catch {}\n\t}\n\tconst query = args.toLowerCase();\n\tconst items = sessions\n\t\t.sort((a, b) => b.modified.getTime() - a.modified.getTime())\n\t\t.filter((s) => !query || `${s.name ?? \"\"} ${s.cwd} ${s.id}`.toLowerCase().includes(query))\n\t\t.map((s) => ({\n\t\t\tlabel: `${s.name || s.firstMessage.slice(0, 35) || s.id.slice(0, 8)} · ${basename(s.cwd)} · ${s.modified.toLocaleDateString()}`,\n\t\t\tvalue: s.path,\n\t\t}));\n\tawait sessionPicker(ctx, items);\n}\n\nasync function sessionPicker(ctx: MobileContext, items: PickerItem[]): Promise<void> {\n\tawait createPicker(\n\t\tctx.adapter,\n\t\tctx.event.source,\n\t\t{\n\t\t\tkind: \"sessions\",\n\t\t\tsessionKey: ctx.key,\n\t\t\tinvokerId: ctx.event.source.userId,\n\t\t\ttitle: \"Choose a session. Use /sessions <search> to filter.\",\n\t\t\titems,\n\t\t\tvalidate: () => isGatewayOwner(ctx.event.source, loadGatewayConfig()),\n\t\t\tresolve: async (item) => {\n\t\t\t\tawait continueSession(ctx, item.value);\n\t\t\t\treturn { done: true, text: \"Session selection finished.\" };\n\t\t\t},\n\t\t},\n\t\t{ threadId: ctx.event.source.threadId },\n\t);\n}\n\nexport async function handleMobileCommand(ctx: MobileContext, command: string, args: string): Promise<boolean> {\n\tif (!MOBILE_COMMANDS.some((c) => c.name === command) && command !== \"resume\") return false;\n\trequireGatewayOwner(ctx.event.source, ctx.cfg);\n\tbindConversation(ctx.key, ctx.event.source, { owner: ctx.event.source.userId });\n\tif (command === \"project\") {\n\t\tawait browseProject(ctx, args.trim() || undefined);\n\t\treturn true;\n\t}\n\tif (command === \"sessions\" || command === \"resume\" || command === \"continue\") {\n\t\tawait browseSessions(ctx, args, command === \"continue\");\n\t\treturn true;\n\t}\n\tconst session = await ctx.bridge.getSession(ctx.key);\n\tif (!session) throw new Error(\"Select a project and send a task, or use /continue first.\");\n\tconst id = session.sessionManager?.getSessionId();\n\tif (command === \"usage\") {\n\t\tconst stats = session.getSessionStats();\n\t\tconst plans = await (await import(\"../core/usage-service.ts\")).getAllPlanUsageResults(\n\t\t\tsession.model?.provider,\n\t\t\tsession.modelRuntime,\n\t\t);\n\t\tawait ctx.adapter.send(\n\t\t\tctx.event.source.chatId,\n\t\t\t[\n\t\t\t\t`Tokens: ${stats.tokens.total} · cost: $${stats.cost.toFixed(4)}`,\n\t\t\t\t...plans.usages.flatMap((p) =>\n\t\t\t\t\tp.windows.map((w) => `${p.provider} ${w.label}: ${w.usedPercent.toFixed(1)}% used`),\n\t\t\t\t),\n\t\t\t\t...plans.errors,\n\t\t\t].join(\"\\n\"),\n\t\t);\n\t\treturn true;\n\t}\n\tif (command === \"processes\") {\n\t\tif (!id) throw new Error(\"No session identity.\");\n\t\tconst processes = await import(\"../core/process-registry.ts\");\n\t\tconst own = processes.list(id);\n\t\tif (args) {\n\t\t\tconst [action, raw] = args.split(/\\s+/);\n\t\t\tconst pid = Number(raw);\n\t\t\tif (action !== \"stop\" || !own.some((p) => p.pid === pid))\n\t\t\t\tthrow new Error(\"Usage: /processes stop <pid> from this session's process list.\");\n\t\t\tprocesses.kill(pid);\n\t\t\tawait ctx.adapter.send(ctx.event.source.chatId, `Stop requested for process ${pid}.`);\n\t\t} else\n\t\t\tawait ctx.adapter.send(\n\t\t\t\tctx.event.source.chatId,\n\t\t\t\town.length\n\t\t\t\t\t? own\n\t\t\t\t\t\t\t.map((p) => `${p.pid} · ${p.status} · ${p.command}`)\n\t\t\t\t\t\t\t.join(\"\\n\")\n\t\t\t\t\t\t\t.slice(0, ctx.adapter.maxMessageLength)\n\t\t\t\t\t: \"No tracked processes.\",\n\t\t\t);\n\t\treturn true;\n\t}\n\tif (command === \"stopall\") {\n\t\tawait ctx.bridge.abort(ctx.key);\n\t\tconst result = id ? await getSubagentCancellation(id)?.stop() : undefined;\n\t\tconst processes = await import(\"../core/process-registry.ts\");\n\t\tconst count = id ? processes.list(id).filter((p) => p.status !== \"exited\").length : 0;\n\t\tif (id) processes.killAll(id);\n\t\tawait ctx.adapter.send(\n\t\t\tctx.event.source.chatId,\n\t\t\t`Stopped the current turn. Requested stop for ${result?.requested ?? 0} background runs and ${count} tracked processes${result?.failed ? `; ${result.failed} requests failed` : \"\"}. Wait for them to exit before transferring.`,\n\t\t);\n\t\treturn true;\n\t}\n\tif (ctx.bridge.getStatus(ctx.key).busy) throw new Error(\"Wait for the current turn or use /stop first.\");\n\tif (command === \"refresh\") {\n\t\tawait session.modelRuntime.refresh();\n\t\tawait ctx.adapter.send(ctx.event.source.chatId, \"Model catalog refreshed. Use /model to choose.\");\n\t\treturn true;\n\t}\n\tif (command === \"fast\") {\n\t\tif (session.model?.provider !== \"openai-codex\" || !session.settingsManager)\n\t\t\tthrow new Error(\"Fast mode is available only for OpenAI Codex subscriptions.\");\n\t\tconst current = session.settingsManager.getOpenAIFastMode();\n\t\tif (args && ![\"on\", \"off\", \"status\"].includes(args)) throw new Error(\"Usage: /fast on|off|status\");\n\t\tif (args !== \"status\") session.settingsManager.setOpenAIFastMode(args ? args === \"on\" : !current);\n\t\tawait ctx.adapter.send(\n\t\t\tctx.event.source.chatId,\n\t\t\t`Fast mode: ${session.settingsManager.getOpenAIFastMode() ? \"on\" : \"off\"}`,\n\t\t);\n\t\treturn true;\n\t}\n\tif (command === \"skill\") {\n\t\tconst names = session.resourceLoader?.getSkills().skills.map((s) => s.name) ?? [];\n\t\tconst [name, ...task] = args.split(/\\s+/).filter(Boolean);\n\t\tconst chosen = name || (await gatewaySelect(ctx.key, \"Choose a skill\", names));\n\t\tif (!chosen) return true;\n\t\tif (!names.includes(chosen)) throw new Error(\"That skill is not loaded for this project.\");\n\t\tctx.event.text = `/skill:${chosen} ${task.join(\" \") || (await gatewayInput(ctx.key, \"What should this skill do?\")) || \"\"}`;\n\t\treturn false;\n\t}\n\tif (command === \"download\") {\n\t\tif (!ctx.adapter.sendFile) throw new Error(\"This platform cannot send files.\");\n\t\tif (!args) throw new Error(\"Usage: /download <project-relative path>\");\n\t\tconst cwd = session.sessionManager?.getCwd();\n\t\tif (!cwd) throw new Error(\"No project selected.\");\n\t\tconst file = resolveWithinRoots(resolve(cwd, args), [cwd]);\n\t\tconst stat = statSync(file);\n\t\tif (!stat.isFile() || stat.size > 8 * 1024 * 1024) throw new Error(\"Choose a file no larger than 8 MB.\");\n\t\tif (\n\t\t\t/(^|[\\\\/])(?:\\.env(?:\\.[^\\\\/]*)?|auth\\.json|gateway\\.json|credentials[^\\\\/]*|id_rsa|id_ed25519)([\\\\/]|$)/i.test(\n\t\t\t\tfile,\n\t\t\t)\n\t\t)\n\t\t\tthrow new Error(\"Credential files cannot be sent through chat.\");\n\t\tconst result = await ctx.adapter.sendFile(ctx.event.source.chatId, file, { threadId: ctx.event.source.threadId });\n\t\tif (!result.success) throw new Error(result.error ?? \"File delivery failed.\");\n\t\treturn true;\n\t}\n\tif (command === \"settings\") {\n\t\tconst choice = await gatewaySelect(ctx.key, \"Session settings\", [\"Model\", \"Thinking\", \"Permissions\"]);\n\t\tif (choice === \"Model\" || choice === \"Thinking\") {\n\t\t\tconst { CHAT_COMMANDS, runChatCommand } = await import(\"./commands.ts\");\n\t\t\tconst cmd = CHAT_COMMANDS.find((c) => c.name === choice.toLowerCase());\n\t\t\tif (cmd)\n\t\t\t\tawait runChatCommand(cmd, {\n\t\t\t\t\t...ctx,\n\t\t\t\t\targs: \"\",\n\t\t\t\t\treply: async (text) => {\n\t\t\t\t\t\tawait ctx.adapter.send(ctx.event.source.chatId, text);\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\treturn true;\n\t\t}\n\t\tif (choice !== \"Permissions\") return true;\n\t}\n\tconst requested =\n\t\tcommand === \"plan\"\n\t\t\t? \"read-only\"\n\t\t\t: args || (await gatewaySelect(ctx.key, `Permission mode: ${getPermissionMode(id)}`, [...PERMISSION_MODES]));\n\tif (!requested) return true;\n\tconst mode = requested === \"read\" ? \"read-only\" : requested;\n\tif (!PERMISSION_MODES.includes(mode as (typeof PERMISSION_MODES)[number]))\n\t\tthrow new Error(\"Choose yolo, auto, or read-only.\");\n\tsetPermissionMode(mode as (typeof PERMISSION_MODES)[number], id);\n\tsession.sessionManager?.setPermissionMode?.(mode as (typeof PERMISSION_MODES)[number]);\n\tawait ctx.adapter.send(ctx.event.source.chatId, `Permission mode: ${mode}`);\n\tif (command === \"plan\" && args) {\n\t\tctx.event.text = `Create a plan for: ${args}`;\n\t\treturn false;\n\t}\n\treturn true;\n}\n"]}
1
+ {"version":3,"file":"mobile-commands.js","sourceRoot":"","sources":["../../src/gateway/mobile-commands.ts"],"names":[],"mappings":"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","sourcesContent":["import { mkdirSync, readdirSync, realpathSync, statSync } from \"node:fs\";\nimport { basename, dirname, isAbsolute, join, relative, resolve } from \"node:path\";\nimport { getPermissionMode, PERMISSION_MODES, setPermissionMode } from \"../core/permissions.ts\";\nimport { SessionManager } from \"../core/session-manager.ts\";\nimport { getSubagentCancellation } from \"../core/subagent-cancellation.ts\";\nimport { isAuthorized, requireAuthorized } from \"./authz.ts\";\nimport { createPicker, type PickerItem, type PickerResolveResult } from \"./buttons.ts\";\nimport { type GatewayConfig, loadGatewayConfig } from \"./config.ts\";\nimport { bindConversation, conversationBinding } from \"./conversations.ts\";\nimport { gatewayInput, gatewaySelect } from \"./presenter.ts\";\nimport type { BridgeLike } from \"./router.ts\";\nimport type { MessageEvent, PlatformAdapter } from \"./types.ts\";\n\nexport const MOBILE_COMMANDS = [\n\t{ name: \"project\", description: \"Browse folders and choose a project\" },\n\t{ name: \"continue\", description: \"Continue a handoff or the latest TUI session\" },\n\t{ name: \"sessions\", description: \"Browse saved sessions across projects\" },\n\t{ name: \"mode\", description: \"Choose yolo, auto, or read-only permissions\" },\n\t{ name: \"plan\", description: \"Plan work and approve it from this chat\" },\n\t{ name: \"settings\", description: \"Change this session's model, thinking, or permissions\" },\n\t{ name: \"stopall\", description: \"Stop this session and its background subagents\" },\n\t{ name: \"download\", description: \"Send a file from the current project\" },\n\t{ name: \"usage\", description: \"Show session tokens and subscription usage\" },\n\t{ name: \"processes\", description: \"List or stop this session's shell processes\" },\n\t{ name: \"refresh\", description: \"Refresh available models\" },\n\t{ name: \"skill\", description: \"Choose a skill and send it a task\" },\n\t{ name: \"fast\", description: \"Toggle OpenAI Codex fast mode\" },\n];\n\nexport const FORWARDED_COMMANDS = [\n\t{ name: \"goal\", description: \"Set or manage the session goal\" },\n\t{ name: \"cron\", description: \"Schedule prompts and manage scheduled jobs\" },\n\t{ name: \"run\", description: \"Launch a subagent task\" },\n\t{ name: \"chain\", description: \"Run a sequence of subagent tasks\" },\n\t{ name: \"parallel\", description: \"Run independent subagent tasks\" },\n\t{ name: \"mcp\", description: \"Show configured MCP servers\" },\n\t{ name: \"lsp\", description: \"Show language server status\" },\n];\n\nexport function resolveWithinRoots(path: string, roots: string[]): string {\n\tconst actual = realpathSync(resolve(path));\n\tif (\n\t\t!roots.some((root) => {\n\t\t\ttry {\n\t\t\t\tconst rel = relative(realpathSync(root), actual);\n\t\t\t\treturn (\n\t\t\t\t\trel === \"\" ||\n\t\t\t\t\t(!rel.startsWith(`..${process.platform === \"win32\" ? \"\\\\\" : \"/\"}`) && rel !== \"..\" && !isAbsolute(rel))\n\t\t\t\t);\n\t\t\t} catch {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t})\n\t)\n\t\tthrow new Error(\"That path is outside the approved folders.\");\n\treturn actual;\n}\n\nexport function createProjectFolder(parent: string, name: string, roots: string[]): string {\n\tif (\n\t\t!name ||\n\t\tname === \".\" ||\n\t\tname === \"..\" ||\n\t\t/[\\\\/\\x00-\\x1f<>:\"|?*]/.test(name) ||\n\t\t/[. ]$/.test(name) ||\n\t\t/^(con|prn|aux|nul|com\\d|lpt\\d)(\\.|$)/i.test(name)\n\t)\n\t\tthrow new Error(\"Use a simple folder name without slashes or reserved characters.\");\n\tconst actual = resolveWithinRoots(parent, roots);\n\tmkdirSync(join(actual, name));\n\treturn resolveWithinRoots(join(actual, name), roots);\n}\n\ninterface MobileContext {\n\tkey: string;\n\tevent: MessageEvent;\n\tadapter: PlatformAdapter;\n\tbridge: BridgeLike;\n\tcfg: GatewayConfig;\n}\n\nasync function browseProject(ctx: MobileContext, initialPath?: string): Promise<void> {\n\tconst { key, event, adapter, bridge } = ctx;\n\tconst roots = ctx.cfg.projectRoots ?? [];\n\tif (!roots.length) throw new Error(\"Add approved project folders with lunr gateway setup first.\");\n\tlet current: string | undefined = initialPath\n\t\t? resolveWithinRoots(initialPath, ctx.cfg.projectRoots ?? [])\n\t\t: undefined;\n\tconst view = (): { title: string; items: PickerItem[] } => {\n\t\tif (!current)\n\t\t\treturn {\n\t\t\t\ttitle: \"Choose a project folder\",\n\t\t\t\titems: [...new Set([...(conversationBinding(key)?.recentProjects ?? []), ...roots])]\n\t\t\t\t\t.filter((p) => {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tresolveWithinRoots(p, roots);\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t})\n\t\t\t\t\t.map((p) => ({ label: p, value: p })),\n\t\t\t};\n\t\tcurrent = resolveWithinRoots(current, roots);\n\t\tconst items: PickerItem[] = [\n\t\t\t{ label: \"Use this folder\", value: \"use\" },\n\t\t\t{ label: \"New folder\", value: \"new\" },\n\t\t\t{ label: \"Recent and roots\", value: \"roots\" },\n\t\t];\n\t\ttry {\n\t\t\tconst up = resolveWithinRoots(dirname(current), roots);\n\t\t\tif (up !== current) items.push({ label: \"Up\", value: up });\n\t\t} catch {}\n\t\tfor (const item of readdirSync(current, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {\n\t\t\tif (!item.isDirectory() && !item.isSymbolicLink()) continue;\n\t\t\ttry {\n\t\t\t\tconst path = resolveWithinRoots(join(current, item.name), roots);\n\t\t\t\tif (statSync(path).isDirectory()) items.push({ label: item.name, value: path });\n\t\t\t} catch {}\n\t\t}\n\t\treturn { title: current, items };\n\t};\n\tconst initial = view();\n\tawait createPicker(\n\t\tadapter,\n\t\tevent.source,\n\t\t{\n\t\t\tkind: \"project\",\n\t\t\tsessionKey: key,\n\t\t\tinvokerId: event.source.userId,\n\t\t\t...initial,\n\t\t\tvalidate: () => isAuthorized(event.source, loadGatewayConfig()),\n\t\t\tresolve: async (item): Promise<PickerResolveResult> => {\n\t\t\t\trequireAuthorized(event.source);\n\t\t\t\tif (item.value === \"use\" && current) {\n\t\t\t\t\tconst cwd = resolveWithinRoots(current, loadGatewayConfig().projectRoots ?? []);\n\t\t\t\t\tif (bridge.getStatus(key).busy)\n\t\t\t\t\t\tthrow new Error(\"Stop the current turn or wait before switching projects.\");\n\t\t\t\t\tawait bridge.reset(key);\n\t\t\t\t\tbindConversation(key, event.source, { cwd, owner: event.source.userId });\n\t\t\t\t\treturn {\n\t\t\t\t\t\tdone: true,\n\t\t\t\t\t\ttext: `Project selected: ${cwd}\\nSend a task to begin. Existing sessions are still available through /sessions.`,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tif (item.value === \"new\" && current) {\n\t\t\t\t\tconst name = await gatewayInput(key, \"New folder name\");\n\t\t\t\t\tif (name) current = createProjectFolder(current, name, loadGatewayConfig().projectRoots ?? []);\n\t\t\t\t} else current = item.value === \"roots\" ? undefined : item.value;\n\t\t\t\treturn { done: false, ...view() };\n\t\t\t},\n\t\t},\n\t\t{ threadId: event.source.threadId },\n\t);\n}\n\nconst transfers = new Map<string, AbortController>();\nexport function cancelMobileTransfer(key: string): void {\n\ttransfers.get(key)?.abort();\n}\n\nasync function continueSession(ctx: MobileContext, file: string): Promise<void> {\n\tif (transfers.has(ctx.key)) throw new Error(\"A session transfer is already pending. Use /stop to cancel it.\");\n\tconst controller = new AbortController();\n\ttransfers.set(ctx.key, controller);\n\ttry {\n\t\tawait performContinue(ctx, file, controller.signal);\n\t} finally {\n\t\ttransfers.delete(ctx.key);\n\t}\n}\n\nasync function performContinue(ctx: MobileContext, file: string, signal: AbortSignal): Promise<void> {\n\trequireAuthorized(ctx.event.source);\n\tconst { requestSessionTransfer, SessionTransferError } = await import(\"../core/session-handoff.ts\");\n\tconst { key, bridge } = ctx;\n\tconst current = bridge.peekSession?.(key);\n\tif (current?.sessionManager?.getSessionFile() === file) {\n\t\tawait ctx.adapter.send(ctx.event.source.chatId, \"This session is already open here.\");\n\t\treturn;\n\t}\n\tif (bridge.getStatus(key).busy) throw new Error(\"Stop the current phone session before switching.\");\n\ttry {\n\t\tawait requestSessionTransfer(file, { timeoutMs: 3000, signal });\n\t} catch (error) {\n\t\tif (!(error instanceof SessionTransferError) || ![\"busy\", \"timeout\"].includes(error.code)) throw error;\n\t\tconst choice = await gatewaySelect(\n\t\t\tkey,\n\t\t\t`${error instanceof Error ? error.message : \"Session is in use\"}\\nHow should lunR continue?`,\n\t\t\t[\"Wait until idle\", \"Stop and continue\", \"Cancel\"],\n\t\t\t{ signal },\n\t\t);\n\t\tif (!choice || choice === \"Cancel\") return;\n\t\tif (choice === \"Stop and continue\") await requestSessionTransfer(file, { stop: true, timeoutMs: 30_000, signal });\n\t\telse {\n\t\t\tconst deadline = Date.now() + 120_000;\n\t\t\tfor (;;) {\n\t\t\t\tsignal.throwIfAborted();\n\t\t\t\trequireAuthorized(ctx.event.source);\n\t\t\t\ttry {\n\t\t\t\t\tawait requestSessionTransfer(file, { timeoutMs: 3000, signal });\n\t\t\t\t\tbreak;\n\t\t\t\t} catch (retryError) {\n\t\t\t\t\tif (\n\t\t\t\t\t\t!(retryError instanceof SessionTransferError) ||\n\t\t\t\t\t\t![\"busy\", \"timeout\"].includes(retryError.code) ||\n\t\t\t\t\t\tDate.now() >= deadline\n\t\t\t\t\t)\n\t\t\t\t\t\tthrow retryError;\n\t\t\t\t}\n\t\t\t\tawait new Promise((resolve) => setTimeout(resolve, 500));\n\t\t\t}\n\t\t}\n\t}\n\tsignal.throwIfAborted();\n\trequireAuthorized(ctx.event.source);\n\tawait bridge.switchSession(key, file);\n\tconst session = await bridge.getSession(key);\n\tconst cwd = session?.sessionManager?.getCwd();\n\tbindConversation(key, ctx.event.source, { cwd, owner: ctx.event.source.userId });\n\tconst id = session?.sessionManager?.getSessionId();\n\tif (id && [\"auto\", \"yolo\"].includes(getPermissionMode(id))) {\n\t\tconst requested = getPermissionMode(id);\n\t\tsetPermissionMode(\"read-only\", id);\n\t\tsession?.sessionManager?.setPermissionMode?.(\"read-only\");\n\t\tif (\n\t\t\t(await gatewaySelect(\n\t\t\t\tkey,\n\t\t\t\t`Continue with ${requested} permissions? Tools can change files and run commands without individual approval.`,\n\t\t\t\t[\"Keep read-only\", `Use ${requested}`],\n\t\t\t)) === `Use ${requested}`\n\t\t) {\n\t\t\tsetPermissionMode(requested, id);\n\t\t\tsession?.sessionManager?.setPermissionMode?.(requested);\n\t\t}\n\t}\n\tawait ctx.adapter.send(\n\t\tctx.event.source.chatId,\n\t\t`Continuing ${session?.sessionManager?.getSessionName() ?? basename(file)}\\nProject: ${cwd}\\nSend your next instruction.`,\n\t\t{ threadId: ctx.event.source.threadId },\n\t);\n}\n\nasync function browseSessions(ctx: MobileContext, args: string, quick: boolean): Promise<void> {\n\tconst handoff = await import(\"../core/session-handoff.ts\");\n\tif (quick) {\n\t\tconst candidates = handoff.listHandoffCandidates();\n\t\tif (!candidates.length) {\n\t\t\tconst latest = handoff.latestTuiSession();\n\t\t\tif (!latest)\n\t\t\t\tthrow new Error(\"No recent TUI session found. Use /sessions or mark one in the terminal with /handoff.\");\n\t\t\tawait continueSession(ctx, latest.sessionFile);\n\t\t\treturn;\n\t\t}\n\t\tif (candidates.length === 1) {\n\t\t\tawait continueSession(ctx, candidates[0].sessionFile);\n\t\t\treturn;\n\t\t}\n\t\tawait sessionPicker(\n\t\t\tctx,\n\t\t\tcandidates.map((s) => ({ label: `${s.cwd} · ${basename(s.sessionFile)}`, value: s.sessionFile })),\n\t\t);\n\t\treturn;\n\t}\n\tconst sessions = await SessionManager.listAll();\n\tconst known = new Set(sessions.map((s) => s.path));\n\tfor (const file of handoff.listRegisteredSessionPaths()) {\n\t\tif (known.has(file)) continue;\n\t\ttry {\n\t\t\tconst manager = SessionManager.openReadOnly(file);\n\t\t\tconst header = manager.getHeader();\n\t\t\tif (header)\n\t\t\t\tsessions.push({\n\t\t\t\t\tid: header.id,\n\t\t\t\t\tpath: file,\n\t\t\t\t\tcwd: manager.getCwd(),\n\t\t\t\t\tname: manager.getSessionName(),\n\t\t\t\t\tcreated: new Date(header.timestamp),\n\t\t\t\t\tmodified: statSync(file).mtime,\n\t\t\t\t\tmessageCount: manager.getEntries().length,\n\t\t\t\t\tfirstMessage: \"\",\n\t\t\t\t\tallMessagesText: \"\",\n\t\t\t\t});\n\t\t} catch {}\n\t}\n\tconst query = args.toLowerCase();\n\tconst items = sessions\n\t\t.sort((a, b) => b.modified.getTime() - a.modified.getTime())\n\t\t.filter((s) => !query || `${s.name ?? \"\"} ${s.cwd} ${s.id}`.toLowerCase().includes(query))\n\t\t.map((s) => ({\n\t\t\tlabel: `${s.name || s.firstMessage.slice(0, 35) || s.id.slice(0, 8)} · ${basename(s.cwd)} · ${s.modified.toLocaleDateString()}`,\n\t\t\tvalue: s.path,\n\t\t}));\n\tawait sessionPicker(ctx, items);\n}\n\nasync function sessionPicker(ctx: MobileContext, items: PickerItem[]): Promise<void> {\n\tawait createPicker(\n\t\tctx.adapter,\n\t\tctx.event.source,\n\t\t{\n\t\t\tkind: \"sessions\",\n\t\t\tsessionKey: ctx.key,\n\t\t\tinvokerId: ctx.event.source.userId,\n\t\t\ttitle: \"Choose a session. Use /sessions <search> to filter.\",\n\t\t\titems,\n\t\t\tvalidate: () => isAuthorized(ctx.event.source, loadGatewayConfig()),\n\t\t\tresolve: async (item) => {\n\t\t\t\tawait continueSession(ctx, item.value);\n\t\t\t\treturn { done: true, text: \"Session selection finished.\" };\n\t\t\t},\n\t\t},\n\t\t{ threadId: ctx.event.source.threadId },\n\t);\n}\n\nexport async function handleMobileCommand(ctx: MobileContext, command: string, args: string): Promise<boolean> {\n\tif (!MOBILE_COMMANDS.some((c) => c.name === command) && command !== \"resume\") return false;\n\trequireAuthorized(ctx.event.source, ctx.cfg);\n\tbindConversation(ctx.key, ctx.event.source, { owner: ctx.event.source.userId });\n\tif (command === \"project\") {\n\t\tawait browseProject(ctx, args.trim() || undefined);\n\t\treturn true;\n\t}\n\tif (command === \"sessions\" || command === \"resume\" || command === \"continue\") {\n\t\tawait browseSessions(ctx, args, command === \"continue\");\n\t\treturn true;\n\t}\n\tconst session = await ctx.bridge.getSession(ctx.key);\n\tif (!session) throw new Error(\"Select a project and send a task, or use /continue first.\");\n\tconst id = session.sessionManager?.getSessionId();\n\tif (command === \"usage\") {\n\t\tconst stats = session.getSessionStats();\n\t\tconst plans = await (await import(\"../core/usage-service.ts\")).getAllPlanUsageResults(\n\t\t\tsession.model?.provider,\n\t\t\tsession.modelRuntime,\n\t\t);\n\t\tawait ctx.adapter.send(\n\t\t\tctx.event.source.chatId,\n\t\t\t[\n\t\t\t\t`Tokens: ${stats.tokens.total} · cost: $${stats.cost.toFixed(4)}`,\n\t\t\t\t...plans.usages.flatMap((p) =>\n\t\t\t\t\tp.windows.map((w) => `${p.provider} ${w.label}: ${w.usedPercent.toFixed(1)}% used`),\n\t\t\t\t),\n\t\t\t\t...plans.errors,\n\t\t\t].join(\"\\n\"),\n\t\t);\n\t\treturn true;\n\t}\n\tif (command === \"processes\") {\n\t\tif (!id) throw new Error(\"No session identity.\");\n\t\tconst processes = await import(\"../core/process-registry.ts\");\n\t\tconst own = processes.list(id);\n\t\tif (args) {\n\t\t\tconst [action, raw] = args.split(/\\s+/);\n\t\t\tconst pid = Number(raw);\n\t\t\tif (action !== \"stop\" || !own.some((p) => p.pid === pid))\n\t\t\t\tthrow new Error(\"Usage: /processes stop <pid> from this session's process list.\");\n\t\t\tprocesses.kill(pid);\n\t\t\tawait ctx.adapter.send(ctx.event.source.chatId, `Stop requested for process ${pid}.`);\n\t\t} else\n\t\t\tawait ctx.adapter.send(\n\t\t\t\tctx.event.source.chatId,\n\t\t\t\town.length\n\t\t\t\t\t? own\n\t\t\t\t\t\t\t.map((p) => `${p.pid} · ${p.status} · ${p.command}`)\n\t\t\t\t\t\t\t.join(\"\\n\")\n\t\t\t\t\t\t\t.slice(0, ctx.adapter.maxMessageLength)\n\t\t\t\t\t: \"No tracked processes.\",\n\t\t\t);\n\t\treturn true;\n\t}\n\tif (command === \"stopall\") {\n\t\tawait ctx.bridge.abort(ctx.key);\n\t\tconst result = id ? await getSubagentCancellation(id)?.stop() : undefined;\n\t\tconst processes = await import(\"../core/process-registry.ts\");\n\t\tconst count = id ? processes.list(id).filter((p) => p.status !== \"exited\").length : 0;\n\t\tif (id) processes.killAll(id);\n\t\tawait ctx.adapter.send(\n\t\t\tctx.event.source.chatId,\n\t\t\t`Stopped the current turn. Requested stop for ${result?.requested ?? 0} background runs and ${count} tracked processes${result?.failed ? `; ${result.failed} requests failed` : \"\"}. Wait for them to exit before transferring.`,\n\t\t);\n\t\treturn true;\n\t}\n\tif (ctx.bridge.getStatus(ctx.key).busy) throw new Error(\"Wait for the current turn or use /stop first.\");\n\tif (command === \"refresh\") {\n\t\tawait session.modelRuntime.refresh();\n\t\tawait ctx.adapter.send(ctx.event.source.chatId, \"Model catalog refreshed. Use /model to choose.\");\n\t\treturn true;\n\t}\n\tif (command === \"fast\") {\n\t\tif (session.model?.provider !== \"openai-codex\" || !session.settingsManager)\n\t\t\tthrow new Error(\"Fast mode is available only for OpenAI Codex subscriptions.\");\n\t\tconst current = session.settingsManager.getOpenAIFastMode();\n\t\tif (args && ![\"on\", \"off\", \"status\"].includes(args)) throw new Error(\"Usage: /fast on|off|status\");\n\t\tif (args !== \"status\") session.settingsManager.setOpenAIFastMode(args ? args === \"on\" : !current);\n\t\tawait ctx.adapter.send(\n\t\t\tctx.event.source.chatId,\n\t\t\t`Fast mode: ${session.settingsManager.getOpenAIFastMode() ? \"on\" : \"off\"}`,\n\t\t);\n\t\treturn true;\n\t}\n\tif (command === \"skill\") {\n\t\tconst names = session.resourceLoader?.getSkills().skills.map((s) => s.name) ?? [];\n\t\tconst [name, ...task] = args.split(/\\s+/).filter(Boolean);\n\t\tconst chosen = name || (await gatewaySelect(ctx.key, \"Choose a skill\", names));\n\t\tif (!chosen) return true;\n\t\tif (!names.includes(chosen)) throw new Error(\"That skill is not loaded for this project.\");\n\t\tctx.event.text = `/skill:${chosen} ${task.join(\" \") || (await gatewayInput(ctx.key, \"What should this skill do?\")) || \"\"}`;\n\t\treturn false;\n\t}\n\tif (command === \"download\") {\n\t\tif (!ctx.adapter.sendFile) throw new Error(\"This platform cannot send files.\");\n\t\tif (!args) throw new Error(\"Usage: /download <project-relative path>\");\n\t\tconst cwd = session.sessionManager?.getCwd();\n\t\tif (!cwd) throw new Error(\"No project selected.\");\n\t\tconst file = resolveWithinRoots(resolve(cwd, args), [cwd]);\n\t\tconst stat = statSync(file);\n\t\tif (!stat.isFile() || stat.size > 8 * 1024 * 1024) throw new Error(\"Choose a file no larger than 8 MB.\");\n\t\tif (\n\t\t\t/(^|[\\\\/])(?:\\.env(?:\\.[^\\\\/]*)?|auth\\.json|gateway\\.json|credentials[^\\\\/]*|id_rsa|id_ed25519)([\\\\/]|$)/i.test(\n\t\t\t\tfile,\n\t\t\t)\n\t\t)\n\t\t\tthrow new Error(\"Credential files cannot be sent through chat.\");\n\t\tconst result = await ctx.adapter.sendFile(ctx.event.source.chatId, file, { threadId: ctx.event.source.threadId });\n\t\tif (!result.success) throw new Error(result.error ?? \"File delivery failed.\");\n\t\treturn true;\n\t}\n\tif (command === \"settings\") {\n\t\tconst choice = await gatewaySelect(ctx.key, \"Session settings\", [\"Model\", \"Thinking\", \"Permissions\"]);\n\t\tif (choice === \"Model\" || choice === \"Thinking\") {\n\t\t\tconst { CHAT_COMMANDS, runChatCommand } = await import(\"./commands.ts\");\n\t\t\tconst cmd = CHAT_COMMANDS.find((c) => c.name === choice.toLowerCase());\n\t\t\tif (cmd)\n\t\t\t\tawait runChatCommand(cmd, {\n\t\t\t\t\t...ctx,\n\t\t\t\t\targs: \"\",\n\t\t\t\t\treply: async (text) => {\n\t\t\t\t\t\tawait ctx.adapter.send(ctx.event.source.chatId, text);\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\treturn true;\n\t\t}\n\t\tif (choice !== \"Permissions\") return true;\n\t}\n\tconst requested =\n\t\tcommand === \"plan\"\n\t\t\t? \"read-only\"\n\t\t\t: args || (await gatewaySelect(ctx.key, `Permission mode: ${getPermissionMode(id)}`, [...PERMISSION_MODES]));\n\tif (!requested) return true;\n\tconst mode = requested === \"read\" ? \"read-only\" : requested;\n\tif (!PERMISSION_MODES.includes(mode as (typeof PERMISSION_MODES)[number]))\n\t\tthrow new Error(\"Choose yolo, auto, or read-only.\");\n\tsetPermissionMode(mode as (typeof PERMISSION_MODES)[number], id);\n\tsession.sessionManager?.setPermissionMode?.(mode as (typeof PERMISSION_MODES)[number]);\n\tawait ctx.adapter.send(ctx.event.source.chatId, `Permission mode: ${mode}`);\n\tif (command === \"plan\" && args) {\n\t\tctx.event.text = `Create a plan for: ${args}`;\n\t\treturn false;\n\t}\n\treturn true;\n}\n"]}
@@ -1,5 +1,7 @@
1
1
  import type { ExtensionUIContext, ExtensionUIDialogOptions } from "../core/extensions/types.ts";
2
+ import { type GatewayConfig } from "./config.ts";
2
3
  import type { MessageEvent, PlatformAdapter } from "./types.ts";
4
+ export declare function rememberGatewayRole(key: string, source: MessageEvent["source"]): void;
3
5
  export declare function gatewayDestination(key: string): {
4
6
  adapter: PlatformAdapter;
5
7
  source: MessageEvent["source"];
@@ -7,7 +9,16 @@ export declare function gatewayDestination(key: string): {
7
9
  export declare function withGatewayPresentation<T>(key: string, run: () => Promise<T>): Promise<T>;
8
10
  export declare function startGatewayPresenter(connected: Map<string, PlatformAdapter>): void;
9
11
  export declare function stopGatewayPresenter(): void;
10
- export declare function sendGatewayNotice(key: string, text: string): Promise<void>;
12
+ export declare function gatewayEpoch(key: string): number;
13
+ export declare function sendGatewayNotice(key: string, text: string, kind?: "notice" | "result", epoch?: number): Promise<void>;
14
+ export declare function queueGatewayText(key: string, source: MessageEvent["source"], adapter: PlatformAdapter, text: string, options: {
15
+ kind: "result" | "notice";
16
+ replyTo?: string;
17
+ cfg?: GatewayConfig;
18
+ chunks?: string[];
19
+ epoch?: number;
20
+ }): Promise<void>;
21
+ export declare function flushGatewayOutbox(): Promise<void>;
11
22
  export declare function invalidateGatewayDialogs(key: string): void;
12
23
  export declare function acceptGatewayInput(key: string, event: MessageEvent): boolean;
13
24
  export declare function gatewaySelect(key: string, title: string, options: string[], opts?: ExtensionUIDialogOptions): Promise<string | undefined>;
@@ -1 +1 @@
1
- {"version":3,"file":"presenter.d.ts","sourceRoot":"","sources":["../../src/gateway/presenter.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,kBAAkB,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AAShG,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAyBhE,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,eAAe,CAAC;IAAC,MAAM,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAA;CAAE,CAM5G;AAED,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAGzF;AAED,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,GAAG,IAAI,CAenF;AAED,wBAAgB,oBAAoB,IAAI,IAAI,CAK3C;AAED,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAQhF;AA+BD,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAK1D;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAM5E;AAqCD,wBAAgB,aAAa,CAC5B,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EAAE,EACjB,IAAI,CAAC,EAAE,wBAAwB,GAC7B,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAuB7B;AAED,wBAAgB,YAAY,CAC3B,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,WAAW,CAAC,EAAE,MAAM,EACpB,IAAI,CAAC,EAAE,wBAAwB,GAC7B,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAO7B;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,kBAAkB,CAuB/D","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { getAgentDir } from \"../config.ts\";\nimport { noOpUIContext } from \"../core/extensions/runner.ts\";\nimport type { ExtensionUIContext, ExtensionUIDialogOptions } from \"../core/extensions/types.ts\";\nimport { runWithApprovalContext } from \"./approval.ts\";\nimport { isAuthorized, isGatewayOwner } from \"./authz.ts\";\nimport { createPicker } from \"./buttons.ts\";\nimport { loadGatewayConfig } from \"./config.ts\";\nimport { conversationBinding } from \"./conversations.ts\";\nimport { createPairingStore } from \"./pairing.ts\";\nimport { atomicJson } from \"./service.ts\";\nimport { splitMessage } from \"./text.ts\";\nimport type { MessageEvent, PlatformAdapter } from \"./types.ts\";\n\nconst epochs = new Map<string, number>();\nconst inputs = new Map<string, { userId: string; resolve: (value: string | undefined) => void }>();\nconst dialogs = new Map<string, Set<() => void>>();\nlet adapters = new Map<string, PlatformAdapter>();\nlet timer: ReturnType<typeof setInterval> | undefined;\nlet sending = false;\ninterface Outbound {\n\tid: string;\n\tkey: string;\n\tepoch: number;\n\ttext: string;\n}\nconst path = () => join(getAgentDir(), \"gateway-outbox.json\");\nlet outbox: Outbound[] = [];\n\nfunction canDeliver(key: string): boolean {\n\tconst binding = conversationBinding(key);\n\tif (!binding) return false;\n\tconst cfg = loadGatewayConfig();\n\tif (binding.owner && (binding.owner !== binding.source.userId || !isGatewayOwner(binding.source, cfg))) return false;\n\treturn isAuthorized(binding.source, cfg, createPairingStore());\n}\n\nexport function gatewayDestination(key: string): { adapter: PlatformAdapter; source: MessageEvent[\"source\"] } {\n\tconst binding = conversationBinding(key);\n\tconst adapter = binding && adapters.get(binding.source.platform);\n\tif (!binding || !adapter || !canDeliver(key))\n\t\tthrow new Error(\"This chat is no longer authorized or its platform is disconnected.\");\n\treturn { adapter, source: binding.source };\n}\n\nexport function withGatewayPresentation<T>(key: string, run: () => Promise<T>): Promise<T> {\n\tconst { adapter, source } = gatewayDestination(key);\n\treturn runWithApprovalContext({ adapter, source, key }, run);\n}\n\nexport function startGatewayPresenter(connected: Map<string, PlatformAdapter>): void {\n\tadapters = connected;\n\tif (existsSync(path())) {\n\t\ttry {\n\t\t\toutbox = JSON.parse(readFileSync(path(), \"utf8\")) as Outbound[];\n\t\t} catch {\n\t\t\tthrow new Error(\"Gateway outbox is invalid. Restore it before starting.\");\n\t\t}\n\t}\n\tif (timer) clearInterval(timer);\n\ttimer = setInterval(() => {\n\t\tvoid flushOutbox();\n\t}, 3000);\n\ttimer.unref();\n\tvoid flushOutbox();\n}\n\nexport function stopGatewayPresenter(): void {\n\tif (timer) clearInterval(timer);\n\ttimer = undefined;\n\tfor (const key of dialogs.keys()) invalidateGatewayDialogs(key);\n\tadapters = new Map();\n}\n\nexport async function sendGatewayNotice(key: string, text: string): Promise<void> {\n\tconst clean = text.replace(/\\x1b\\[[0-9;]*[a-zA-Z]/g, \"\").trim();\n\tif (!clean || !canDeliver(key)) return;\n\tconst { adapter } = gatewayDestination(key);\n\tfor (const chunk of splitMessage(clean, adapter.maxMessageLength))\n\t\toutbox.push({ id: randomUUID(), key, epoch: epochs.get(key) ?? 0, text: chunk });\n\tatomicJson(path(), outbox);\n\tawait flushOutbox();\n}\n\nasync function flushOutbox(): Promise<void> {\n\tif (sending) return;\n\tsending = true;\n\ttry {\n\t\tfor (const item of [...outbox]) {\n\t\t\tif (!canDeliver(item.key)) {\n\t\t\t\toutbox = outbox.filter((v) => v.id !== item.id);\n\t\t\t\tatomicJson(path(), outbox);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tlet target: ReturnType<typeof gatewayDestination>;\n\t\t\ttry {\n\t\t\t\ttarget = gatewayDestination(item.key);\n\t\t\t} catch {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst result = await target.adapter\n\t\t\t\t.send(target.source.chatId, item.text, { threadId: target.source.threadId })\n\t\t\t\t.catch(() => ({ success: false }));\n\t\t\tif (result.success) {\n\t\t\t\toutbox = outbox.filter((v) => v.id !== item.id);\n\t\t\t\tatomicJson(path(), outbox);\n\t\t\t} else break;\n\t\t}\n\t} finally {\n\t\tsending = false;\n\t}\n}\n\nexport function invalidateGatewayDialogs(key: string): void {\n\tepochs.set(key, (epochs.get(key) ?? 0) + 1);\n\tfor (const cancel of dialogs.get(key) ?? []) cancel();\n\tdialogs.delete(key);\n\tinputs.delete(key);\n}\n\nexport function acceptGatewayInput(key: string, event: MessageEvent): boolean {\n\tconst input = inputs.get(key);\n\tif (!input || input.userId !== event.source.userId || !canDeliver(key)) return false;\n\tif (event.text.startsWith(\"/\") && event.text !== \"/cancel\") return false;\n\tinput.resolve(event.text === \"/cancel\" ? undefined : event.text);\n\treturn true;\n}\n\nfunction dialog(\n\tkey: string,\n\topts: ExtensionUIDialogOptions | undefined,\n\tshow: (done: (value: string | undefined) => void, valid: () => boolean) => Promise<void>,\n): Promise<string | undefined> {\n\tconst epoch = epochs.get(key) ?? 0;\n\treturn new Promise((resolve, reject) => {\n\t\tlet settled = false;\n\t\tconst finish = (value: string | undefined, error?: unknown) => {\n\t\t\tif (settled) return;\n\t\t\tsettled = true;\n\t\t\tclearTimeout(timeout);\n\t\t\topts?.signal?.removeEventListener(\"abort\", cancel);\n\t\t\tinputs.delete(key);\n\t\t\tdialogs.get(key)?.delete(cancel);\n\t\t\tif (error !== undefined) reject(error);\n\t\t\telse resolve(value);\n\t\t};\n\t\tconst done = (value: string | undefined) => finish(value);\n\t\tconst cancel = () => done(undefined);\n\t\tconst timeout = setTimeout(cancel, opts?.timeout ?? 300_000);\n\t\tconst set = dialogs.get(key) ?? new Set();\n\t\tset.add(cancel);\n\t\tdialogs.set(key, set);\n\t\topts?.signal?.addEventListener(\"abort\", cancel, { once: true });\n\t\tif (opts?.signal?.aborted) {\n\t\t\tcancel();\n\t\t\treturn;\n\t\t}\n\t\tvoid show(done, () => !settled && (epochs.get(key) ?? 0) === epoch && canDeliver(key)).catch((error) => {\n\t\t\tfinish(undefined, error);\n\t\t});\n\t});\n}\n\nexport function gatewaySelect(\n\tkey: string,\n\ttitle: string,\n\toptions: string[],\n\topts?: ExtensionUIDialogOptions,\n): Promise<string | undefined> {\n\treturn dialog(key, opts, async (done, valid) => {\n\t\tconst { adapter, source } = gatewayDestination(key);\n\t\tconst result = await createPicker(\n\t\t\tadapter,\n\t\t\tsource,\n\t\t\t{\n\t\t\t\tkind: \"dialog\",\n\t\t\t\tsessionKey: key,\n\t\t\t\tinvokerId: source.userId,\n\t\t\t\ttitle,\n\t\t\t\titems: options.map((value) => ({ label: value, value })),\n\t\t\t\tvalidate: valid,\n\t\t\t\tonCancel: () => done(undefined),\n\t\t\t\tresolve: async (item) => {\n\t\t\t\t\tdone(item.value);\n\t\t\t\t\treturn { done: true, text: `${title}\\n${item.value}` };\n\t\t\t\t},\n\t\t\t},\n\t\t\t{ threadId: source.threadId },\n\t\t);\n\t\tif (!result.success) throw new Error(result.error ?? \"Could not send picker.\");\n\t});\n}\n\nexport function gatewayInput(\n\tkey: string,\n\ttitle: string,\n\tplaceholder?: string,\n\topts?: ExtensionUIDialogOptions,\n): Promise<string | undefined> {\n\tif (inputs.has(key)) return Promise.reject(new Error(\"Answer or cancel the existing question first.\"));\n\treturn dialog(key, opts, async (done) => {\n\t\tconst { source } = gatewayDestination(key);\n\t\tinputs.set(key, { userId: source.userId, resolve: done });\n\t\tawait sendGatewayNotice(key, `${title}${placeholder ? `\\n${placeholder}` : \"\"}\\nReply with text, or /cancel.`);\n\t});\n}\n\nexport function createGatewayUI(key: string): ExtensionUIContext {\n\treturn {\n\t\t...noOpUIContext,\n\t\tselect: (title, options, opts) => gatewaySelect(key, title, options, opts),\n\t\tconfirm: async (title, message, opts) =>\n\t\t\t(await gatewaySelect(key, `${title}\\n${message}`, [\"Approve\", \"Decline\"], opts)) === \"Approve\",\n\t\tinput: (title, placeholder, opts) => gatewayInput(key, title, placeholder, opts),\n\t\teditor: (title, prefill) => gatewayInput(key, title, prefill),\n\t\tnotify: (message) => {\n\t\t\tvoid sendGatewayNotice(key, message).catch(() => {});\n\t\t},\n\t\tcustom: async () => {\n\t\t\tthrow new Error(\n\t\t\t\t\"This command requires the terminal interface. Use the gateway's text commands or button pickers.\",\n\t\t\t);\n\t\t},\n\t\tpasteToEditor: (text) => {\n\t\t\tvoid sendGatewayNotice(key, text).catch(() => {});\n\t\t},\n\t\tsetEditorText: (text) => {\n\t\t\tvoid sendGatewayNotice(key, text).catch(() => {});\n\t\t},\n\t};\n}\n"]}
1
+ {"version":3,"file":"presenter.d.ts","sourceRoot":"","sources":["../../src/gateway/presenter.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,kBAAkB,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AAIhG,OAAO,EAAE,KAAK,aAAa,EAAwC,MAAM,aAAa,CAAC;AAKvF,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAe,MAAM,YAAY,CAAC;AAoC7E,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,CAAC,QAAQ,CAAC,GAAG,IAAI,CAIrF;AAUD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,eAAe,CAAC;IAAC,MAAM,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAA;CAAE,CAM5G;AAED,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAGzF;AAED,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,GAAG,IAAI,CA2BnF;AAED,wBAAgB,oBAAoB,IAAI,IAAI,CAO3C;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,wBAAsB,iBAAiB,CACtC,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EACZ,IAAI,GAAE,QAAQ,GAAG,QAAmB,EACpC,KAAK,SAAoB,GACvB,OAAO,CAAC,IAAI,CAAC,CAKf;AAED,wBAAsB,gBAAgB,CACrC,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,YAAY,CAAC,QAAQ,CAAC,EAC9B,OAAO,EAAE,eAAe,EACxB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE;IAAE,IAAI,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,aAAa,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAC9G,OAAO,CAAC,IAAI,CAAC,CAqBf;AAED,wBAAgB,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC,CAElD;AAsED,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAU1D;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAM5E;AAqCD,wBAAgB,aAAa,CAC5B,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EAAE,EACjB,IAAI,CAAC,EAAE,wBAAwB,GAC7B,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAuB7B;AAED,wBAAgB,YAAY,CAC3B,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,WAAW,CAAC,EAAE,MAAM,EACpB,IAAI,CAAC,EAAE,wBAAwB,GAC7B,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAa7B;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,kBAAkB,CA4B/D","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { getAgentDir } from \"../config.ts\";\nimport { noOpUIContext } from \"../core/extensions/runner.ts\";\nimport type { ExtensionUIContext, ExtensionUIDialogOptions } from \"../core/extensions/types.ts\";\nimport { runWithApprovalContext } from \"./approval.ts\";\nimport { isAuthorized } from \"./authz.ts\";\nimport { createPicker } from \"./buttons.ts\";\nimport { type GatewayConfig, gatewayConfigPath, loadGatewayConfig } from \"./config.ts\";\nimport { conversationBinding } from \"./conversations.ts\";\nimport { createPairingStore } from \"./pairing.ts\";\nimport { atomicJson } from \"./service.ts\";\nimport { splitMessage } from \"./text.ts\";\nimport type { MessageEvent, PlatformAdapter, SendOptions } from \"./types.ts\";\n\nconst epochs = new Map<string, number>();\nconst inputs = new Map<string, { userId: string; resolve: (value: string | undefined) => void }>();\nconst dialogs = new Map<string, Set<() => void>>();\nlet adapters = new Map<string, PlatformAdapter>();\nconst deliveryConfigs = new Map<string, GatewayConfig>();\nconst roleGrants = new Map<string, { userId: string; chatId: string; threadId?: string }>();\nlet timer: ReturnType<typeof setInterval> | undefined;\nconst activeDeliveries = new Map<string, Promise<void>>();\ninterface Outbound {\n\tid: string;\n\tkey: string;\n\tepoch: number;\n\ttext: string;\n\tsource?: MessageEvent[\"source\"];\n\treplyTo?: string;\n\tkind?: \"result\" | \"notice\";\n\tattempts?: number;\n\tnextAttempt?: number;\n\tfailed?: boolean;\n\tbatchId?: string;\n}\nconst MAX_ATTEMPTS = 5;\nconst path = () => join(getAgentDir(), \"gateway-outbox.json\");\nlet outbox: Outbound[] = [];\n\nfunction sourceWithCurrentRole(key: string, source: MessageEvent[\"source\"]): MessageEvent[\"source\"] {\n\tconst grant = roleGrants.get(key);\n\treturn {\n\t\t...source,\n\t\troleAuthorized:\n\t\t\tgrant?.userId === source.userId && grant.chatId === source.chatId && grant.threadId === source.threadId,\n\t};\n}\n\nexport function rememberGatewayRole(key: string, source: MessageEvent[\"source\"]): void {\n\tif (source.roleAuthorized === true)\n\t\troleGrants.set(key, { userId: source.userId, chatId: source.chatId, threadId: source.threadId });\n\telse roleGrants.delete(key);\n}\n\nfunction canDeliver(key: string): boolean {\n\tconst binding = conversationBinding(key);\n\tif (!binding) return false;\n\tconst cfg = loadGatewayConfig();\n\tif (binding.owner && binding.owner !== binding.source.userId) return false;\n\treturn isAuthorized(sourceWithCurrentRole(key, binding.source), cfg, createPairingStore());\n}\n\nexport function gatewayDestination(key: string): { adapter: PlatformAdapter; source: MessageEvent[\"source\"] } {\n\tconst binding = conversationBinding(key);\n\tconst adapter = binding && adapters.get(binding.source.platform);\n\tif (!binding || !adapter || !canDeliver(key))\n\t\tthrow new Error(\"This chat is no longer authorized or its platform is disconnected.\");\n\treturn { adapter, source: binding.source };\n}\n\nexport function withGatewayPresentation<T>(key: string, run: () => Promise<T>): Promise<T> {\n\tconst { adapter, source } = gatewayDestination(key);\n\treturn runWithApprovalContext({ adapter, source, key }, run);\n}\n\nexport function startGatewayPresenter(connected: Map<string, PlatformAdapter>): void {\n\tadapters = connected;\n\tif (existsSync(path())) {\n\t\ttry {\n\t\t\tconst raw: unknown = JSON.parse(readFileSync(path(), \"utf8\"));\n\t\t\tif (\n\t\t\t\t!Array.isArray(raw) ||\n\t\t\t\t!raw.every(\n\t\t\t\t\t(item) =>\n\t\t\t\t\t\titem && typeof item.id === \"string\" && typeof item.key === \"string\" && typeof item.text === \"string\",\n\t\t\t\t)\n\t\t\t)\n\t\t\t\tthrow new Error(\"Invalid outbox\");\n\t\t\toutbox = raw as Outbound[];\n\t\t} catch {\n\t\t\tthrow new Error(\"Gateway outbox is invalid. Restore it before starting.\");\n\t\t}\n\t} else outbox = [];\n\tfor (const item of outbox) {\n\t\tif (item.kind === \"notice\") epochs.set(item.key, Math.max(epochs.get(item.key) ?? 0, item.epoch ?? 0));\n\t}\n\tif (timer) clearInterval(timer);\n\ttimer = setInterval(() => {\n\t\tvoid flushOutbox().catch((error) => console.error(\"[gateway] outbox flush failed:\", error));\n\t}, 3000);\n\ttimer.unref();\n\tvoid flushOutbox().catch((error) => console.error(\"[gateway] outbox flush failed:\", error));\n}\n\nexport function stopGatewayPresenter(): void {\n\tif (timer) clearInterval(timer);\n\ttimer = undefined;\n\tfor (const key of dialogs.keys()) invalidateGatewayDialogs(key);\n\tadapters = new Map();\n\tdeliveryConfigs.clear();\n\troleGrants.clear();\n}\n\nexport function gatewayEpoch(key: string): number {\n\treturn epochs.get(key) ?? 0;\n}\n\nexport async function sendGatewayNotice(\n\tkey: string,\n\ttext: string,\n\tkind: \"notice\" | \"result\" = \"notice\",\n\tepoch = gatewayEpoch(key),\n): Promise<void> {\n\tconst clean = text.replace(/\\x1b\\[[0-9;]*[a-zA-Z]/g, \"\").trim();\n\tif (!clean || !canDeliver(key)) return;\n\tconst { adapter, source } = gatewayDestination(key);\n\tawait queueGatewayText(key, source, adapter, clean, { kind, epoch });\n}\n\nexport async function queueGatewayText(\n\tkey: string,\n\tsource: MessageEvent[\"source\"],\n\tadapter: PlatformAdapter,\n\ttext: string,\n\toptions: { kind: \"result\" | \"notice\"; replyTo?: string; cfg?: GatewayConfig; chunks?: string[]; epoch?: number },\n): Promise<void> {\n\tif (!text || (options.kind === \"notice\" && options.epoch !== undefined && options.epoch !== gatewayEpoch(key)))\n\t\treturn;\n\tadapters.set(source.platform, adapter);\n\tif (options.cfg) deliveryConfigs.set(key, options.cfg);\n\tconst chunks = options.chunks ?? splitMessage(text, adapter.maxMessageLength);\n\tconst batchId = randomUUID();\n\tfor (const [index, chunk] of chunks.entries())\n\t\toutbox.push({\n\t\t\tid: randomUUID(),\n\t\t\tbatchId,\n\t\t\tkey,\n\t\t\tsource: { ...source, roleAuthorized: undefined },\n\t\t\tepoch: options.epoch ?? gatewayEpoch(key),\n\t\t\ttext: chunk,\n\t\t\tkind: options.kind,\n\t\t\treplyTo: index === 0 ? options.replyTo : undefined,\n\t\t});\n\tatomicJson(path(), outbox);\n\tif (activeDeliveries.has(key)) await activeDeliveries.get(key);\n\tawait flushKey(key);\n}\n\nexport function flushGatewayOutbox(): Promise<void> {\n\treturn flushOutbox();\n}\n\nfunction flushOutbox(): Promise<void> {\n\treturn Promise.all([...new Set(outbox.map((item) => item.key))].map(flushKey)).then(() => {});\n}\n\nfunction flushKey(key: string): Promise<void> {\n\tconst current = activeDeliveries.get(key);\n\tif (current) return current;\n\tconst running = drainKey(key).finally(() => {\n\t\tactiveDeliveries.delete(key);\n\t});\n\tactiveDeliveries.set(key, running);\n\treturn running;\n}\n\nasync function drainKey(key: string): Promise<void> {\n\tconst failedBatches = new Set(outbox.filter((item) => item.failed && item.batchId).map((item) => item.batchId));\n\tfor (const item of [...outbox].filter((item) => item.key === key)) {\n\t\tif (item.failed || (item.batchId && failedBatches.has(item.batchId))) continue;\n\t\tif (item.kind === \"notice\" && item.epoch !== (epochs.get(item.key) ?? 0)) {\n\t\t\toutbox = outbox.filter((v) => v.id !== item.id);\n\t\t\tatomicJson(path(), outbox);\n\t\t\tcontinue;\n\t\t}\n\t\tconst binding = conversationBinding(item.key);\n\t\tconst source = item.source ?? binding?.source;\n\t\tif (!source) break;\n\t\tconst cfg = existsSync(gatewayConfigPath())\n\t\t\t? loadGatewayConfig()\n\t\t\t: (deliveryConfigs.get(item.key) ?? loadGatewayConfig());\n\t\tif (\n\t\t\t(binding &&\n\t\t\t\t(binding.source.platform !== source.platform ||\n\t\t\t\t\tbinding.source.chatId !== source.chatId ||\n\t\t\t\t\tbinding.source.userId !== source.userId ||\n\t\t\t\t\tbinding.source.threadId !== source.threadId)) ||\n\t\t\t!isAuthorized(sourceWithCurrentRole(key, source), cfg, createPairingStore()) ||\n\t\t\t(binding?.owner && binding.owner !== source.userId)\n\t\t) {\n\t\t\toutbox = outbox.filter((v) => v.id !== item.id);\n\t\t\tatomicJson(path(), outbox);\n\t\t\tcontinue;\n\t\t}\n\t\tconst adapter = adapters.get(source.platform);\n\t\tif (!adapter || (item.nextAttempt ?? 0) > Date.now()) break;\n\t\tconst opts: SendOptions = { threadId: source.threadId, replyTo: item.replyTo };\n\t\tconst result = await adapter\n\t\t\t.send(source.chatId, item.text, opts)\n\t\t\t.catch((error: unknown) => ({ success: false as const, error: String(error), retryable: true }));\n\t\tif (result.success) {\n\t\t\toutbox = outbox.filter((v) => v.id !== item.id);\n\t\t\tatomicJson(path(), outbox);\n\t\t} else {\n\t\t\titem.attempts = (item.attempts ?? 0) + 1;\n\t\t\titem.failed = result.retryable === false || item.attempts >= MAX_ATTEMPTS;\n\t\t\titem.nextAttempt = Date.now() + Math.min(60_000, 3000 * 2 ** (item.attempts - 1));\n\t\t\tif (item.failed && item.batchId) {\n\t\t\t\tfailedBatches.add(item.batchId);\n\t\t\t\tfor (const pending of outbox) if (pending.batchId === item.batchId) pending.failed = true;\n\t\t\t}\n\t\t\tatomicJson(path(), outbox);\n\t\t\tconsole.error(\n\t\t\t\t`[gateway] delivery ${item.failed ? \"failed permanently\" : \"retry scheduled\"} for ${source.platform}: ${result.error ?? \"unknown error\"}`,\n\t\t\t);\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\nexport function invalidateGatewayDialogs(key: string): void {\n\tepochs.set(key, (epochs.get(key) ?? 0) + 1);\n\tconst remaining = outbox.filter((item) => item.key !== key || item.kind !== \"notice\");\n\tif (remaining.length !== outbox.length) {\n\t\toutbox = remaining;\n\t\tatomicJson(path(), outbox);\n\t}\n\tfor (const cancel of dialogs.get(key) ?? []) cancel();\n\tdialogs.delete(key);\n\tinputs.delete(key);\n}\n\nexport function acceptGatewayInput(key: string, event: MessageEvent): boolean {\n\tconst input = inputs.get(key);\n\tif (!input || input.userId !== event.source.userId || !canDeliver(key)) return false;\n\tif (event.text.startsWith(\"/\") && event.text !== \"/cancel\") return false;\n\tinput.resolve(event.text === \"/cancel\" ? undefined : event.text);\n\treturn true;\n}\n\nfunction dialog(\n\tkey: string,\n\topts: ExtensionUIDialogOptions | undefined,\n\tshow: (done: (value: string | undefined) => void, valid: () => boolean) => Promise<void>,\n): Promise<string | undefined> {\n\tconst epoch = epochs.get(key) ?? 0;\n\treturn new Promise((resolve, reject) => {\n\t\tlet settled = false;\n\t\tconst finish = (value: string | undefined, error?: unknown) => {\n\t\t\tif (settled) return;\n\t\t\tsettled = true;\n\t\t\tclearTimeout(timeout);\n\t\t\topts?.signal?.removeEventListener(\"abort\", cancel);\n\t\t\tinputs.delete(key);\n\t\t\tdialogs.get(key)?.delete(cancel);\n\t\t\tif (error !== undefined) reject(error);\n\t\t\telse resolve(value);\n\t\t};\n\t\tconst done = (value: string | undefined) => finish(value);\n\t\tconst cancel = () => done(undefined);\n\t\tconst timeout = setTimeout(cancel, opts?.timeout ?? 300_000);\n\t\tconst set = dialogs.get(key) ?? new Set();\n\t\tset.add(cancel);\n\t\tdialogs.set(key, set);\n\t\topts?.signal?.addEventListener(\"abort\", cancel, { once: true });\n\t\tif (opts?.signal?.aborted) {\n\t\t\tcancel();\n\t\t\treturn;\n\t\t}\n\t\tvoid show(done, () => !settled && (epochs.get(key) ?? 0) === epoch && canDeliver(key)).catch((error) => {\n\t\t\tfinish(undefined, error);\n\t\t});\n\t});\n}\n\nexport function gatewaySelect(\n\tkey: string,\n\ttitle: string,\n\toptions: string[],\n\topts?: ExtensionUIDialogOptions,\n): Promise<string | undefined> {\n\treturn dialog(key, opts, async (done, valid) => {\n\t\tconst { adapter, source } = gatewayDestination(key);\n\t\tconst result = await createPicker(\n\t\t\tadapter,\n\t\t\tsource,\n\t\t\t{\n\t\t\t\tkind: \"dialog\",\n\t\t\t\tsessionKey: key,\n\t\t\t\tinvokerId: source.userId,\n\t\t\t\ttitle,\n\t\t\t\titems: options.map((value) => ({ label: value, value })),\n\t\t\t\tvalidate: valid,\n\t\t\t\tonCancel: () => done(undefined),\n\t\t\t\tresolve: async (item) => {\n\t\t\t\t\tdone(item.value);\n\t\t\t\t\treturn { done: true, text: `${title}\\n${item.value}` };\n\t\t\t\t},\n\t\t\t},\n\t\t\t{ threadId: source.threadId },\n\t\t);\n\t\tif (!result.success) throw new Error(result.error ?? \"Could not send picker.\");\n\t});\n}\n\nexport function gatewayInput(\n\tkey: string,\n\ttitle: string,\n\tplaceholder?: string,\n\topts?: ExtensionUIDialogOptions,\n): Promise<string | undefined> {\n\tif (inputs.has(key)) return Promise.reject(new Error(\"Answer or cancel the existing question first.\"));\n\tconst epoch = gatewayEpoch(key);\n\treturn dialog(key, opts, async (done) => {\n\t\tconst { source } = gatewayDestination(key);\n\t\tinputs.set(key, { userId: source.userId, resolve: done });\n\t\tawait sendGatewayNotice(\n\t\t\tkey,\n\t\t\t`${title}${placeholder ? `\\n${placeholder}` : \"\"}\\nReply with text, or /cancel.`,\n\t\t\t\"notice\",\n\t\t\tepoch,\n\t\t);\n\t});\n}\n\nexport function createGatewayUI(key: string): ExtensionUIContext {\n\tconst epoch = gatewayEpoch(key);\n\treturn {\n\t\t...noOpUIContext,\n\t\tselect: (title, options, opts) =>\n\t\t\tgatewayEpoch(key) === epoch ? gatewaySelect(key, title, options, opts) : Promise.resolve(undefined),\n\t\tconfirm: async (title, message, opts) =>\n\t\t\tgatewayEpoch(key) === epoch &&\n\t\t\t(await gatewaySelect(key, `${title}\\n${message}`, [\"Approve\", \"Decline\"], opts)) === \"Approve\",\n\t\tinput: (title, placeholder, opts) =>\n\t\t\tgatewayEpoch(key) === epoch ? gatewayInput(key, title, placeholder, opts) : Promise.resolve(undefined),\n\t\teditor: (title, prefill) =>\n\t\t\tgatewayEpoch(key) === epoch ? gatewayInput(key, title, prefill) : Promise.resolve(undefined),\n\t\tnotify: (message) => {\n\t\t\tvoid sendGatewayNotice(key, message, \"notice\", epoch).catch(() => {});\n\t\t},\n\t\tcustom: async () => {\n\t\t\tthrow new Error(\n\t\t\t\t\"This command requires the terminal interface. Use the gateway's text commands or button pickers.\",\n\t\t\t);\n\t\t},\n\t\tpasteToEditor: (text) => {\n\t\t\tvoid sendGatewayNotice(key, text, \"notice\", epoch).catch(() => {});\n\t\t},\n\t\tsetEditorText: (text) => {\n\t\t\tvoid sendGatewayNotice(key, text, \"notice\", epoch).catch(() => {});\n\t\t},\n\t};\n}\n"]}