@ashx-j/lunr 0.2.20 → 0.2.22

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 (528) hide show
  1. package/CHANGELOG.md +14 -2
  2. package/README.md +20 -4
  3. package/dist/builtin-extensions/index.d.ts.map +1 -1
  4. package/dist/builtin-extensions/index.js +1 -0
  5. package/dist/builtin-extensions/index.js.map +1 -1
  6. package/dist/builtin-extensions/lunr-browser.d.ts +3 -0
  7. package/dist/builtin-extensions/lunr-browser.d.ts.map +1 -0
  8. package/dist/builtin-extensions/lunr-browser.js +56 -0
  9. package/dist/builtin-extensions/lunr-browser.js.map +1 -0
  10. package/dist/builtin-extensions/lunr-todos.d.ts +6 -5
  11. package/dist/builtin-extensions/lunr-todos.d.ts.map +1 -1
  12. package/dist/builtin-extensions/lunr-todos.js +24 -7
  13. package/dist/builtin-extensions/lunr-todos.js.map +1 -1
  14. package/dist/builtin-extensions/pi-intercom/broker/spawn.d.ts.map +1 -1
  15. package/dist/builtin-extensions/pi-intercom/broker/spawn.js +30 -21
  16. package/dist/builtin-extensions/pi-intercom/broker/spawn.js.map +1 -1
  17. package/dist/builtin-extensions/pi-intercom/index.d.ts.map +1 -1
  18. package/dist/builtin-extensions/pi-intercom/index.js +15 -3
  19. package/dist/builtin-extensions/pi-intercom/index.js.map +1 -1
  20. package/dist/builtin-extensions/pi-subagents/src/extension/control-notices.d.ts +1 -1
  21. package/dist/builtin-extensions/pi-subagents/src/extension/control-notices.d.ts.map +1 -1
  22. package/dist/builtin-extensions/pi-subagents/src/extension/control-notices.js +5 -1
  23. package/dist/builtin-extensions/pi-subagents/src/extension/control-notices.js.map +1 -1
  24. package/dist/builtin-extensions/pi-subagents/src/extension/fanout-child.d.ts.map +1 -1
  25. package/dist/builtin-extensions/pi-subagents/src/extension/fanout-child.js +2 -2
  26. package/dist/builtin-extensions/pi-subagents/src/extension/fanout-child.js.map +1 -1
  27. package/dist/builtin-extensions/pi-subagents/src/extension/index.d.ts +8 -7
  28. package/dist/builtin-extensions/pi-subagents/src/extension/index.d.ts.map +1 -1
  29. package/dist/builtin-extensions/pi-subagents/src/extension/index.js +78 -31
  30. package/dist/builtin-extensions/pi-subagents/src/extension/index.js.map +1 -1
  31. package/dist/builtin-extensions/pi-subagents/src/extension/schemas.d.ts.map +1 -1
  32. package/dist/builtin-extensions/pi-subagents/src/extension/schemas.js +2 -2
  33. package/dist/builtin-extensions/pi-subagents/src/extension/schemas.js.map +1 -1
  34. package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.d.ts +4 -3
  35. package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.d.ts.map +1 -1
  36. package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.js +6 -2
  37. package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.js.map +1 -1
  38. package/dist/builtin-extensions/pi-subagents/src/intercom/communication.d.ts +17 -0
  39. package/dist/builtin-extensions/pi-subagents/src/intercom/communication.d.ts.map +1 -0
  40. package/dist/builtin-extensions/pi-subagents/src/intercom/communication.js +45 -0
  41. package/dist/builtin-extensions/pi-subagents/src/intercom/communication.js.map +1 -0
  42. package/dist/builtin-extensions/pi-subagents/src/intercom/intercom-bridge.d.ts.map +1 -1
  43. package/dist/builtin-extensions/pi-subagents/src/intercom/intercom-bridge.js +4 -11
  44. package/dist/builtin-extensions/pi-subagents/src/intercom/intercom-bridge.js.map +1 -1
  45. package/dist/builtin-extensions/pi-subagents/src/intercom/native-supervisor-channel.d.ts +5 -1
  46. package/dist/builtin-extensions/pi-subagents/src/intercom/native-supervisor-channel.d.ts.map +1 -1
  47. package/dist/builtin-extensions/pi-subagents/src/intercom/native-supervisor-channel.js +186 -58
  48. package/dist/builtin-extensions/pi-subagents/src/intercom/native-supervisor-channel.js.map +1 -1
  49. package/dist/builtin-extensions/pi-subagents/src/intercom/result-intercom.d.ts +1 -0
  50. package/dist/builtin-extensions/pi-subagents/src/intercom/result-intercom.d.ts.map +1 -1
  51. package/dist/builtin-extensions/pi-subagents/src/intercom/result-intercom.js +1 -1
  52. package/dist/builtin-extensions/pi-subagents/src/intercom/result-intercom.js.map +1 -1
  53. package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-ask.d.ts.map +1 -1
  54. package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-ask.js +5 -0
  55. package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-ask.js.map +1 -1
  56. package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-questions.d.ts +2 -0
  57. package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-questions.d.ts.map +1 -1
  58. package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-questions.js +3 -2
  59. package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-questions.js.map +1 -1
  60. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-execution.d.ts +2 -0
  61. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-execution.d.ts.map +1 -1
  62. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-execution.js +4 -3
  63. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-execution.js.map +1 -1
  64. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-job-tracker.d.ts.map +1 -1
  65. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-job-tracker.js +2 -0
  66. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-job-tracker.js.map +1 -1
  67. package/dist/builtin-extensions/pi-subagents/src/runs/background/auto-drain.d.ts +1 -0
  68. package/dist/builtin-extensions/pi-subagents/src/runs/background/auto-drain.d.ts.map +1 -1
  69. package/dist/builtin-extensions/pi-subagents/src/runs/background/auto-drain.js +2 -1
  70. package/dist/builtin-extensions/pi-subagents/src/runs/background/auto-drain.js.map +1 -1
  71. package/dist/builtin-extensions/pi-subagents/src/runs/background/notify.d.ts +6 -2
  72. package/dist/builtin-extensions/pi-subagents/src/runs/background/notify.d.ts.map +1 -1
  73. package/dist/builtin-extensions/pi-subagents/src/runs/background/notify.js +23 -1
  74. package/dist/builtin-extensions/pi-subagents/src/runs/background/notify.js.map +1 -1
  75. package/dist/builtin-extensions/pi-subagents/src/runs/background/result-watcher.d.ts.map +1 -1
  76. package/dist/builtin-extensions/pi-subagents/src/runs/background/result-watcher.js +1 -0
  77. package/dist/builtin-extensions/pi-subagents/src/runs/background/result-watcher.js.map +1 -1
  78. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-runner.d.ts +100 -0
  79. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-runner.d.ts.map +1 -1
  80. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-runner.js +46 -31
  81. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-runner.js.map +1 -1
  82. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-wait.d.ts +1 -0
  83. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-wait.d.ts.map +1 -1
  84. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-wait.js +2 -0
  85. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-wait.js.map +1 -1
  86. package/dist/builtin-extensions/pi-subagents/src/runs/background/top-level-async.d.ts +15 -2
  87. package/dist/builtin-extensions/pi-subagents/src/runs/background/top-level-async.d.ts.map +1 -1
  88. package/dist/builtin-extensions/pi-subagents/src/runs/background/top-level-async.js +14 -4
  89. package/dist/builtin-extensions/pi-subagents/src/runs/background/top-level-async.js.map +1 -1
  90. package/dist/builtin-extensions/pi-subagents/src/runs/background/wait-tool.d.ts.map +1 -1
  91. package/dist/builtin-extensions/pi-subagents/src/runs/background/wait-tool.js +1 -1
  92. package/dist/builtin-extensions/pi-subagents/src/runs/background/wait-tool.js.map +1 -1
  93. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/execution.d.ts.map +1 -1
  94. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/execution.js +1 -1
  95. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/execution.js.map +1 -1
  96. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.d.ts +0 -1
  97. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.d.ts.map +1 -1
  98. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.js +9 -9
  99. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.js.map +1 -1
  100. package/dist/builtin-extensions/pi-subagents/src/runs/shared/completion-guard.d.ts +1 -1
  101. package/dist/builtin-extensions/pi-subagents/src/runs/shared/completion-guard.d.ts.map +1 -1
  102. package/dist/builtin-extensions/pi-subagents/src/runs/shared/completion-guard.js +1 -1
  103. package/dist/builtin-extensions/pi-subagents/src/runs/shared/completion-guard.js.map +1 -1
  104. package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.d.ts +1 -0
  105. package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.d.ts.map +1 -1
  106. package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.js.map +1 -1
  107. package/dist/builtin-extensions/pi-subagents/src/runs/shared/pi-args.d.ts +3 -0
  108. package/dist/builtin-extensions/pi-subagents/src/runs/shared/pi-args.d.ts.map +1 -1
  109. package/dist/builtin-extensions/pi-subagents/src/runs/shared/pi-args.js +5 -0
  110. package/dist/builtin-extensions/pi-subagents/src/runs/shared/pi-args.js.map +1 -1
  111. package/dist/builtin-extensions/pi-subagents/src/runs/shared/subagent-control.d.ts +1 -0
  112. package/dist/builtin-extensions/pi-subagents/src/runs/shared/subagent-control.d.ts.map +1 -1
  113. package/dist/builtin-extensions/pi-subagents/src/runs/shared/subagent-control.js +3 -0
  114. package/dist/builtin-extensions/pi-subagents/src/runs/shared/subagent-control.js.map +1 -1
  115. package/dist/builtin-extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.d.ts.map +1 -1
  116. package/dist/builtin-extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.js +1 -1
  117. package/dist/builtin-extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.js.map +1 -1
  118. package/dist/builtin-extensions/pi-subagents/src/runs/shared/task-intent.d.ts +2 -2
  119. package/dist/builtin-extensions/pi-subagents/src/runs/shared/task-intent.d.ts.map +1 -1
  120. package/dist/builtin-extensions/pi-subagents/src/runs/shared/task-intent.js +5 -10
  121. package/dist/builtin-extensions/pi-subagents/src/runs/shared/task-intent.js.map +1 -1
  122. package/dist/builtin-extensions/pi-subagents/src/shared/async-guidance.d.ts +2 -0
  123. package/dist/builtin-extensions/pi-subagents/src/shared/async-guidance.d.ts.map +1 -0
  124. package/dist/builtin-extensions/pi-subagents/src/shared/async-guidance.js +3 -0
  125. package/dist/builtin-extensions/pi-subagents/src/shared/async-guidance.js.map +1 -0
  126. package/dist/builtin-extensions/pi-subagents/src/shared/types.d.ts +6 -0
  127. package/dist/builtin-extensions/pi-subagents/src/shared/types.d.ts.map +1 -1
  128. package/dist/builtin-extensions/pi-subagents/src/shared/types.js.map +1 -1
  129. package/dist/builtin-extensions/pi-subagents/src/slash/delegation-adapters.d.ts.map +1 -1
  130. package/dist/builtin-extensions/pi-subagents/src/slash/delegation-adapters.js.map +1 -1
  131. package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.d.ts +7 -0
  132. package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.d.ts.map +1 -1
  133. package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.js +11 -7
  134. package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.js.map +1 -1
  135. package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.d.ts +4 -0
  136. package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.d.ts.map +1 -1
  137. package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.js +22 -23
  138. package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.js.map +1 -1
  139. package/dist/builtin-extensions/pi-subagents/src/tui/communication.d.ts +18 -0
  140. package/dist/builtin-extensions/pi-subagents/src/tui/communication.d.ts.map +1 -0
  141. package/dist/builtin-extensions/pi-subagents/src/tui/communication.js +47 -0
  142. package/dist/builtin-extensions/pi-subagents/src/tui/communication.js.map +1 -0
  143. package/dist/builtin-extensions/pi-subagents/src/tui/render.d.ts +2 -0
  144. package/dist/builtin-extensions/pi-subagents/src/tui/render.d.ts.map +1 -1
  145. package/dist/builtin-extensions/pi-subagents/src/tui/render.js +237 -374
  146. package/dist/builtin-extensions/pi-subagents/src/tui/render.js.map +1 -1
  147. package/dist/builtin-extensions/pi-web-access/index.d.ts.map +1 -1
  148. package/dist/builtin-extensions/pi-web-access/index.js +11 -7
  149. package/dist/builtin-extensions/pi-web-access/index.js.map +1 -1
  150. package/dist/cli/args.d.ts.map +1 -1
  151. package/dist/cli/args.js +2 -1
  152. package/dist/cli/args.js.map +1 -1
  153. package/dist/cli/install-cli.d.ts.map +1 -1
  154. package/dist/cli/install-cli.js +15 -45
  155. package/dist/cli/install-cli.js.map +1 -1
  156. package/dist/core/agent-session-runtime.d.ts +9 -0
  157. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  158. package/dist/core/agent-session-runtime.js +126 -29
  159. package/dist/core/agent-session-runtime.js.map +1 -1
  160. package/dist/core/agent-session.d.ts +3 -0
  161. package/dist/core/agent-session.d.ts.map +1 -1
  162. package/dist/core/agent-session.js +20 -2
  163. package/dist/core/agent-session.js.map +1 -1
  164. package/dist/core/browser/network.d.ts +9 -0
  165. package/dist/core/browser/network.d.ts.map +1 -0
  166. package/dist/core/browser/network.js +146 -0
  167. package/dist/core/browser/network.js.map +1 -0
  168. package/dist/core/browser/runtime.d.ts +24 -0
  169. package/dist/core/browser/runtime.d.ts.map +1 -0
  170. package/dist/core/browser/runtime.js +289 -0
  171. package/dist/core/browser/runtime.js.map +1 -0
  172. package/dist/core/browser/schema.d.ts +16 -0
  173. package/dist/core/browser/schema.d.ts.map +1 -0
  174. package/dist/core/browser/schema.js +36 -0
  175. package/dist/core/browser/schema.js.map +1 -0
  176. package/dist/core/browser/settings.d.ts +8 -0
  177. package/dist/core/browser/settings.d.ts.map +1 -0
  178. package/dist/core/browser/settings.js +30 -0
  179. package/dist/core/browser/settings.js.map +1 -0
  180. package/dist/core/browser/setup.d.ts +2 -0
  181. package/dist/core/browser/setup.d.ts.map +1 -0
  182. package/dist/core/browser/setup.js +16 -0
  183. package/dist/core/browser/setup.js.map +1 -0
  184. package/dist/core/customize.d.ts +2 -0
  185. package/dist/core/customize.d.ts.map +1 -1
  186. package/dist/core/customize.js +17 -13
  187. package/dist/core/customize.js.map +1 -1
  188. package/dist/core/export-html/index.d.ts.map +1 -1
  189. package/dist/core/export-html/index.js +1 -1
  190. package/dist/core/export-html/index.js.map +1 -1
  191. package/dist/core/extensions/runner.d.ts +1 -0
  192. package/dist/core/extensions/runner.d.ts.map +1 -1
  193. package/dist/core/extensions/runner.js +1 -1
  194. package/dist/core/extensions/runner.js.map +1 -1
  195. package/dist/core/extensions/types.d.ts +1 -1
  196. package/dist/core/extensions/types.d.ts.map +1 -1
  197. package/dist/core/extensions/types.js.map +1 -1
  198. package/dist/core/install-features.d.ts.map +1 -1
  199. package/dist/core/install-features.js +10 -8
  200. package/dist/core/install-features.js.map +1 -1
  201. package/dist/core/memory-cap.d.ts.map +1 -1
  202. package/dist/core/memory-cap.js +5 -3
  203. package/dist/core/memory-cap.js.map +1 -1
  204. package/dist/core/model-tiers.d.ts.map +1 -1
  205. package/dist/core/model-tiers.js +9 -6
  206. package/dist/core/model-tiers.js.map +1 -1
  207. package/dist/core/permissions.d.ts.map +1 -1
  208. package/dist/core/permissions.js +9 -0
  209. package/dist/core/permissions.js.map +1 -1
  210. package/dist/core/plan-mode.d.ts.map +1 -1
  211. package/dist/core/plan-mode.js +3 -0
  212. package/dist/core/plan-mode.js.map +1 -1
  213. package/dist/core/process-registry.d.ts.map +1 -1
  214. package/dist/core/process-registry.js +6 -4
  215. package/dist/core/process-registry.js.map +1 -1
  216. package/dist/core/runtime-scope.d.ts +11 -0
  217. package/dist/core/runtime-scope.d.ts.map +1 -0
  218. package/dist/core/runtime-scope.js +3 -0
  219. package/dist/core/runtime-scope.js.map +1 -0
  220. package/dist/core/sdk.d.ts.map +1 -1
  221. package/dist/core/sdk.js +13 -0
  222. package/dist/core/sdk.js.map +1 -1
  223. package/dist/core/session-handoff.d.ts +35 -0
  224. package/dist/core/session-handoff.d.ts.map +1 -0
  225. package/dist/core/session-handoff.js +214 -0
  226. package/dist/core/session-handoff.js.map +1 -0
  227. package/dist/core/session-manager.d.ts +20 -0
  228. package/dist/core/session-manager.d.ts.map +1 -1
  229. package/dist/core/session-manager.js +184 -22
  230. package/dist/core/session-manager.js.map +1 -1
  231. package/dist/core/session-ownership.d.ts +28 -0
  232. package/dist/core/session-ownership.d.ts.map +1 -0
  233. package/dist/core/session-ownership.js +138 -0
  234. package/dist/core/session-ownership.js.map +1 -0
  235. package/dist/core/session-retention.d.ts.map +1 -1
  236. package/dist/core/session-retention.js +11 -2
  237. package/dist/core/session-retention.js.map +1 -1
  238. package/dist/core/settings-manager.d.ts +11 -0
  239. package/dist/core/settings-manager.d.ts.map +1 -1
  240. package/dist/core/settings-manager.js +29 -0
  241. package/dist/core/settings-manager.js.map +1 -1
  242. package/dist/core/slash-commands.d.ts.map +1 -1
  243. package/dist/core/slash-commands.js +2 -0
  244. package/dist/core/slash-commands.js.map +1 -1
  245. package/dist/core/subagent-spinner-setting.d.ts +6 -0
  246. package/dist/core/subagent-spinner-setting.d.ts.map +1 -0
  247. package/dist/core/subagent-spinner-setting.js +12 -0
  248. package/dist/core/subagent-spinner-setting.js.map +1 -0
  249. package/dist/core/subagent-spinner.d.ts +4 -0
  250. package/dist/core/subagent-spinner.d.ts.map +1 -0
  251. package/dist/core/subagent-spinner.js +6 -0
  252. package/dist/core/subagent-spinner.js.map +1 -0
  253. package/dist/core/system-prompt.d.ts.map +1 -1
  254. package/dist/core/system-prompt.js +5 -2
  255. package/dist/core/system-prompt.js.map +1 -1
  256. package/dist/core/todo-settings.d.ts +5 -0
  257. package/dist/core/todo-settings.d.ts.map +1 -0
  258. package/dist/core/todo-settings.js +7 -0
  259. package/dist/core/todo-settings.js.map +1 -0
  260. package/dist/core/tools/bash.d.ts.map +1 -1
  261. package/dist/core/tools/bash.js +4 -4
  262. package/dist/core/tools/bash.js.map +1 -1
  263. package/dist/core/tools/edit.d.ts.map +1 -1
  264. package/dist/core/tools/edit.js +5 -3
  265. package/dist/core/tools/edit.js.map +1 -1
  266. package/dist/core/tools/find.d.ts.map +1 -1
  267. package/dist/core/tools/find.js +4 -4
  268. package/dist/core/tools/find.js.map +1 -1
  269. package/dist/core/tools/grep.d.ts.map +1 -1
  270. package/dist/core/tools/grep.js +4 -4
  271. package/dist/core/tools/grep.js.map +1 -1
  272. package/dist/core/tools/ls.d.ts.map +1 -1
  273. package/dist/core/tools/ls.js +4 -4
  274. package/dist/core/tools/ls.js.map +1 -1
  275. package/dist/core/tools/read.d.ts.map +1 -1
  276. package/dist/core/tools/read.js +4 -4
  277. package/dist/core/tools/read.js.map +1 -1
  278. package/dist/core/tools/render-utils.d.ts +11 -2
  279. package/dist/core/tools/render-utils.d.ts.map +1 -1
  280. package/dist/core/tools/render-utils.js +31 -4
  281. package/dist/core/tools/render-utils.js.map +1 -1
  282. package/dist/core/tools/write.d.ts.map +1 -1
  283. package/dist/core/tools/write.js +4 -4
  284. package/dist/core/tools/write.js.map +1 -1
  285. package/dist/core/usage-service.d.ts.map +1 -1
  286. package/dist/core/usage-service.js +5 -3
  287. package/dist/core/usage-service.js.map +1 -1
  288. package/dist/gateway/adapters/discord.d.ts +12 -1
  289. package/dist/gateway/adapters/discord.d.ts.map +1 -1
  290. package/dist/gateway/adapters/discord.js +112 -17
  291. package/dist/gateway/adapters/discord.js.map +1 -1
  292. package/dist/gateway/adapters/telegram.d.ts +4 -2
  293. package/dist/gateway/adapters/telegram.d.ts.map +1 -1
  294. package/dist/gateway/adapters/telegram.js +34 -11
  295. package/dist/gateway/adapters/telegram.js.map +1 -1
  296. package/dist/gateway/agent-bridge.d.ts +14 -3
  297. package/dist/gateway/agent-bridge.d.ts.map +1 -1
  298. package/dist/gateway/agent-bridge.js +252 -60
  299. package/dist/gateway/agent-bridge.js.map +1 -1
  300. package/dist/gateway/approval.d.ts +1 -0
  301. package/dist/gateway/approval.d.ts.map +1 -1
  302. package/dist/gateway/approval.js +60 -18
  303. package/dist/gateway/approval.js.map +1 -1
  304. package/dist/gateway/authz.d.ts +2 -0
  305. package/dist/gateway/authz.d.ts.map +1 -1
  306. package/dist/gateway/authz.js +13 -0
  307. package/dist/gateway/authz.js.map +1 -1
  308. package/dist/gateway/buttons.d.ts +3 -1
  309. package/dist/gateway/buttons.d.ts.map +1 -1
  310. package/dist/gateway/buttons.js +18 -3
  311. package/dist/gateway/buttons.js.map +1 -1
  312. package/dist/gateway/command.d.ts.map +1 -1
  313. package/dist/gateway/command.js +49 -4
  314. package/dist/gateway/command.js.map +1 -1
  315. package/dist/gateway/commands.d.ts.map +1 -1
  316. package/dist/gateway/commands.js +18 -3
  317. package/dist/gateway/commands.js.map +1 -1
  318. package/dist/gateway/config.d.ts +5 -0
  319. package/dist/gateway/config.d.ts.map +1 -1
  320. package/dist/gateway/config.js +5 -0
  321. package/dist/gateway/config.js.map +1 -1
  322. package/dist/gateway/conversations.d.ts +14 -0
  323. package/dist/gateway/conversations.d.ts.map +1 -0
  324. package/dist/gateway/conversations.js +30 -0
  325. package/dist/gateway/conversations.js.map +1 -0
  326. package/dist/gateway/download.d.ts +2 -0
  327. package/dist/gateway/download.d.ts.map +1 -0
  328. package/dist/gateway/download.js +36 -0
  329. package/dist/gateway/download.js.map +1 -0
  330. package/dist/gateway/index.d.ts.map +1 -1
  331. package/dist/gateway/index.js +85 -26
  332. package/dist/gateway/index.js.map +1 -1
  333. package/dist/gateway/mobile-commands.d.ts +24 -0
  334. package/dist/gateway/mobile-commands.d.ts.map +1 -0
  335. package/dist/gateway/mobile-commands.js +422 -0
  336. package/dist/gateway/mobile-commands.js.map +1 -0
  337. package/dist/gateway/presenter.d.ts +16 -0
  338. package/dist/gateway/presenter.d.ts.map +1 -0
  339. package/dist/gateway/presenter.js +210 -0
  340. package/dist/gateway/presenter.js.map +1 -0
  341. package/dist/gateway/router.d.ts +1 -0
  342. package/dist/gateway/router.d.ts.map +1 -1
  343. package/dist/gateway/router.js +32 -3
  344. package/dist/gateway/router.js.map +1 -1
  345. package/dist/gateway/service.d.ts +46 -0
  346. package/dist/gateway/service.d.ts.map +1 -0
  347. package/dist/gateway/service.js +395 -0
  348. package/dist/gateway/service.js.map +1 -0
  349. package/dist/gateway/setup.d.ts +4 -0
  350. package/dist/gateway/setup.d.ts.map +1 -0
  351. package/dist/gateway/setup.js +146 -0
  352. package/dist/gateway/setup.js.map +1 -0
  353. package/dist/gateway/types.d.ts +4 -2
  354. package/dist/gateway/types.d.ts.map +1 -1
  355. package/dist/gateway/types.js.map +1 -1
  356. package/dist/index.d.ts +2 -0
  357. package/dist/index.d.ts.map +1 -1
  358. package/dist/index.js +2 -0
  359. package/dist/index.js.map +1 -1
  360. package/dist/main.d.ts.map +1 -1
  361. package/dist/main.js +2 -1
  362. package/dist/main.js.map +1 -1
  363. package/dist/modes/interactive/components/assistant-message.d.ts +11 -2
  364. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  365. package/dist/modes/interactive/components/assistant-message.js +53 -16
  366. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  367. package/dist/modes/interactive/components/copyable-text.d.ts +31 -0
  368. package/dist/modes/interactive/components/copyable-text.d.ts.map +1 -0
  369. package/dist/modes/interactive/components/copyable-text.js +165 -0
  370. package/dist/modes/interactive/components/copyable-text.js.map +1 -0
  371. package/dist/modes/interactive/components/custom-entry.d.ts +1 -0
  372. package/dist/modes/interactive/components/custom-entry.d.ts.map +1 -1
  373. package/dist/modes/interactive/components/custom-entry.js +8 -0
  374. package/dist/modes/interactive/components/custom-entry.js.map +1 -1
  375. package/dist/modes/interactive/components/custom-message.d.ts +1 -0
  376. package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
  377. package/dist/modes/interactive/components/custom-message.js +8 -0
  378. package/dist/modes/interactive/components/custom-message.js.map +1 -1
  379. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  380. package/dist/modes/interactive/components/session-selector.js +16 -0
  381. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  382. package/dist/modes/interactive/components/settings-selector.d.ts +9 -0
  383. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  384. package/dist/modes/interactive/components/settings-selector.js +111 -1
  385. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  386. package/dist/modes/interactive/extension-widget-order.d.ts +8 -0
  387. package/dist/modes/interactive/extension-widget-order.d.ts.map +1 -0
  388. package/dist/modes/interactive/extension-widget-order.js +37 -0
  389. package/dist/modes/interactive/extension-widget-order.js.map +1 -0
  390. package/dist/modes/interactive/interactive-mode.d.ts +3 -0
  391. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  392. package/dist/modes/interactive/interactive-mode.js +166 -29
  393. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  394. package/dist/node-runtime/agent-session-services-NQ6GKOIK.js +49 -0
  395. package/dist/node-runtime/{builtin-extensions-X4JMM4ZS.js → builtin-extensions-GVC6IFDU.js} +6 -4
  396. package/dist/node-runtime/{chunk-LTYWTR3V.js → chunk-2MI5OPMN.js} +17 -2
  397. package/dist/node-runtime/{chunk-W3CVH5RX.js → chunk-2TKODGBZ.js} +11 -6
  398. package/dist/node-runtime/chunk-4EULYYR4.js +62 -0
  399. package/dist/node-runtime/chunk-5BNJ4JUH.js +672 -0
  400. package/dist/node-runtime/{chunk-6N22HULO.js → chunk-5D7LC2ZQ.js} +7 -2
  401. package/dist/node-runtime/chunk-5ZH3ZFIZ.js +308 -0
  402. package/dist/node-runtime/{chunk-KBKMCJDU.js → chunk-5ZQXRPMC.js} +19 -4
  403. package/dist/node-runtime/{chunk-6KDIOJL3.js → chunk-6427XAWG.js} +3 -3
  404. package/dist/node-runtime/{chunk-BOHIDQT4.js → chunk-6B2POMK7.js} +1 -1
  405. package/dist/node-runtime/{chunk-RNBHABBA.js → chunk-7QWNYZDI.js} +7 -0
  406. package/dist/node-runtime/chunk-AZJHNQKQ.js +205 -0
  407. package/dist/node-runtime/chunk-BFNXONG3.js +521 -0
  408. package/dist/node-runtime/{chunk-IRPJXI6U.js → chunk-BX2RB477.js} +1 -1
  409. package/dist/node-runtime/chunk-CCCN2UCX.js +14 -0
  410. package/dist/node-runtime/{chunk-25I2BHAA.js → chunk-CSUZVNYE.js} +1 -1
  411. package/dist/node-runtime/{chunk-QZMODZQ2.js → chunk-E24EO34J.js} +2 -1
  412. package/dist/node-runtime/{chunk-QKFMBRAL.js → chunk-EQ63ANHL.js} +508 -140
  413. package/dist/node-runtime/{chunk-ELWEXVO5.js → chunk-GJSAD4AB.js} +216 -201
  414. package/dist/node-runtime/{chunk-AOFXZQKA.js → chunk-GMHJCCEN.js} +8 -8
  415. package/dist/node-runtime/{chunk-DDWHZ633.js → chunk-GNN7H3B7.js} +1 -1
  416. package/dist/node-runtime/chunk-GS66LV4M.js +2830 -0
  417. package/dist/node-runtime/{chunk-6BEIBLQ3.js → chunk-H3XF4UVQ.js} +1 -1
  418. package/dist/node-runtime/chunk-H4K3JDRB.js +47 -0
  419. package/dist/node-runtime/{chunk-AROOY4BB.js → chunk-HTFRRDSF.js} +2 -7
  420. package/dist/node-runtime/chunk-IMLCWLPI.js +9 -0
  421. package/dist/node-runtime/{chunk-4CSFRBCN.js → chunk-IQIEU7SB.js} +9 -674
  422. package/dist/node-runtime/{chunk-OPEK5RRY.js → chunk-IVXYUAJE.js} +1 -1
  423. package/dist/node-runtime/{chunk-AL2FMKKM.js → chunk-IWOWXRWU.js} +58 -48
  424. package/dist/node-runtime/chunk-KKUTQQV7.js +144 -0
  425. package/dist/node-runtime/chunk-LISUTZS3.js +19 -0
  426. package/dist/node-runtime/{chunk-K3646JTM.js → chunk-LMBNLFXQ.js} +25 -314
  427. package/dist/node-runtime/{chunk-7NBZ5P7I.js → chunk-NAY6UUQZ.js} +1 -1
  428. package/dist/node-runtime/chunk-OAR4TYZE.js +146 -0
  429. package/dist/node-runtime/{chunk-STERBGUB.js → chunk-OFKSVRV7.js} +2 -2
  430. package/dist/node-runtime/{chunk-JZQ7F36T.js → chunk-ORH324EP.js} +19 -3
  431. package/dist/node-runtime/{chunk-2SJB2AWP.js → chunk-PC2Z5TKZ.js} +3 -3
  432. package/dist/node-runtime/{chunk-46ECNOLF.js → chunk-QDGKKKUM.js} +97 -162
  433. package/dist/node-runtime/chunk-R3K2F5GI.js +122 -0
  434. package/dist/node-runtime/chunk-RMQZU2YU.js +117 -0
  435. package/dist/node-runtime/{chunk-JYNNB7DU.js → chunk-TDL7UWJ7.js} +283 -2999
  436. package/dist/node-runtime/{chunk-G6LRAP36.js → chunk-TQGPP4SC.js} +1 -1
  437. package/dist/node-runtime/chunk-UAEOTO52.js +119 -0
  438. package/dist/node-runtime/{chunk-4DJ6HEGH.js → chunk-UAFLNHSH.js} +18 -14
  439. package/dist/node-runtime/{chunk-AY6CAJSL.js → chunk-UJOCPOMX.js} +6 -3
  440. package/dist/node-runtime/chunk-UP2XBVH5.js +40 -0
  441. package/dist/node-runtime/{chunk-WJVFOIB5.js → chunk-UQUCFAJ3.js} +1 -1
  442. package/dist/node-runtime/chunk-URD2SLIT.js +1019 -0
  443. package/dist/node-runtime/chunk-US544NN6.js +13 -0
  444. package/dist/node-runtime/chunk-UWPJL22I.js +341 -0
  445. package/dist/node-runtime/chunk-V2A7CEXK.js +355 -0
  446. package/dist/node-runtime/chunk-VJPTNWAP.js +708 -0
  447. package/dist/node-runtime/{chunk-WKDK4C5P.js → chunk-VSSXXL36.js} +38 -164
  448. package/dist/node-runtime/{chunk-4I23VTC4.js → chunk-VWCE2HSZ.js} +21 -124
  449. package/dist/node-runtime/{chunk-CBGB57XT.js → chunk-WADV2VDS.js} +32 -1014
  450. package/dist/node-runtime/{chunk-GKLEQ3I4.js → chunk-XLTL257W.js} +126 -27
  451. package/dist/node-runtime/chunk-YPHAIRZT.js +10 -0
  452. package/dist/node-runtime/cli-runtime.js +2 -2
  453. package/dist/node-runtime/command-3JHHXOPX.js +45 -0
  454. package/dist/node-runtime/commands-2JVNFGMQ.js +36 -0
  455. package/dist/node-runtime/{commands-MV5KOZ64.js → commands-KAMO2T6P.js} +10 -10
  456. package/dist/node-runtime/config-RORQUQFG.js +20 -0
  457. package/dist/node-runtime/{customize-XEXL2DGQ.js → customize-VFJV3U6A.js} +2 -1
  458. package/dist/node-runtime/{direct-tool-executor-BK7CLEBX.js → direct-tool-executor-YAVOLDFY.js} +8 -8
  459. package/dist/node-runtime/{export-html-TEXVV5RP.js → export-html-KBFVV63J.js} +4 -3
  460. package/dist/node-runtime/{extension-input-O4HSAEM4.js → extension-input-K24TVKVW.js} +4 -4
  461. package/dist/node-runtime/{extension-selector-X5FCX43D.js → extension-selector-SPNF7EDR.js} +4 -4
  462. package/dist/node-runtime/{extract-XLQSJN4V.js → extract-EQJE7FZZ.js} +2 -2
  463. package/dist/node-runtime/{gateway-L4ANRTVE.js → gateway-VFO6SFKK.js} +275 -994
  464. package/dist/node-runtime/{gemini-search-U7SUMPQA.js → gemini-search-35OCRFLN.js} +1 -1
  465. package/dist/node-runtime/{gemini-url-context-PXWCBQHK.js → gemini-url-context-UQY3PHHW.js} +2 -2
  466. package/dist/node-runtime/index.js +105 -64
  467. package/dist/node-runtime/{init-3C7Z24OI.js → init-X2LIUB2H.js} +3 -3
  468. package/dist/node-runtime/{install-cli-EXMJQESX.js → install-cli-C3CF7O7N.js} +21 -82
  469. package/dist/node-runtime/interactive-mode-LOM6AIF6.js +72 -0
  470. package/dist/node-runtime/{interactive-view-ILS6TAN5.js → interactive-view-IDSCPPK7.js} +8 -8
  471. package/dist/node-runtime/lunr-browser-YNW7FTYX.js +87 -0
  472. package/dist/node-runtime/{lunr-cron-NNYTWTGF.js → lunr-cron-BKHGNBKT.js} +19 -5
  473. package/dist/node-runtime/main.js +45 -30
  474. package/dist/node-runtime/{memory-cap-3S4XRLNP.js → memory-cap-EL3KL4JJ.js} +2 -1
  475. package/dist/node-runtime/mobile-commands-HMP25WBC.js +32 -0
  476. package/dist/node-runtime/model-runtime-PLQKAG4B.js +16 -0
  477. package/dist/node-runtime/{model-tiers-NJLHUEGK.js → model-tiers-OU3U5CZG.js} +2 -1
  478. package/dist/node-runtime/{package-manager-cli-7RKSZGEN.js → package-manager-cli-VCK4E2RC.js} +23 -15
  479. package/dist/node-runtime/{pi-intercom-DDQMRNPJ.js → pi-intercom-HBPK5HSJ.js} +38 -34
  480. package/dist/node-runtime/{pi-mcp-adapter-GUFZWW54.js → pi-mcp-adapter-E6WULBKF.js} +4 -4
  481. package/dist/node-runtime/{pi-subagents-T5WMMLBB.js → pi-subagents-FEUDLJOE.js} +476 -412
  482. package/dist/node-runtime/{pi-web-access-2CQGFLT2.js → pi-web-access-WTGMNZ32.js} +15 -15
  483. package/dist/node-runtime/process-registry-4FAKZQOL.js +31 -0
  484. package/dist/node-runtime/{proxy-modes-V6YVFH3C.js → proxy-modes-OSQCWRBI.js} +9 -9
  485. package/dist/node-runtime/rpc-entry.js +46 -31
  486. package/dist/node-runtime/{rpc-mode-W5ZTLTMZ.js → rpc-mode-P5ODXPEG.js} +2 -2
  487. package/dist/node-runtime/runtime-4VA6JKNF.js +373 -0
  488. package/dist/node-runtime/{runtime-bridges-NJQERQ72.js → runtime-bridges-3XUQ46XW.js} +6 -5
  489. package/dist/node-runtime/service-ISSP6VHE.js +36 -0
  490. package/dist/node-runtime/session-handoff-HC7R5E24.js +33 -0
  491. package/dist/node-runtime/{session-manager-E7AREDTV.js → session-manager-CFN4UFM2.js} +2 -1
  492. package/dist/node-runtime/{session-selector-FJ7M2AIX.js → session-selector-LHRMJOKT.js} +5 -4
  493. package/dist/node-runtime/{settings-manager-GHPTUN7R.js → settings-manager-UUZ6NUXI.js} +8 -2
  494. package/dist/node-runtime/setup-JBKOLJ6F.js +18 -0
  495. package/dist/node-runtime/setup-NRXVZBLJ.js +155 -0
  496. package/dist/node-runtime/{subagent-executor-SRFC26SJ.js → subagent-executor-MLUMBWCP.js} +35 -63
  497. package/dist/node-runtime/theme-U7IGOA7O.js +68 -0
  498. package/dist/node-runtime/trust-manager-MMISNCYO.js +17 -0
  499. package/dist/node-runtime/{update-cli-L3JIBH2U.js → update-cli-4TP25CNW.js} +8 -2
  500. package/dist/node-runtime/usage-service-LFB2SWYV.js +37 -0
  501. package/dist/node-runtime/{video-extract-OYT5WKS5.js → video-extract-OOZHR7SU.js} +2 -2
  502. package/dist/node-runtime/{youtube-extract-TQYKGFGS.js → youtube-extract-FNPAUNHU.js} +6 -6
  503. package/docs/browser.md +86 -0
  504. package/docs/extensions.md +2 -0
  505. package/docs/features.md +99 -17
  506. package/docs/interactive-startup.md +2 -1
  507. package/docs/sessions.md +10 -0
  508. package/docs/settings.md +3 -1
  509. package/docs/tui.md +2 -0
  510. package/docs/usage.md +16 -0
  511. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  512. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  513. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  514. package/examples/extensions/gondolin/package-lock.json +2 -2
  515. package/examples/extensions/gondolin/package.json +1 -1
  516. package/examples/extensions/sandbox/package-lock.json +2 -2
  517. package/examples/extensions/sandbox/package.json +1 -1
  518. package/examples/extensions/with-deps/package-lock.json +2 -2
  519. package/examples/extensions/with-deps/package.json +1 -1
  520. package/package.json +7 -4
  521. package/scripts/install-browser.mjs +20 -0
  522. package/dist/node-runtime/agent-session-services-75JKASCW.js +0 -36
  523. package/dist/node-runtime/chunk-HQCKFM2O.js +0 -56
  524. package/dist/node-runtime/command-RBTRL55A.js +0 -13
  525. package/dist/node-runtime/interactive-mode-HPUNH7SV.js +0 -57
  526. package/dist/node-runtime/{chunk-UWQYRSYQ.js → chunk-YJMMG7C6.js} +25 -25
  527. package/dist/node-runtime/{mcp-panel-IIGMXQGP.js → mcp-panel-KTTFXJZ4.js} +3 -3
  528. package/dist/node-runtime/{src-BPQFJR76.js → src-IVPNZ2BX.js} +9 -9
@@ -0,0 +1,422 @@
1
+ import { mkdirSync, readdirSync, realpathSync, statSync } from "node:fs";
2
+ import { basename, dirname, isAbsolute, join, relative, resolve } from "node:path";
3
+ import { getPermissionMode, PERMISSION_MODES, setPermissionMode } from "../core/permissions.js";
4
+ import { SessionManager } from "../core/session-manager.js";
5
+ import { getSubagentCancellation } from "../core/subagent-cancellation.js";
6
+ import { isGatewayOwner, requireGatewayOwner } from "./authz.js";
7
+ import { createPicker } from "./buttons.js";
8
+ import { loadGatewayConfig } from "./config.js";
9
+ import { bindConversation, conversationBinding } from "./conversations.js";
10
+ import { gatewayInput, gatewaySelect } from "./presenter.js";
11
+ export const MOBILE_COMMANDS = [
12
+ { name: "project", description: "Browse folders and choose a project" },
13
+ { name: "continue", description: "Continue a handoff or the latest TUI session" },
14
+ { name: "sessions", description: "Browse saved sessions across projects" },
15
+ { name: "mode", description: "Choose manual, yolo, plan, or auto permissions" },
16
+ { name: "plan", description: "Plan work and approve it from this chat" },
17
+ { name: "settings", description: "Change this session's model, thinking, or permissions" },
18
+ { name: "stopall", description: "Stop this session and its background subagents" },
19
+ { name: "download", description: "Send a file from the current project" },
20
+ { name: "usage", description: "Show session tokens and subscription usage" },
21
+ { name: "processes", description: "List or stop this session's shell processes" },
22
+ { name: "refresh", description: "Refresh available models" },
23
+ { name: "skill", description: "Choose a skill and send it a task" },
24
+ { name: "fast", description: "Toggle OpenAI Codex fast mode" },
25
+ ];
26
+ export const FORWARDED_COMMANDS = [
27
+ { name: "goal", description: "Set or manage the session goal" },
28
+ { name: "cron", description: "Schedule prompts and manage scheduled jobs" },
29
+ { name: "run", description: "Launch a subagent task" },
30
+ { name: "chain", description: "Run a sequence of subagent tasks" },
31
+ { name: "parallel", description: "Run independent subagent tasks" },
32
+ { name: "mcp", description: "Show configured MCP servers" },
33
+ { name: "lsp", description: "Show language server status" },
34
+ ];
35
+ export function resolveWithinRoots(path, roots) {
36
+ const actual = realpathSync(resolve(path));
37
+ if (!roots.some((root) => {
38
+ try {
39
+ const rel = relative(realpathSync(root), actual);
40
+ return (rel === "" ||
41
+ (!rel.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`) && rel !== ".." && !isAbsolute(rel)));
42
+ }
43
+ catch {
44
+ return false;
45
+ }
46
+ }))
47
+ throw new Error("That path is outside the approved folders.");
48
+ return actual;
49
+ }
50
+ export function createProjectFolder(parent, name, roots) {
51
+ if (!name ||
52
+ name === "." ||
53
+ name === ".." ||
54
+ /[\\/\x00-\x1f<>:"|?*]/.test(name) ||
55
+ /[. ]$/.test(name) ||
56
+ /^(con|prn|aux|nul|com\d|lpt\d)(\.|$)/i.test(name))
57
+ throw new Error("Use a simple folder name without slashes or reserved characters.");
58
+ const actual = resolveWithinRoots(parent, roots);
59
+ mkdirSync(join(actual, name));
60
+ return resolveWithinRoots(join(actual, name), roots);
61
+ }
62
+ async function browseProject(ctx, initialPath) {
63
+ const { key, event, adapter, bridge } = ctx;
64
+ const roots = ctx.cfg.projectRoots ?? [];
65
+ if (!roots.length)
66
+ throw new Error("Add approved project folders with lunr gateway setup first.");
67
+ let current = initialPath
68
+ ? resolveWithinRoots(initialPath, ctx.cfg.projectRoots ?? [])
69
+ : undefined;
70
+ const view = () => {
71
+ if (!current)
72
+ return {
73
+ title: "Choose a project folder",
74
+ items: [...new Set([...(conversationBinding(key)?.recentProjects ?? []), ...roots])]
75
+ .filter((p) => {
76
+ try {
77
+ resolveWithinRoots(p, roots);
78
+ return true;
79
+ }
80
+ catch {
81
+ return false;
82
+ }
83
+ })
84
+ .map((p) => ({ label: p, value: p })),
85
+ };
86
+ current = resolveWithinRoots(current, roots);
87
+ const items = [
88
+ { label: "Use this folder", value: "use" },
89
+ { label: "New folder", value: "new" },
90
+ { label: "Recent and roots", value: "roots" },
91
+ ];
92
+ try {
93
+ const up = resolveWithinRoots(dirname(current), roots);
94
+ if (up !== current)
95
+ items.push({ label: "Up", value: up });
96
+ }
97
+ catch { }
98
+ for (const item of readdirSync(current, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
99
+ if (!item.isDirectory() && !item.isSymbolicLink())
100
+ continue;
101
+ try {
102
+ const path = resolveWithinRoots(join(current, item.name), roots);
103
+ if (statSync(path).isDirectory())
104
+ items.push({ label: item.name, value: path });
105
+ }
106
+ catch { }
107
+ }
108
+ return { title: current, items };
109
+ };
110
+ const initial = view();
111
+ await createPicker(adapter, event.source, {
112
+ kind: "project",
113
+ sessionKey: key,
114
+ invokerId: event.source.userId,
115
+ ...initial,
116
+ validate: () => isGatewayOwner(event.source, loadGatewayConfig()),
117
+ resolve: async (item) => {
118
+ requireGatewayOwner(event.source);
119
+ if (item.value === "use" && current) {
120
+ const cwd = resolveWithinRoots(current, loadGatewayConfig().projectRoots ?? []);
121
+ if (bridge.getStatus(key).busy)
122
+ throw new Error("Stop the current turn or wait before switching projects.");
123
+ await bridge.reset(key);
124
+ bindConversation(key, event.source, { cwd, owner: event.source.userId });
125
+ return {
126
+ done: true,
127
+ text: `Project selected: ${cwd}\nSend a task to begin. Existing sessions are still available through /sessions.`,
128
+ };
129
+ }
130
+ if (item.value === "new" && current) {
131
+ const name = await gatewayInput(key, "New folder name");
132
+ if (name)
133
+ current = createProjectFolder(current, name, loadGatewayConfig().projectRoots ?? []);
134
+ }
135
+ else
136
+ current = item.value === "roots" ? undefined : item.value;
137
+ return { done: false, ...view() };
138
+ },
139
+ }, { threadId: event.source.threadId });
140
+ }
141
+ const transfers = new Map();
142
+ export function cancelMobileTransfer(key) {
143
+ transfers.get(key)?.abort();
144
+ }
145
+ async function continueSession(ctx, file) {
146
+ if (transfers.has(ctx.key))
147
+ throw new Error("A session transfer is already pending. Use /stop to cancel it.");
148
+ const controller = new AbortController();
149
+ transfers.set(ctx.key, controller);
150
+ try {
151
+ await performContinue(ctx, file, controller.signal);
152
+ }
153
+ finally {
154
+ transfers.delete(ctx.key);
155
+ }
156
+ }
157
+ async function performContinue(ctx, file, signal) {
158
+ requireGatewayOwner(ctx.event.source);
159
+ const { requestSessionTransfer, SessionTransferError } = await import("../core/session-handoff.js");
160
+ const { key, bridge } = ctx;
161
+ const current = await bridge.getSession(key);
162
+ if (current?.sessionManager?.getSessionFile() === file) {
163
+ await ctx.adapter.send(ctx.event.source.chatId, "This session is already open here.");
164
+ return;
165
+ }
166
+ if (bridge.getStatus(key).busy)
167
+ throw new Error("Stop the current phone session before switching.");
168
+ try {
169
+ await requestSessionTransfer(file, { timeoutMs: 3000, signal });
170
+ }
171
+ catch (error) {
172
+ if (!(error instanceof SessionTransferError) || error.code !== "busy")
173
+ throw error;
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
+ if (!choice || choice === "Cancel")
176
+ return;
177
+ if (choice === "Stop and continue")
178
+ await requestSessionTransfer(file, { stop: true, timeoutMs: 30_000, signal });
179
+ else {
180
+ const deadline = Date.now() + 120_000;
181
+ for (;;) {
182
+ signal.throwIfAborted();
183
+ requireGatewayOwner(ctx.event.source);
184
+ try {
185
+ await requestSessionTransfer(file, { timeoutMs: 3000, signal });
186
+ break;
187
+ }
188
+ catch (retryError) {
189
+ if (!(retryError instanceof SessionTransferError) ||
190
+ retryError.code !== "busy" ||
191
+ Date.now() >= deadline)
192
+ throw retryError;
193
+ }
194
+ await new Promise((resolve) => setTimeout(resolve, 500));
195
+ }
196
+ }
197
+ }
198
+ signal.throwIfAborted();
199
+ requireGatewayOwner(ctx.event.source);
200
+ await bridge.switchSession(key, file);
201
+ const session = await bridge.getSession(key);
202
+ const cwd = session?.sessionManager?.getCwd();
203
+ bindConversation(key, ctx.event.source, { cwd, owner: ctx.event.source.userId });
204
+ const id = session?.sessionManager?.getSessionId();
205
+ if (id && ["auto", "yolo"].includes(getPermissionMode(id))) {
206
+ const requested = getPermissionMode(id);
207
+ setPermissionMode("manual", id);
208
+ session?.sessionManager?.setPermissionMode?.("manual");
209
+ if ((await gatewaySelect(key, `Continue with ${requested} permissions? Tools can change files and run commands without individual approval.`, ["Keep manual", `Use ${requested}`])) === `Use ${requested}`) {
210
+ setPermissionMode(requested, id);
211
+ session?.sessionManager?.setPermissionMode?.(requested);
212
+ }
213
+ }
214
+ await ctx.adapter.send(ctx.event.source.chatId, `Continuing ${session?.sessionManager?.getSessionName() ?? basename(file)}\nProject: ${cwd}\nSend your next instruction.`, { threadId: ctx.event.source.threadId });
215
+ }
216
+ async function browseSessions(ctx, args, quick) {
217
+ const handoff = await import("../core/session-handoff.js");
218
+ if (quick) {
219
+ const candidates = handoff.listHandoffCandidates();
220
+ if (!candidates.length) {
221
+ const latest = handoff.latestTuiSession();
222
+ if (!latest)
223
+ throw new Error("No recent TUI session found. Use /sessions or mark one in the terminal with /handoff.");
224
+ await continueSession(ctx, latest.sessionFile);
225
+ return;
226
+ }
227
+ if (candidates.length === 1) {
228
+ await continueSession(ctx, candidates[0].sessionFile);
229
+ return;
230
+ }
231
+ await sessionPicker(ctx, candidates.map((s) => ({ label: `${s.cwd} · ${basename(s.sessionFile)}`, value: s.sessionFile })));
232
+ return;
233
+ }
234
+ const sessions = await SessionManager.listAll();
235
+ const known = new Set(sessions.map((s) => s.path));
236
+ for (const file of handoff.listRegisteredSessionPaths()) {
237
+ if (known.has(file))
238
+ continue;
239
+ try {
240
+ const manager = SessionManager.openReadOnly(file);
241
+ const header = manager.getHeader();
242
+ if (header)
243
+ sessions.push({
244
+ id: header.id,
245
+ path: file,
246
+ cwd: manager.getCwd(),
247
+ name: manager.getSessionName(),
248
+ created: new Date(header.timestamp),
249
+ modified: statSync(file).mtime,
250
+ messageCount: manager.getEntries().length,
251
+ firstMessage: "",
252
+ allMessagesText: "",
253
+ });
254
+ }
255
+ catch { }
256
+ }
257
+ const query = args.toLowerCase();
258
+ const items = sessions
259
+ .sort((a, b) => b.modified.getTime() - a.modified.getTime())
260
+ .filter((s) => !query || `${s.name ?? ""} ${s.cwd} ${s.id}`.toLowerCase().includes(query))
261
+ .map((s) => ({
262
+ label: `${s.name || s.firstMessage.slice(0, 35) || s.id.slice(0, 8)} · ${basename(s.cwd)} · ${s.modified.toLocaleDateString()}`,
263
+ value: s.path,
264
+ }));
265
+ await sessionPicker(ctx, items);
266
+ }
267
+ async function sessionPicker(ctx, items) {
268
+ await createPicker(ctx.adapter, ctx.event.source, {
269
+ kind: "sessions",
270
+ sessionKey: ctx.key,
271
+ invokerId: ctx.event.source.userId,
272
+ title: "Choose a session. Use /sessions <search> to filter.",
273
+ items,
274
+ validate: () => isGatewayOwner(ctx.event.source, loadGatewayConfig()),
275
+ resolve: async (item) => {
276
+ await continueSession(ctx, item.value);
277
+ return { done: true, text: "Session selection finished." };
278
+ },
279
+ }, { threadId: ctx.event.source.threadId });
280
+ }
281
+ export async function handleMobileCommand(ctx, command, args) {
282
+ if (!MOBILE_COMMANDS.some((c) => c.name === command) && command !== "resume")
283
+ return false;
284
+ requireGatewayOwner(ctx.event.source, ctx.cfg);
285
+ bindConversation(ctx.key, ctx.event.source, { owner: ctx.event.source.userId });
286
+ if (command === "project") {
287
+ await browseProject(ctx, args.trim() || undefined);
288
+ return true;
289
+ }
290
+ if (command === "sessions" || command === "resume" || command === "continue") {
291
+ await browseSessions(ctx, args, command === "continue");
292
+ return true;
293
+ }
294
+ const session = await ctx.bridge.getSession(ctx.key);
295
+ if (!session)
296
+ throw new Error("Select a project and send a task, or use /continue first.");
297
+ const id = session.sessionManager?.getSessionId();
298
+ if (command === "usage") {
299
+ const stats = session.getSessionStats();
300
+ const plans = await (await import("../core/usage-service.js")).getAllPlanUsageResults(session.model?.provider, session.modelRuntime);
301
+ await ctx.adapter.send(ctx.event.source.chatId, [
302
+ `Tokens: ${stats.tokens.total} · cost: $${stats.cost.toFixed(4)}`,
303
+ ...plans.usages.flatMap((p) => p.windows.map((w) => `${p.provider} ${w.label}: ${w.usedPercent.toFixed(1)}% used`)),
304
+ ...plans.errors,
305
+ ].join("\n"));
306
+ return true;
307
+ }
308
+ if (command === "processes") {
309
+ if (!id)
310
+ throw new Error("No session identity.");
311
+ const processes = await import("../core/process-registry.js");
312
+ const own = processes.list(id);
313
+ if (args) {
314
+ const [action, raw] = args.split(/\s+/);
315
+ const pid = Number(raw);
316
+ if (action !== "stop" || !own.some((p) => p.pid === pid))
317
+ throw new Error("Usage: /processes stop <pid> from this session's process list.");
318
+ processes.kill(pid);
319
+ await ctx.adapter.send(ctx.event.source.chatId, `Stop requested for process ${pid}.`);
320
+ }
321
+ else
322
+ await ctx.adapter.send(ctx.event.source.chatId, own.length
323
+ ? own
324
+ .map((p) => `${p.pid} · ${p.status} · ${p.command}`)
325
+ .join("\n")
326
+ .slice(0, ctx.adapter.maxMessageLength)
327
+ : "No tracked processes.");
328
+ return true;
329
+ }
330
+ if (command === "stopall") {
331
+ await ctx.bridge.abort(ctx.key);
332
+ const result = id ? await getSubagentCancellation(id)?.stop() : undefined;
333
+ const processes = await import("../core/process-registry.js");
334
+ const count = id ? processes.list(id).filter((p) => p.status !== "exited").length : 0;
335
+ if (id)
336
+ processes.killAll(id);
337
+ await ctx.adapter.send(ctx.event.source.chatId, `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.`);
338
+ return true;
339
+ }
340
+ if (ctx.bridge.getStatus(ctx.key).busy)
341
+ throw new Error("Wait for the current turn or use /stop first.");
342
+ if (command === "refresh") {
343
+ await session.modelRuntime.refresh();
344
+ await ctx.adapter.send(ctx.event.source.chatId, "Model catalog refreshed. Use /model to choose.");
345
+ return true;
346
+ }
347
+ if (command === "fast") {
348
+ if (session.model?.provider !== "openai-codex" || !session.settingsManager)
349
+ throw new Error("Fast mode is available only for OpenAI Codex subscriptions.");
350
+ const current = session.settingsManager.getOpenAIFastMode();
351
+ if (args && !["on", "off", "status"].includes(args))
352
+ throw new Error("Usage: /fast on|off|status");
353
+ if (args !== "status")
354
+ session.settingsManager.setOpenAIFastMode(args ? args === "on" : !current);
355
+ await ctx.adapter.send(ctx.event.source.chatId, `Fast mode: ${session.settingsManager.getOpenAIFastMode() ? "on" : "off"}`);
356
+ return true;
357
+ }
358
+ if (command === "skill") {
359
+ const names = session.resourceLoader?.getSkills().skills.map((s) => s.name) ?? [];
360
+ const [name, ...task] = args.split(/\s+/).filter(Boolean);
361
+ const chosen = name || (await gatewaySelect(ctx.key, "Choose a skill", names));
362
+ if (!chosen)
363
+ return true;
364
+ if (!names.includes(chosen))
365
+ throw new Error("That skill is not loaded for this project.");
366
+ ctx.event.text = `/skill:${chosen} ${task.join(" ") || (await gatewayInput(ctx.key, "What should this skill do?")) || ""}`;
367
+ return false;
368
+ }
369
+ if (command === "download") {
370
+ if (!ctx.adapter.sendFile)
371
+ throw new Error("This platform cannot send files.");
372
+ if (!args)
373
+ throw new Error("Usage: /download <project-relative path>");
374
+ const cwd = session.sessionManager?.getCwd();
375
+ if (!cwd)
376
+ throw new Error("No project selected.");
377
+ const file = resolveWithinRoots(resolve(cwd, args), [cwd]);
378
+ const stat = statSync(file);
379
+ if (!stat.isFile() || stat.size > 8 * 1024 * 1024)
380
+ throw new Error("Choose a file no larger than 8 MB.");
381
+ if (/(^|[\\/])(?:\.env(?:\.[^\\/]*)?|auth\.json|gateway\.json|credentials[^\\/]*|id_rsa|id_ed25519)([\\/]|$)/i.test(file))
382
+ throw new Error("Credential files cannot be sent through chat.");
383
+ const result = await ctx.adapter.sendFile(ctx.event.source.chatId, file, { threadId: ctx.event.source.threadId });
384
+ if (!result.success)
385
+ throw new Error(result.error ?? "File delivery failed.");
386
+ return true;
387
+ }
388
+ if (command === "settings") {
389
+ const choice = await gatewaySelect(ctx.key, "Session settings", ["Model", "Thinking", "Permissions"]);
390
+ if (choice === "Model" || choice === "Thinking") {
391
+ const { CHAT_COMMANDS, runChatCommand } = await import("./commands.js");
392
+ const cmd = CHAT_COMMANDS.find((c) => c.name === choice.toLowerCase());
393
+ if (cmd)
394
+ await runChatCommand(cmd, {
395
+ ...ctx,
396
+ args: "",
397
+ reply: async (text) => {
398
+ await ctx.adapter.send(ctx.event.source.chatId, text);
399
+ },
400
+ });
401
+ return true;
402
+ }
403
+ if (choice !== "Permissions")
404
+ return true;
405
+ }
406
+ const requested = command === "plan"
407
+ ? "plan"
408
+ : args || (await gatewaySelect(ctx.key, `Permission mode: ${getPermissionMode(id)}`, [...PERMISSION_MODES]));
409
+ if (!requested)
410
+ return true;
411
+ if (!PERMISSION_MODES.includes(requested))
412
+ throw new Error("Choose manual, yolo, plan, or auto.");
413
+ setPermissionMode(requested, id);
414
+ session.sessionManager?.setPermissionMode?.(requested);
415
+ await ctx.adapter.send(ctx.event.source.chatId, `Permission mode: ${requested}`);
416
+ if (command === "plan" && args) {
417
+ ctx.event.text = args;
418
+ return false;
419
+ }
420
+ return true;
421
+ }
422
+ //# sourceMappingURL=mobile-commands.js.map
@@ -0,0 +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 manual, yolo, plan, or auto 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(\"manual\", id);\n\t\tsession?.sessionManager?.setPermissionMode?.(\"manual\");\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 manual\", `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? \"plan\"\n\t\t\t: args || (await gatewaySelect(ctx.key, `Permission mode: ${getPermissionMode(id)}`, [...PERMISSION_MODES]));\n\tif (!requested) return true;\n\tif (!PERMISSION_MODES.includes(requested as (typeof PERMISSION_MODES)[number]))\n\t\tthrow new Error(\"Choose manual, yolo, plan, or auto.\");\n\tsetPermissionMode(requested as (typeof PERMISSION_MODES)[number], id);\n\tsession.sessionManager?.setPermissionMode?.(requested as (typeof PERMISSION_MODES)[number]);\n\tawait ctx.adapter.send(ctx.event.source.chatId, `Permission mode: ${requested}`);\n\tif (command === \"plan\" && args) {\n\t\tctx.event.text = args;\n\t\treturn false;\n\t}\n\treturn true;\n}\n"]}
@@ -0,0 +1,16 @@
1
+ import type { ExtensionUIContext, ExtensionUIDialogOptions } from "../core/extensions/types.ts";
2
+ import type { MessageEvent, PlatformAdapter } from "./types.ts";
3
+ export declare function gatewayDestination(key: string): {
4
+ adapter: PlatformAdapter;
5
+ source: MessageEvent["source"];
6
+ };
7
+ export declare function withGatewayPresentation<T>(key: string, run: () => Promise<T>): Promise<T>;
8
+ export declare function startGatewayPresenter(connected: Map<string, PlatformAdapter>): void;
9
+ export declare function stopGatewayPresenter(): void;
10
+ export declare function sendGatewayNotice(key: string, text: string): Promise<void>;
11
+ export declare function invalidateGatewayDialogs(key: string): void;
12
+ export declare function acceptGatewayInput(key: string, event: MessageEvent): boolean;
13
+ export declare function gatewaySelect(key: string, title: string, options: string[], opts?: ExtensionUIDialogOptions): Promise<string | undefined>;
14
+ export declare function gatewayInput(key: string, title: string, placeholder?: string, opts?: ExtensionUIDialogOptions): Promise<string | undefined>;
15
+ export declare function createGatewayUI(key: string): ExtensionUIContext;
16
+ //# sourceMappingURL=presenter.d.ts.map
@@ -0,0 +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"]}