@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
@@ -1 +1 @@
1
- {"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/gateway/service.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawn, spawnSync } from \"node:child_process\";\nimport { createHash, randomUUID } from \"node:crypto\";\nimport { existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from \"node:fs\";\nimport { homedir, userInfo } from \"node:os\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { getAgentDir } from \"../config.ts\";\n\nexport type StartupMode = \"off\" | \"login\" | \"boot\";\nexport interface GatewayServiceSettings {\n\tstartup: StartupMode;\n}\nexport interface GatewayRuntimeStatus {\n\tversion: 1;\n\tinstance: string;\n\tpid: number;\n\tstartedAt: string;\n\tupdatedAt: string;\n\tstate: \"starting\" | \"ready\" | \"stopping\";\n\tplatforms: Record<string, string>;\n}\nconst servicePrefix = \"lunr-gateway\";\nexport const serviceDirectory = () => join(getAgentDir(), \"gateway-service\");\nexport const gatewayLogPath = () => join(serviceDirectory(), \"gateway.log\");\nconst statusPath = () => join(serviceDirectory(), \"status.json\");\nconst controlPath = () => join(serviceDirectory(), \"control.json\");\nconst settingsPath = () => join(serviceDirectory(), \"service.json\");\n\nexport function atomicJson(path: string, value: unknown): void {\n\tmkdirSync(dirname(path), { recursive: true, mode: 0o700 });\n\tconst temp = `${path}.${randomUUID()}.tmp`;\n\twriteFileSync(temp, `${JSON.stringify(value, null, 2)}\\n`, { mode: 0o600 });\n\trenameSync(temp, path);\n}\n\nfunction readJson(path: string): unknown {\n\ttry {\n\t\treturn JSON.parse(readFileSync(path, \"utf8\"));\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nexport function loadServiceSettings(): GatewayServiceSettings {\n\tconst raw = readJson(settingsPath());\n\tif (raw && typeof raw === \"object\" && \"startup\" in raw && (raw.startup === \"login\" || raw.startup === \"boot\")) {\n\t\treturn { startup: raw.startup };\n\t}\n\treturn { startup: \"off\" };\n}\n\nexport function processExists(pid: number): boolean {\n\tif (!Number.isSafeInteger(pid) || pid <= 0) return false;\n\ttry {\n\t\tprocess.kill(pid, 0);\n\t\treturn true;\n\t} catch (error) {\n\t\treturn !(error && typeof error === \"object\" && \"code\" in error && error.code === \"ESRCH\");\n\t}\n}\n\nexport function readGatewayStatus(file = statusPath()): GatewayRuntimeStatus | undefined {\n\tconst raw = readJson(file);\n\tif (\n\t\t!raw ||\n\t\ttypeof raw !== \"object\" ||\n\t\t!(\"version\" in raw) ||\n\t\traw.version !== 1 ||\n\t\t!(\"pid\" in raw) ||\n\t\ttypeof raw.pid !== \"number\"\n\t)\n\t\treturn undefined;\n\tif (\n\t\t!(\"instance\" in raw) ||\n\t\ttypeof raw.instance !== \"string\" ||\n\t\t!(\"updatedAt\" in raw) ||\n\t\ttypeof raw.updatedAt !== \"string\"\n\t)\n\t\treturn undefined;\n\tif (!(\"state\" in raw) || ![\"starting\", \"ready\", \"stopping\"].includes(String(raw.state))) return undefined;\n\tif (\n\t\t!(\"platforms\" in raw) ||\n\t\t!raw.platforms ||\n\t\ttypeof raw.platforms !== \"object\" ||\n\t\t!(\"startedAt\" in raw) ||\n\t\ttypeof raw.startedAt !== \"string\"\n\t)\n\t\treturn undefined;\n\treturn raw as GatewayRuntimeStatus;\n}\n\nexport function gatewayIsRunning(): boolean {\n\tconst status = readGatewayStatus();\n\treturn !!status && processExists(status.pid);\n}\n\nexport function claimGateway(onStop: () => void): {\n\tupdate: (platforms: Record<string, string>, state?: GatewayRuntimeStatus[\"state\"]) => void;\n\trelease: () => void;\n} {\n\tconst dir = serviceDirectory();\n\tmkdirSync(dir, { recursive: true, mode: 0o700 });\n\tconst lock = join(dir, \"lock\");\n\ttry {\n\t\tmkdirSync(lock);\n\t} catch (error) {\n\t\tif (!error || typeof error !== \"object\" || !(\"code\" in error) || error.code !== \"EEXIST\") throw error;\n\t\tconst previous = readGatewayStatus(join(lock, \"owner.json\"));\n\t\tif (!previous || processExists(previous.pid))\n\t\t\tthrow new Error(\"Gateway already running or startup lock is unresolved. Run lunr gateway doctor.\");\n\t\t// Recovery is serialized; a late recoverer must not remove a new owner's lock.\n\t\tconst recovery = join(dir, \"recovery\");\n\t\tmkdirSync(recovery);\n\t\ttry {\n\t\t\tconst current = readGatewayStatus(join(lock, \"owner.json\"));\n\t\t\tif (!current || current.instance !== previous.instance || processExists(current.pid))\n\t\t\t\tthrow new Error(\"Gateway ownership changed. Try again.\");\n\t\t\trmSync(lock, { recursive: true });\n\t\t\tmkdirSync(lock);\n\t\t} finally {\n\t\t\trmSync(recovery, { recursive: true, force: true });\n\t\t}\n\t}\n\tconst status: GatewayRuntimeStatus = {\n\t\tversion: 1,\n\t\tinstance: randomUUID(),\n\t\tpid: process.pid,\n\t\tstartedAt: new Date().toISOString(),\n\t\tupdatedAt: new Date().toISOString(),\n\t\tstate: \"starting\",\n\t\tplatforms: {},\n\t};\n\tatomicJson(join(lock, \"owner.json\"), status);\n\tconst save = () => {\n\t\tstatus.updatedAt = new Date().toISOString();\n\t\tatomicJson(statusPath(), status);\n\t};\n\tsave();\n\tlet stopping = false;\n\tconst timer = setInterval(() => {\n\t\tsave();\n\t\tconst control = readJson(controlPath());\n\t\tif (\n\t\t\t!stopping &&\n\t\t\tcontrol &&\n\t\t\ttypeof control === \"object\" &&\n\t\t\t\"instance\" in control &&\n\t\t\tcontrol.instance === status.instance &&\n\t\t\t\"action\" in control &&\n\t\t\tcontrol.action === \"stop\"\n\t\t) {\n\t\t\tstopping = true;\n\t\t\tstatus.state = \"stopping\";\n\t\t\tonStop();\n\t\t}\n\t}, 500);\n\treturn {\n\t\tupdate(platforms, state = \"ready\") {\n\t\t\tstatus.platforms = { ...platforms };\n\t\t\tstatus.state = state;\n\t\t\tsave();\n\t\t},\n\t\trelease() {\n\t\t\tclearInterval(timer);\n\t\t\tif (readGatewayStatus()?.instance === status.instance) {\n\t\t\t\trmSync(statusPath(), { force: true });\n\t\t\t\trmSync(controlPath(), { force: true });\n\t\t\t\trmSync(lock, { recursive: true, force: true });\n\t\t\t}\n\t\t},\n\t};\n}\n\nfunction cliPath(): string {\n\tconst candidate = process.argv[1];\n\tif (candidate && existsSync(candidate)) return resolve(candidate);\n\treturn fileURLToPath(new URL(\"../cli.js\", import.meta.url));\n}\n\nconst sleep = (ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms));\n\nexport async function startGatewayService(): Promise<string> {\n\tif (gatewayIsRunning()) return \"Gateway is already running.\";\n\tmkdirSync(serviceDirectory(), { recursive: true, mode: 0o700 });\n\tconst startup = loadServiceSettings().startup;\n\tif (startup !== \"off\") {\n\t\tconst user = userInfo();\n\t\tconst spec = startupSpec(process.platform, startup, {\n\t\t\thome: homedir(),\n\t\t\tagentDir: getAgentDir(),\n\t\t\tnode: process.execPath,\n\t\t\tcli: cliPath(),\n\t\t\tusername: user.username,\n\t\t\tuid: user.uid,\n\t\t});\n\t\texecute(spec.start);\n\t\tfor (let i = 0; i < 100; i++) {\n\t\t\tif (readGatewayStatus()?.state === \"ready\" && gatewayIsRunning()) return \"Gateway started.\";\n\t\t\tawait sleep(200);\n\t\t}\n\t\tthrow new Error(`Startup service did not become ready. Run lunr gateway doctor and inspect ${gatewayLogPath()}`);\n\t}\n\tconst { openSync, closeSync } = await import(\"node:fs\");\n\tconst log = openSync(gatewayLogPath(), \"a\", 0o600);\n\tconst child = spawn(process.execPath, [cliPath(), \"gateway\", \"run\"], {\n\t\tcwd: homedir(),\n\t\tdetached: true,\n\t\twindowsHide: true,\n\t\tstdio: [\"ignore\", log, log],\n\t\tenv: { ...process.env, PI_CODING_AGENT_DIR: getAgentDir() },\n\t});\n\tcloseSync(log);\n\tlet spawnError: Error | undefined;\n\tchild.on(\"error\", (error) => {\n\t\tspawnError = error;\n\t});\n\tchild.unref();\n\tfor (let i = 0; i < 100; i++) {\n\t\tif (spawnError) throw spawnError;\n\t\tconst status = readGatewayStatus();\n\t\tif (status && status.pid === child.pid && status.state === \"ready\") return \"Gateway started.\";\n\t\tif (child.exitCode !== null)\n\t\t\tthrow new Error(`Gateway exited with code ${child.exitCode}. See ${gatewayLogPath()}`);\n\t\tawait sleep(200);\n\t}\n\tthrow new Error(`Gateway did not become ready within 20 seconds. Check lunr gateway status and ${gatewayLogPath()}`);\n}\n\nexport async function stopGatewayService(): Promise<string> {\n\tconst status = readGatewayStatus();\n\tif (!status || !processExists(status.pid)) return \"Gateway is not running.\";\n\tatomicJson(controlPath(), { instance: status.instance, action: \"stop\" });\n\tfor (let i = 0; i < 150; i++) {\n\t\tif (readGatewayStatus()?.instance !== status.instance || !processExists(status.pid)) return \"Gateway stopped.\";\n\t\tawait sleep(200);\n\t}\n\tthrow new Error(\"Gateway is still stopping after 30 seconds. Inspect the log; no unrelated process was terminated.\");\n}\n\nexport interface StartupSpec {\n\tpath: string;\n\tcontent: string;\n\tinstall: string[][];\n\tremove: string[][];\n\tverify: string[];\n\tstart: string[];\n}\nfunction xml(value: string): string {\n\treturn value.replaceAll(\"&\", \"&amp;\").replaceAll(\"<\", \"&lt;\").replaceAll(\">\", \"&gt;\").replaceAll('\"', \"&quot;\");\n}\nfunction systemdArg(value: string): string {\n\treturn `\"${value.replaceAll(\"%\", \"%%\").replaceAll(\"\\\\\", \"\\\\\\\\\").replaceAll('\"', '\\\\\"')}\"`;\n}\nfunction ps(value: string): string {\n\treturn `'${value.replaceAll(\"'\", \"''\")}'`;\n}\n\nexport function startupSpec(\n\tplatform: NodeJS.Platform,\n\tmode: Exclude<StartupMode, \"off\">,\n\toptions: { home: string; agentDir: string; node: string; cli: string; username: string; uid: number },\n): StartupSpec {\n\tconst { home, agentDir, node, cli, username, uid } = options;\n\tif ([home, agentDir, node, cli, username].some((value) => /[\\r\\n\\0]/.test(value)))\n\t\tthrow new Error(\"Startup paths and account names must not contain control characters.\");\n\tconst suffix = createHash(\"sha256\").update(resolve(agentDir)).digest(\"hex\").slice(0, 10);\n\tconst serviceName = `${servicePrefix}-${suffix}`;\n\tconst log = join(agentDir, \"gateway-service\", \"gateway.log\");\n\tif (platform === \"linux\") {\n\t\tconst path = join(home, \".config\", \"systemd\", \"user\", `${serviceName}.service`);\n\t\treturn {\n\t\t\tpath,\n\t\t\tcontent: `[Unit]\\nDescription=lunR chat gateway\\nAfter=network-online.target\\n\\n[Service]\\nType=simple\\nExecStart=${systemdArg(node)} ${systemdArg(cli)} gateway run\\nWorkingDirectory=${systemdArg(home)}\\nEnvironment=${systemdArg(`PI_CODING_AGENT_DIR=${agentDir}`)}\\nRestart=on-failure\\nRestartSec=5\\nTimeoutStopSec=30\\nStandardOutput=append:${log.replaceAll(\"%\", \"%%\")}\\nStandardError=append:${log.replaceAll(\"%\", \"%%\")}\\nUMask=0077\\n\\n[Install]\\nWantedBy=default.target\\n`,\n\t\t\tinstall: [\n\t\t\t\t...(mode === \"boot\" ? [[\"loginctl\", \"enable-linger\", username]] : []),\n\t\t\t\t[\"systemctl\", \"--user\", \"daemon-reload\"],\n\t\t\t\t[\"systemctl\", \"--user\", \"enable\", `${serviceName}.service`],\n\t\t\t],\n\t\t\tremove: [[\"systemctl\", \"--user\", \"disable\", `${serviceName}.service`]],\n\t\t\tverify: [\"systemctl\", \"--user\", \"is-enabled\", `${serviceName}.service`],\n\t\t\tstart: [\"systemctl\", \"--user\", \"start\", `${serviceName}.service`],\n\t\t};\n\t}\n\tif (platform === \"darwin\") {\n\t\tconst label = `dev.lunr.gateway.${suffix}`;\n\t\tconst path =\n\t\t\tmode === \"boot\"\n\t\t\t\t? `/Library/LaunchDaemons/${label}.plist`\n\t\t\t\t: join(home, \"Library\", \"LaunchAgents\", `${label}.plist`);\n\t\tconst domain = mode === \"boot\" ? \"system\" : `gui/${uid}`;\n\t\tconst command = (args: string[]) => (mode === \"boot\" ? [\"sudo\", \"launchctl\", ...args] : [\"launchctl\", ...args]);\n\t\treturn {\n\t\t\tpath,\n\t\t\tcontent: `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\\n<plist version=\"1.0\"><dict><key>Label</key><string>${label}</string><key>ProgramArguments</key><array>${[node, cli, \"gateway\", \"run\"].map((v) => `<string>${xml(v)}</string>`).join(\"\")}</array><key>WorkingDirectory</key><string>${xml(home)}</string>${mode === \"boot\" ? `<key>UserName</key><string>${xml(username)}</string>` : \"\"}<key>EnvironmentVariables</key><dict><key>PI_CODING_AGENT_DIR</key><string>${xml(agentDir)}</string><key>HOME</key><string>${xml(home)}</string></dict><key>RunAtLoad</key><true/><key>KeepAlive</key><dict><key>SuccessfulExit</key><false/></dict><key>StandardOutPath</key><string>${xml(log)}</string><key>StandardErrorPath</key><string>${xml(log)}</string></dict></plist>\\n`,\n\t\t\tinstall: [command([\"bootstrap\", domain, path])],\n\t\t\tremove: [command([\"bootout\", `${domain}/${label}`])],\n\t\t\tverify: command([\"print\", `${domain}/${label}`]),\n\t\t\tstart: command([\"kickstart\", `${domain}/${label}`]),\n\t\t};\n\t}\n\tif (platform === \"win32\") {\n\t\tconst path = join(agentDir, \"gateway-service\", \"startup.ps1\");\n\t\tconst content = `$env:PI_CODING_AGENT_DIR = ${ps(agentDir)}\\nSet-Location -LiteralPath ${ps(home)}\\n& ${ps(node)} ${ps(cli)} gateway run *>> ${ps(log)}\\nexit $LASTEXITCODE\\n`;\n\t\tconst action = `New-ScheduledTaskAction -Execute 'powershell.exe' -Argument ${ps(`-NoProfile -NonInteractive -WindowStyle Hidden -ExecutionPolicy Bypass -File \"${path}\"`)}`;\n\t\tconst trigger =\n\t\t\tmode === \"boot\"\n\t\t\t\t? \"New-ScheduledTaskTrigger -AtStartup\"\n\t\t\t\t: `New-ScheduledTaskTrigger -AtLogOn -User ${ps(username)}`;\n\t\tconst register = `$ErrorActionPreference='Stop'; $a=${action}; $t=${trigger}; $s=New-ScheduledTaskSettingsSet -RestartCount 3 -RestartInterval (New-TimeSpan -Minutes 1) -ExecutionTimeLimit ([TimeSpan]::Zero) -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries; ${mode === \"boot\" ? `$c=Get-Credential -UserName ${ps(username)} -Message 'Windows needs your account credentials to run lunR before login'; if(!$c){throw 'Cancelled'}; Register-ScheduledTask -TaskName '${serviceName}' -Action $a -Trigger $t -Settings $s -User $c.UserName -Password $c.GetNetworkCredential().Password -Force | Out-Null` : `Register-ScheduledTask -TaskName '${serviceName}' -Action $a -Trigger $t -Settings $s -User ${ps(username)} -Force | Out-Null`}`;\n\t\tconst command = (script: string) => [\"powershell.exe\", \"-NoProfile\", \"-Command\", script];\n\t\treturn {\n\t\t\tpath,\n\t\t\tcontent,\n\t\t\tinstall: [command(register)],\n\t\t\tremove: [\n\t\t\t\tcommand(\n\t\t\t\t\t`$ErrorActionPreference='Stop'; Unregister-ScheduledTask -TaskName '${serviceName}' -Confirm:$false`,\n\t\t\t\t),\n\t\t\t],\n\t\t\tverify: command(`$ErrorActionPreference='Stop'; Get-ScheduledTask -TaskName '${serviceName}' | Out-Null`),\n\t\t\tstart: command(`$ErrorActionPreference='Stop'; Start-ScheduledTask -TaskName '${serviceName}'`),\n\t\t};\n\t}\n\tthrow new Error(`Automatic startup is not supported on ${platform}. Run lunr gateway start manually.`);\n}\n\nfunction execute(command: string[]): void {\n\tconst [file, ...args] = command;\n\tconst result = spawnSync(file, args, { stdio: \"inherit\", windowsHide: true, timeout: 120_000 });\n\tif (result.error) throw result.error;\n\tif (result.status !== 0) throw new Error(`${file} failed. Check OS permissions and run lunr gateway doctor.`);\n}\n\nexport async function configureStartup(mode: StartupMode): Promise<void> {\n\tconst previous = loadServiceSettings().startup;\n\tif (process.platform === \"linux\" && mode === \"login\") {\n\t\tconst linger = spawnSync(\"loginctl\", [\"show-user\", userInfo().username, \"--property=Linger\", \"--value\"], {\n\t\t\tencoding: \"utf8\",\n\t\t\ttimeout: 10_000,\n\t\t});\n\t\tif (linger.stdout?.trim() === \"yes\")\n\t\t\tthrow new Error(\n\t\t\t\t\"Linux user services already start at boot because lingering is enabled. Choose boot, or disable lingering yourself before choosing login. lunR will not change other user services.\",\n\t\t\t);\n\t}\n\tconst user = userInfo();\n\tconst options = {\n\t\thome: homedir(),\n\t\tagentDir: getAgentDir(),\n\t\tnode: process.execPath,\n\t\tcli: cliPath(),\n\t\tusername: user.username,\n\t\tuid: user.uid,\n\t};\n\tif (previous !== \"off\") {\n\t\tconst old = startupSpec(process.platform, previous, options);\n\t\tfor (const command of old.remove) execute(command);\n\t\tif (process.platform === \"darwin\" && previous === \"boot\") execute([\"sudo\", \"rm\", \"-f\", old.path]);\n\t\telse rmSync(old.path, { force: true });\n\t\tatomicJson(settingsPath(), { startup: \"off\" });\n\t}\n\tif (mode === \"off\") {\n\t\tatomicJson(settingsPath(), { startup: \"off\" });\n\t\treturn;\n\t}\n\tconst spec = startupSpec(process.platform, mode, options);\n\tmkdirSync(serviceDirectory(), { recursive: true, mode: 0o700 });\n\tif (process.platform === \"darwin\" && mode === \"boot\") {\n\t\tconst temporary = join(serviceDirectory(), \"install.plist\");\n\t\twriteFileSync(temporary, spec.content, { mode: 0o600 });\n\t\ttry {\n\t\t\texecute([\"sudo\", \"install\", \"-o\", \"root\", \"-g\", \"wheel\", \"-m\", \"644\", temporary, spec.path]);\n\t\t} finally {\n\t\t\trmSync(temporary, { force: true });\n\t\t}\n\t} else {\n\t\tmkdirSync(dirname(spec.path), { recursive: true, mode: 0o700 });\n\t\twriteFileSync(spec.path, spec.content, { mode: 0o600 });\n\t}\n\tfor (const command of spec.install) execute(command);\n\texecute(spec.verify);\n\tatomicJson(settingsPath(), { startup: mode });\n}\n\nfunction startupVerification(): string {\n\tconst mode = loadServiceSettings().startup;\n\tif (mode === \"off\") return \"\";\n\ttry {\n\t\tconst user = userInfo();\n\t\tconst spec = startupSpec(process.platform, mode, {\n\t\t\thome: homedir(),\n\t\t\tagentDir: getAgentDir(),\n\t\t\tnode: process.execPath,\n\t\t\tcli: cliPath(),\n\t\t\tusername: user.username,\n\t\t\tuid: user.uid,\n\t\t});\n\t\tconst [command, ...args] = spec.verify[0] === \"sudo\" ? spec.verify.slice(1) : spec.verify;\n\t\tconst result = spawnSync(command, args, { encoding: \"utf8\", windowsHide: true, timeout: 5000 });\n\t\treturn result.status === 0 ? \" (native service verified)\" : \" (native service missing or unavailable)\";\n\t} catch {\n\t\treturn \" (native service could not be checked)\";\n\t}\n}\n\nexport function serviceStatusText(): string {\n\tconst status = readGatewayStatus();\n\tconst alive = !!status && processExists(status.pid);\n\tconst fresh = !!status && Date.now() - Date.parse(status.updatedAt) < 5000;\n\treturn [\n\t\t`Gateway: ${alive ? `${status.state}${fresh ? \"\" : \" (not responding)\"}` : \"stopped\"}`,\n\t\t`Automatic startup: ${loadServiceSettings().startup}${startupVerification()}`,\n\t\t...(alive\n\t\t\t? [`PID: ${status.pid}`, ...Object.entries(status.platforms).map(([name, state]) => `${name}: ${state}`)]\n\t\t\t: []),\n\t\t`Log: ${gatewayLogPath()}`,\n\t].join(\"\\n\");\n}\n\nexport function readGatewayLog(): string {\n\ttry {\n\t\treturn readFileSync(gatewayLogPath(), \"utf8\")\n\t\t\t.split(\"\\n\")\n\t\t\t.slice(-100)\n\t\t\t.join(\"\\n\")\n\t\t\t.replace(/bot\\d+:[A-Za-z0-9_-]+/g, \"bot[redacted]\");\n\t} catch {\n\t\treturn \"No gateway log yet.\";\n\t}\n}\n"]}
1
+ {"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/gateway/service.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawn, spawnSync } from \"node:child_process\";\nimport { createHash, randomUUID } from \"node:crypto\";\nimport { existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from \"node:fs\";\nimport { homedir, userInfo } from \"node:os\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { getAgentDir } from \"../config.ts\";\n\nexport type StartupMode = \"off\" | \"login\" | \"boot\";\nexport interface GatewayServiceSettings {\n\tstartup: StartupMode;\n}\nexport interface GatewayRuntimeStatus {\n\tversion: 1;\n\tinstance: string;\n\tpid: number;\n\tstartedAt: string;\n\tupdatedAt: string;\n\tstate: \"starting\" | \"ready\" | \"stopping\";\n\tplatforms: Record<string, string>;\n}\nconst servicePrefix = \"lunr-gateway\";\nexport const serviceDirectory = () => join(getAgentDir(), \"gateway-service\");\nexport const gatewayLogPath = () => join(serviceDirectory(), \"gateway.log\");\nconst statusPath = () => join(serviceDirectory(), \"status.json\");\nconst controlPath = () => join(serviceDirectory(), \"control.json\");\nconst settingsPath = () => join(serviceDirectory(), \"service.json\");\n\nexport function atomicJson(path: string, value: unknown): void {\n\tmkdirSync(dirname(path), { recursive: true, mode: 0o700 });\n\tconst temp = `${path}.${randomUUID()}.tmp`;\n\twriteFileSync(temp, `${JSON.stringify(value, null, 2)}\\n`, { mode: 0o600 });\n\trenameSync(temp, path);\n}\n\nfunction readJson(path: string): unknown {\n\ttry {\n\t\treturn JSON.parse(readFileSync(path, \"utf8\"));\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nexport function loadServiceSettings(): GatewayServiceSettings {\n\tconst raw = readJson(settingsPath());\n\tif (raw && typeof raw === \"object\" && \"startup\" in raw && (raw.startup === \"login\" || raw.startup === \"boot\")) {\n\t\treturn { startup: raw.startup };\n\t}\n\treturn { startup: \"off\" };\n}\n\nexport function processExists(pid: number): boolean {\n\tif (!Number.isSafeInteger(pid) || pid <= 0) return false;\n\ttry {\n\t\tprocess.kill(pid, 0);\n\t\treturn true;\n\t} catch (error) {\n\t\treturn !(error && typeof error === \"object\" && \"code\" in error && error.code === \"ESRCH\");\n\t}\n}\n\nexport function readGatewayStatus(file = statusPath()): GatewayRuntimeStatus | undefined {\n\tconst raw = readJson(file);\n\tif (\n\t\t!raw ||\n\t\ttypeof raw !== \"object\" ||\n\t\t!(\"version\" in raw) ||\n\t\traw.version !== 1 ||\n\t\t!(\"pid\" in raw) ||\n\t\ttypeof raw.pid !== \"number\"\n\t)\n\t\treturn undefined;\n\tif (\n\t\t!(\"instance\" in raw) ||\n\t\ttypeof raw.instance !== \"string\" ||\n\t\t!(\"updatedAt\" in raw) ||\n\t\ttypeof raw.updatedAt !== \"string\"\n\t)\n\t\treturn undefined;\n\tif (!(\"state\" in raw) || ![\"starting\", \"ready\", \"stopping\"].includes(String(raw.state))) return undefined;\n\tif (\n\t\t!(\"platforms\" in raw) ||\n\t\t!raw.platforms ||\n\t\ttypeof raw.platforms !== \"object\" ||\n\t\t!(\"startedAt\" in raw) ||\n\t\ttypeof raw.startedAt !== \"string\"\n\t)\n\t\treturn undefined;\n\treturn raw as GatewayRuntimeStatus;\n}\n\nexport function gatewayIsRunning(): boolean {\n\tconst status = readGatewayStatus();\n\treturn !!status && processExists(status.pid);\n}\n\nexport function claimGateway(onStop: () => void): {\n\tupdate: (platforms: Record<string, string>, state?: GatewayRuntimeStatus[\"state\"]) => void;\n\trelease: () => void;\n} {\n\tconst dir = serviceDirectory();\n\tmkdirSync(dir, { recursive: true, mode: 0o700 });\n\tconst lock = join(dir, \"lock\");\n\ttry {\n\t\tmkdirSync(lock);\n\t} catch (error) {\n\t\tif (!error || typeof error !== \"object\" || !(\"code\" in error) || error.code !== \"EEXIST\") throw error;\n\t\tconst previous = readGatewayStatus(join(lock, \"owner.json\"));\n\t\tif (!previous || processExists(previous.pid))\n\t\t\tthrow new Error(\"Gateway already running or startup lock is unresolved. Run lunr gateway doctor.\");\n\t\t// Recovery is serialized; a late recoverer must not remove a new owner's lock.\n\t\tconst recovery = join(dir, \"recovery\");\n\t\tmkdirSync(recovery);\n\t\ttry {\n\t\t\tconst current = readGatewayStatus(join(lock, \"owner.json\"));\n\t\t\tif (!current || current.instance !== previous.instance || processExists(current.pid))\n\t\t\t\tthrow new Error(\"Gateway ownership changed. Try again.\");\n\t\t\trmSync(lock, { recursive: true });\n\t\t\tmkdirSync(lock);\n\t\t} finally {\n\t\t\trmSync(recovery, { recursive: true, force: true });\n\t\t}\n\t}\n\tconst status: GatewayRuntimeStatus = {\n\t\tversion: 1,\n\t\tinstance: randomUUID(),\n\t\tpid: process.pid,\n\t\tstartedAt: new Date().toISOString(),\n\t\tupdatedAt: new Date().toISOString(),\n\t\tstate: \"starting\",\n\t\tplatforms: {},\n\t};\n\tatomicJson(join(lock, \"owner.json\"), status);\n\tconst save = () => {\n\t\tstatus.updatedAt = new Date().toISOString();\n\t\tatomicJson(statusPath(), status);\n\t};\n\tsave();\n\tlet stopping = false;\n\tconst timer = setInterval(() => {\n\t\tsave();\n\t\tconst control = readJson(controlPath());\n\t\tif (\n\t\t\t!stopping &&\n\t\t\tcontrol &&\n\t\t\ttypeof control === \"object\" &&\n\t\t\t\"instance\" in control &&\n\t\t\tcontrol.instance === status.instance &&\n\t\t\t\"action\" in control &&\n\t\t\tcontrol.action === \"stop\"\n\t\t) {\n\t\t\tstopping = true;\n\t\t\tstatus.state = \"stopping\";\n\t\t\tonStop();\n\t\t}\n\t}, 500);\n\treturn {\n\t\tupdate(platforms, state = \"ready\") {\n\t\t\tif (stopping && state !== \"stopping\") {\n\t\t\t\tstopping = false;\n\t\t\t\tconst control = readJson(controlPath());\n\t\t\t\tif (control && typeof control === \"object\" && \"instance\" in control && control.instance === status.instance)\n\t\t\t\t\trmSync(controlPath(), { force: true });\n\t\t\t}\n\t\t\tstatus.platforms = { ...platforms };\n\t\t\tstatus.state = state;\n\t\t\tsave();\n\t\t},\n\t\trelease() {\n\t\t\tclearInterval(timer);\n\t\t\tif (readGatewayStatus()?.instance === status.instance) {\n\t\t\t\trmSync(statusPath(), { force: true });\n\t\t\t\trmSync(controlPath(), { force: true });\n\t\t\t\trmSync(lock, { recursive: true, force: true });\n\t\t\t}\n\t\t},\n\t};\n}\n\nfunction cliPath(): string {\n\tconst candidate = process.argv[1];\n\tif (candidate && existsSync(candidate)) return resolve(candidate);\n\treturn fileURLToPath(new URL(\"../cli.js\", import.meta.url));\n}\n\nconst sleep = (ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms));\n\nexport async function startGatewayService(): Promise<string> {\n\tif (gatewayIsRunning()) {\n\t\tif (readGatewayStatus()?.state === \"ready\") return \"Gateway is already running.\";\n\t\tthrow new Error(\n\t\t\t`Gateway process is running but no bot is connected. ${serviceStatusText()}\\nInspect ${gatewayLogPath()}`,\n\t\t);\n\t}\n\tmkdirSync(serviceDirectory(), { recursive: true, mode: 0o700 });\n\tconst startup = loadServiceSettings().startup;\n\tif (startup !== \"off\") {\n\t\tconst user = userInfo();\n\t\tconst spec = startupSpec(process.platform, startup, {\n\t\t\thome: homedir(),\n\t\t\tagentDir: getAgentDir(),\n\t\t\tnode: process.execPath,\n\t\t\tcli: cliPath(),\n\t\t\tusername: user.username,\n\t\t\tuid: user.uid,\n\t\t});\n\t\texecute(spec.start);\n\t\tfor (let i = 0; i < 100; i++) {\n\t\t\tif (readGatewayStatus()?.state === \"ready\" && gatewayIsRunning()) return \"Gateway started.\";\n\t\t\tawait sleep(200);\n\t\t}\n\t\tthrow new Error(\n\t\t\t`Startup service did not connect within 20 seconds. ${serviceStatusText()}\\nRun lunr gateway doctor and inspect ${gatewayLogPath()}`,\n\t\t);\n\t}\n\tconst { openSync, closeSync } = await import(\"node:fs\");\n\tconst log = openSync(gatewayLogPath(), \"a\", 0o600);\n\tconst child = spawn(process.execPath, [cliPath(), \"gateway\", \"run\"], {\n\t\tcwd: homedir(),\n\t\tdetached: true,\n\t\twindowsHide: true,\n\t\tstdio: [\"ignore\", log, log],\n\t\tenv: { ...process.env, PI_CODING_AGENT_DIR: getAgentDir() },\n\t});\n\tcloseSync(log);\n\tlet spawnError: Error | undefined;\n\tchild.on(\"error\", (error) => {\n\t\tspawnError = error;\n\t});\n\tchild.unref();\n\tfor (let i = 0; i < 100; i++) {\n\t\tif (spawnError) throw spawnError;\n\t\tconst status = readGatewayStatus();\n\t\tif (status && status.pid === child.pid && status.state === \"ready\") return \"Gateway started.\";\n\t\tif (child.exitCode !== null)\n\t\t\tthrow new Error(`Gateway exited with code ${child.exitCode}. See ${gatewayLogPath()}`);\n\t\tawait sleep(200);\n\t}\n\tthrow new Error(\n\t\t`Gateway did not connect within 20 seconds. ${serviceStatusText()}\\nCheck lunr gateway status and ${gatewayLogPath()}`,\n\t);\n}\n\nexport async function stopGatewayService(): Promise<string> {\n\tconst status = readGatewayStatus();\n\tif (!status || !processExists(status.pid)) return \"Gateway is not running.\";\n\tatomicJson(controlPath(), { instance: status.instance, action: \"stop\" });\n\tfor (let i = 0; i < 150; i++) {\n\t\tif (readGatewayStatus()?.instance !== status.instance || !processExists(status.pid)) return \"Gateway stopped.\";\n\t\tawait sleep(200);\n\t}\n\tthrow new Error(\"Gateway is still stopping after 30 seconds. Inspect the log; no unrelated process was terminated.\");\n}\n\nexport interface StartupSpec {\n\tpath: string;\n\tcontent: string;\n\tinstall: string[][];\n\tremove: string[][];\n\tverify: string[];\n\tstart: string[];\n}\nfunction xml(value: string): string {\n\treturn value.replaceAll(\"&\", \"&amp;\").replaceAll(\"<\", \"&lt;\").replaceAll(\">\", \"&gt;\").replaceAll('\"', \"&quot;\");\n}\nfunction systemdArg(value: string): string {\n\treturn `\"${value.replaceAll(\"%\", \"%%\").replaceAll(\"\\\\\", \"\\\\\\\\\").replaceAll('\"', '\\\\\"')}\"`;\n}\nfunction ps(value: string): string {\n\treturn `'${value.replaceAll(\"'\", \"''\")}'`;\n}\n\nexport function startupSpec(\n\tplatform: NodeJS.Platform,\n\tmode: Exclude<StartupMode, \"off\">,\n\toptions: { home: string; agentDir: string; node: string; cli: string; username: string; uid: number },\n): StartupSpec {\n\tconst { home, agentDir, node, cli, username, uid } = options;\n\tif ([home, agentDir, node, cli, username].some((value) => /[\\r\\n\\0]/.test(value)))\n\t\tthrow new Error(\"Startup paths and account names must not contain control characters.\");\n\tconst suffix = createHash(\"sha256\").update(resolve(agentDir)).digest(\"hex\").slice(0, 10);\n\tconst serviceName = `${servicePrefix}-${suffix}`;\n\tconst log = join(agentDir, \"gateway-service\", \"gateway.log\");\n\tif (platform === \"linux\") {\n\t\tconst path = join(home, \".config\", \"systemd\", \"user\", `${serviceName}.service`);\n\t\treturn {\n\t\t\tpath,\n\t\t\tcontent: `[Unit]\\nDescription=lunR chat gateway\\nAfter=network-online.target\\n\\n[Service]\\nType=simple\\nExecStart=${systemdArg(node)} ${systemdArg(cli)} gateway run\\nWorkingDirectory=${systemdArg(home)}\\nEnvironment=${systemdArg(`PI_CODING_AGENT_DIR=${agentDir}`)}\\nRestart=on-failure\\nRestartSec=5\\nTimeoutStopSec=30\\nStandardOutput=append:${log.replaceAll(\"%\", \"%%\")}\\nStandardError=append:${log.replaceAll(\"%\", \"%%\")}\\nUMask=0077\\n\\n[Install]\\nWantedBy=default.target\\n`,\n\t\t\tinstall: [\n\t\t\t\t...(mode === \"boot\" ? [[\"loginctl\", \"enable-linger\", username]] : []),\n\t\t\t\t[\"systemctl\", \"--user\", \"daemon-reload\"],\n\t\t\t\t[\"systemctl\", \"--user\", \"enable\", `${serviceName}.service`],\n\t\t\t],\n\t\t\tremove: [[\"systemctl\", \"--user\", \"disable\", `${serviceName}.service`]],\n\t\t\tverify: [\"systemctl\", \"--user\", \"is-enabled\", `${serviceName}.service`],\n\t\t\tstart: [\"systemctl\", \"--user\", \"start\", `${serviceName}.service`],\n\t\t};\n\t}\n\tif (platform === \"darwin\") {\n\t\tconst label = `dev.lunr.gateway.${suffix}`;\n\t\tconst path =\n\t\t\tmode === \"boot\"\n\t\t\t\t? `/Library/LaunchDaemons/${label}.plist`\n\t\t\t\t: join(home, \"Library\", \"LaunchAgents\", `${label}.plist`);\n\t\tconst domain = mode === \"boot\" ? \"system\" : `gui/${uid}`;\n\t\tconst command = (args: string[]) => (mode === \"boot\" ? [\"sudo\", \"launchctl\", ...args] : [\"launchctl\", ...args]);\n\t\treturn {\n\t\t\tpath,\n\t\t\tcontent: `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\\n<plist version=\"1.0\"><dict><key>Label</key><string>${label}</string><key>ProgramArguments</key><array>${[node, cli, \"gateway\", \"run\"].map((v) => `<string>${xml(v)}</string>`).join(\"\")}</array><key>WorkingDirectory</key><string>${xml(home)}</string>${mode === \"boot\" ? `<key>UserName</key><string>${xml(username)}</string>` : \"\"}<key>EnvironmentVariables</key><dict><key>PI_CODING_AGENT_DIR</key><string>${xml(agentDir)}</string><key>HOME</key><string>${xml(home)}</string></dict><key>RunAtLoad</key><true/><key>KeepAlive</key><dict><key>SuccessfulExit</key><false/></dict><key>StandardOutPath</key><string>${xml(log)}</string><key>StandardErrorPath</key><string>${xml(log)}</string></dict></plist>\\n`,\n\t\t\tinstall: [command([\"bootstrap\", domain, path])],\n\t\t\tremove: [command([\"bootout\", `${domain}/${label}`])],\n\t\t\tverify: command([\"print\", `${domain}/${label}`]),\n\t\t\tstart: command([\"kickstart\", `${domain}/${label}`]),\n\t\t};\n\t}\n\tif (platform === \"win32\") {\n\t\tconst path = join(agentDir, \"gateway-service\", \"startup.ps1\");\n\t\tconst content = `$env:PI_CODING_AGENT_DIR = ${ps(agentDir)}\\nSet-Location -LiteralPath ${ps(home)}\\n& ${ps(node)} ${ps(cli)} gateway run *>> ${ps(log)}\\nexit $LASTEXITCODE\\n`;\n\t\tconst action = `New-ScheduledTaskAction -Execute 'powershell.exe' -Argument ${ps(`-NoProfile -NonInteractive -WindowStyle Hidden -ExecutionPolicy Bypass -File \"${path}\"`)}`;\n\t\tconst trigger =\n\t\t\tmode === \"boot\"\n\t\t\t\t? \"New-ScheduledTaskTrigger -AtStartup\"\n\t\t\t\t: `New-ScheduledTaskTrigger -AtLogOn -User ${ps(username)}`;\n\t\tconst register = `$ErrorActionPreference='Stop'; $a=${action}; $t=${trigger}; $s=New-ScheduledTaskSettingsSet -RestartCount 3 -RestartInterval (New-TimeSpan -Minutes 1) -ExecutionTimeLimit ([TimeSpan]::Zero) -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries; ${mode === \"boot\" ? `$c=Get-Credential -UserName ${ps(username)} -Message 'Windows needs your account credentials to run lunR before login'; if(!$c){throw 'Cancelled'}; Register-ScheduledTask -TaskName '${serviceName}' -Action $a -Trigger $t -Settings $s -User $c.UserName -Password $c.GetNetworkCredential().Password -Force | Out-Null` : `Register-ScheduledTask -TaskName '${serviceName}' -Action $a -Trigger $t -Settings $s -User ${ps(username)} -Force | Out-Null`}`;\n\t\tconst command = (script: string) => [\"powershell.exe\", \"-NoProfile\", \"-Command\", script];\n\t\treturn {\n\t\t\tpath,\n\t\t\tcontent,\n\t\t\tinstall: [command(register)],\n\t\t\tremove: [\n\t\t\t\tcommand(\n\t\t\t\t\t`$ErrorActionPreference='Stop'; Unregister-ScheduledTask -TaskName '${serviceName}' -Confirm:$false`,\n\t\t\t\t),\n\t\t\t],\n\t\t\tverify: command(`$ErrorActionPreference='Stop'; Get-ScheduledTask -TaskName '${serviceName}' | Out-Null`),\n\t\t\tstart: command(`$ErrorActionPreference='Stop'; Start-ScheduledTask -TaskName '${serviceName}'`),\n\t\t};\n\t}\n\tthrow new Error(`Automatic startup is not supported on ${platform}. Run lunr gateway start manually.`);\n}\n\nfunction execute(command: string[]): void {\n\tconst [file, ...args] = command;\n\tconst result = spawnSync(file, args, { stdio: \"inherit\", windowsHide: true, timeout: 120_000 });\n\tif (result.error) throw result.error;\n\tif (result.status !== 0) throw new Error(`${file} failed. Check OS permissions and run lunr gateway doctor.`);\n}\n\nexport async function configureStartup(mode: StartupMode): Promise<void> {\n\tconst previous = loadServiceSettings().startup;\n\tif (process.platform === \"linux\" && mode === \"login\") {\n\t\tconst linger = spawnSync(\"loginctl\", [\"show-user\", userInfo().username, \"--property=Linger\", \"--value\"], {\n\t\t\tencoding: \"utf8\",\n\t\t\ttimeout: 10_000,\n\t\t});\n\t\tif (linger.stdout?.trim() === \"yes\")\n\t\t\tthrow new Error(\n\t\t\t\t\"Linux user services already start at boot because lingering is enabled. Choose boot, or disable lingering yourself before choosing login. lunR will not change other user services.\",\n\t\t\t);\n\t}\n\tconst user = userInfo();\n\tconst options = {\n\t\thome: homedir(),\n\t\tagentDir: getAgentDir(),\n\t\tnode: process.execPath,\n\t\tcli: cliPath(),\n\t\tusername: user.username,\n\t\tuid: user.uid,\n\t};\n\tif (previous !== \"off\") {\n\t\tconst old = startupSpec(process.platform, previous, options);\n\t\tfor (const command of old.remove) execute(command);\n\t\tif (process.platform === \"darwin\" && previous === \"boot\") execute([\"sudo\", \"rm\", \"-f\", old.path]);\n\t\telse rmSync(old.path, { force: true });\n\t\tatomicJson(settingsPath(), { startup: \"off\" });\n\t}\n\tif (mode === \"off\") {\n\t\tatomicJson(settingsPath(), { startup: \"off\" });\n\t\treturn;\n\t}\n\tconst spec = startupSpec(process.platform, mode, options);\n\tmkdirSync(serviceDirectory(), { recursive: true, mode: 0o700 });\n\tif (process.platform === \"darwin\" && mode === \"boot\") {\n\t\tconst temporary = join(serviceDirectory(), \"install.plist\");\n\t\twriteFileSync(temporary, spec.content, { mode: 0o600 });\n\t\ttry {\n\t\t\texecute([\"sudo\", \"install\", \"-o\", \"root\", \"-g\", \"wheel\", \"-m\", \"644\", temporary, spec.path]);\n\t\t} finally {\n\t\t\trmSync(temporary, { force: true });\n\t\t}\n\t} else {\n\t\tmkdirSync(dirname(spec.path), { recursive: true, mode: 0o700 });\n\t\twriteFileSync(spec.path, spec.content, { mode: 0o600 });\n\t}\n\tfor (const command of spec.install) execute(command);\n\texecute(spec.verify);\n\tatomicJson(settingsPath(), { startup: mode });\n}\n\nfunction startupVerification(): string {\n\tconst mode = loadServiceSettings().startup;\n\tif (mode === \"off\") return \"\";\n\ttry {\n\t\tconst user = userInfo();\n\t\tconst spec = startupSpec(process.platform, mode, {\n\t\t\thome: homedir(),\n\t\t\tagentDir: getAgentDir(),\n\t\t\tnode: process.execPath,\n\t\t\tcli: cliPath(),\n\t\t\tusername: user.username,\n\t\t\tuid: user.uid,\n\t\t});\n\t\tconst [command, ...args] = spec.verify[0] === \"sudo\" ? spec.verify.slice(1) : spec.verify;\n\t\tconst result = spawnSync(command, args, { encoding: \"utf8\", windowsHide: true, timeout: 5000 });\n\t\treturn result.status === 0 ? \" (native service verified)\" : \" (native service missing or unavailable)\";\n\t} catch {\n\t\treturn \" (native service could not be checked)\";\n\t}\n}\n\nexport function serviceStatusText(): string {\n\tconst status = readGatewayStatus();\n\tconst alive = !!status && processExists(status.pid);\n\tconst fresh = !!status && Date.now() - Date.parse(status.updatedAt) < 5000;\n\treturn [\n\t\t`Gateway: ${alive ? `${status.state}${fresh ? \"\" : \" (not responding)\"}` : \"stopped\"}`,\n\t\t`Automatic startup: ${loadServiceSettings().startup}${startupVerification()}`,\n\t\t...(alive\n\t\t\t? [`PID: ${status.pid}`, ...Object.entries(status.platforms).map(([name, state]) => `${name}: ${state}`)]\n\t\t\t: []),\n\t\t`Log: ${gatewayLogPath()}`,\n\t].join(\"\\n\");\n}\n\nexport function readGatewayLog(): string {\n\ttry {\n\t\treturn readFileSync(gatewayLogPath(), \"utf8\")\n\t\t\t.split(\"\\n\")\n\t\t\t.slice(-100)\n\t\t\t.join(\"\\n\")\n\t\t\t.replace(/bot\\d+:[A-Za-z0-9_-]+/g, \"bot[redacted]\");\n\t} catch {\n\t\treturn \"No gateway log yet.\";\n\t}\n}\n"]}
@@ -1,4 +1,9 @@
1
+ import { SettingsManager } from "../core/settings-manager.ts";
1
2
  export declare function validateBotToken(platform: "telegram" | "discord", token: string): Promise<string>;
3
+ export declare function selectSetupOption<T>(settings: SettingsManager, title: string, options: Array<{
4
+ label: string;
5
+ value: T;
6
+ }>, initial?: T): Promise<T | undefined>;
2
7
  export declare function setupGateway(): Promise<void>;
3
8
  export declare function approveGatewayOwner(platform: string, code: string): string;
4
9
  //# sourceMappingURL=setup.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/gateway/setup.ts"],"names":[],"mappings":"AASA,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,UAAU,GAAG,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAqBvG;AAED,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAmHlD;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAW1E","sourcesContent":["import { existsSync, realpathSync, statSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { createInterface } from \"node:readline/promises\";\nimport { readSecret } from \"../cli/read-secret.ts\";\nimport { loadInstallFeatures, saveInstallFeatures } from \"../core/install-features.ts\";\nimport { loadGatewayConfig, saveGatewayConfig } from \"./config.ts\";\nimport { createPairingStore } from \"./pairing.ts\";\nimport { configureStartup, loadServiceSettings, type StartupMode, startGatewayService } from \"./service.ts\";\n\nexport async function validateBotToken(platform: \"telegram\" | \"discord\", token: string): Promise<string> {\n\tconst url =\n\t\tplatform === \"telegram\" ? `https://api.telegram.org/bot${token}/getMe` : \"https://discord.com/api/v10/users/@me\";\n\tlet response: Response;\n\ttry {\n\t\tresponse = await fetch(url, {\n\t\t\theaders: platform === \"discord\" ? { Authorization: `Bot ${token}` } : {},\n\t\t\tsignal: AbortSignal.timeout(15_000),\n\t\t});\n\t} catch {\n\t\tthrow new Error(`${platform}: could not reach the bot API. Check your connection and try again.`);\n\t}\n\tif (!response.ok)\n\t\tthrow new Error(\n\t\t\t`${platform}: token check failed with HTTP ${response.status}. Check the token and bot permissions.`,\n\t\t);\n\tconst value: unknown = await response.json();\n\tif (!value || typeof value !== \"object\") throw new Error(`${platform}: unexpected bot API response.`);\n\tconst user = platform === \"telegram\" && \"result\" in value ? value.result : value;\n\tif (!user || typeof user !== \"object\" || !(\"id\" in user)) throw new Error(`${platform}: bot identity was missing.`);\n\treturn \"username\" in user && typeof user.username === \"string\" ? user.username : String(user.id);\n}\n\nexport async function setupGateway(): Promise<void> {\n\tif (!process.stdin.isTTY || !process.stdout.isTTY)\n\t\tthrow new Error(\n\t\t\t\"Run lunr gateway setup in a terminal. Bot tokens are entered privately, not as command arguments.\",\n\t\t);\n\tlet rl = createInterface({ input: process.stdin, output: process.stdout });\n\tconst ask = async (question: string, fallback = \"\") =>\n\t\t(await rl.question(`${question}${fallback ? ` [${fallback}]` : \"\"}: `)).trim() || fallback;\n\tconst cfg = loadGatewayConfig();\n\ttry {\n\t\tconsole.log(\n\t\t\t\"Set up lunR on your phone\\nYour computer must stay awake and connected to the internet. Press Ctrl+C to cancel.\\n\",\n\t\t);\n\t\tconst choice = (\n\t\t\tawait ask(\n\t\t\t\t\"Connect telegram, discord, or both\",\n\t\t\t\tcfg.discord.enabled ? (cfg.telegram.enabled ? \"both\" : \"discord\") : \"telegram\",\n\t\t\t)\n\t\t).toLowerCase();\n\t\tif (![\"telegram\", \"discord\", \"both\"].includes(choice)) throw new Error(\"Choose telegram, discord, or both.\");\n\t\tfor (const platform of [\"telegram\", \"discord\"] as const) {\n\t\t\tif (choice !== platform && choice !== \"both\") continue;\n\t\t\tconsole.log(\n\t\t\t\tplatform === \"telegram\"\n\t\t\t\t\t? \"\\nTelegram\\n1. Open https://t.me/BotFather and send /newbot.\\n2. Follow its prompts and copy the bot token.\\n3. Open your new bot and send /whoami. After startup it will show your user ID and pairing code.\\nGuide: https://core.telegram.org/bots/tutorial\"\n\t\t\t\t\t: \"\\nDiscord\\n1. Open https://discord.com/developers/applications and create an application.\\n2. Open Bot, create or reset its token, and enable Message Content Intent for ordinary chat.\\n3. Under Installation, add bot and applications.commands scopes. Grant View Channels, Send Messages, Read Message History, Attach Files, and thread permissions if needed.\\n4. Use the install link to add your bot. In Discord, enable Developer Mode and copy your user ID.\\nGuide: https://docs.discord.com/developers/quick-start/getting-started\",\n\t\t\t);\n\t\t\tlet token = cfg[platform].token;\n\t\t\tif (!token || (await ask(\"Replace the saved token? yes/no\", \"no\")) === \"yes\") {\n\t\t\t\trl.close();\n\t\t\t\ttry {\n\t\t\t\t\ttoken = (await readSecret(`${platform} bot token`))?.trim();\n\t\t\t\t} finally {\n\t\t\t\t\trl = createInterface({ input: process.stdin, output: process.stdout });\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!token) throw new Error(\"No token entered. Existing configuration was not changed.\");\n\t\t\tconsole.log(`Connected bot: ${await validateBotToken(platform, token)}`);\n\t\t\tcfg[platform].token = token;\n\t\t\tcfg[platform].enabled = true;\n\t\t\tcfg.owners ??= { telegram: [], discord: [] };\n\t\t\tconst owner = await ask(\n\t\t\t\t`Your ${platform} user ID, or leave empty to pair after startup`,\n\t\t\t\tcfg.owners[platform][0] ?? \"\",\n\t\t\t);\n\t\t\tif (owner && !/^\\d+$/.test(owner)) throw new Error(\"User IDs contain digits only.\");\n\t\t\tif (owner) {\n\t\t\t\tcfg.owners[platform] = [...new Set([...cfg.owners[platform], owner])];\n\t\t\t\tcfg[platform].allowedUsers = [...new Set([...cfg[platform].allowedUsers, owner])];\n\t\t\t}\n\t\t}\n\t\tconst root = await ask(\n\t\t\t\"Project folder you want to browse from your phone\",\n\t\t\tcfg.projectRoots?.[0] ?? process.cwd(),\n\t\t);\n\t\tconst path = resolve(root);\n\t\tif (!existsSync(path) || !statSync(path).isDirectory()) throw new Error(\"That project folder does not exist.\");\n\t\tcfg.projectRoots = [...new Set([...(cfg.projectRoots ?? []), realpathSync(path)])];\n\t\tconst startup = await ask(\"Automatic startup: off, login, or boot\", \"off\");\n\t\tif (![\"off\", \"login\", \"boot\"].includes(startup)) throw new Error(\"Choose off, login, or boot.\");\n\t\tif (startup === \"boot\")\n\t\t\tconsole.log(\n\t\t\t\t\"Boot startup may require administrator permission or OS-managed account credentials. lunR does not save your account password.\",\n\t\t\t);\n\t\tconst [{ ModelRuntime }, { SettingsManager }] = await Promise.all([\n\t\t\timport(\"../core/model-runtime.ts\"),\n\t\t\timport(\"../core/settings-manager.ts\"),\n\t\t]);\n\t\tconst runtime = await ModelRuntime.create({ allowModelNetwork: false });\n\t\tconst models = await runtime.getAvailable();\n\t\tif (!models.length)\n\t\t\tthrow new Error(\n\t\t\t\t\"No saved model credentials found. Open lunr locally and use /login, then rerun gateway setup. Nothing saved.\",\n\t\t\t);\n\t\tconst settings = SettingsManager.create(process.cwd());\n\t\tconst providers = [...new Set(models.map((model) => model.provider))];\n\t\tconsole.log(`Saved providers: ${providers.join(\", \")}`);\n\t\tconst provider = await ask(\"Model provider\", settings.getDefaultProvider() ?? providers[0]);\n\t\tconst choices = models.filter((model) => model.provider === provider);\n\t\tif (!choices.length) throw new Error(\"Choose one of the saved providers. Nothing saved.\");\n\t\tconsole.log(choices.map((model, index) => `${index + 1}. ${model.id}`).join(\"\\n\"));\n\t\tconst selected = await ask(\n\t\t\t\"Model number or ID\",\n\t\t\tchoices.find((model) => model.id === settings.getDefaultModel())?.id ?? choices[0].id,\n\t\t);\n\t\tconst model = choices.find((model) => model.id === selected) ?? choices[Number(selected) - 1];\n\t\tif (!model) throw new Error(\"Choose a model from the list. Nothing saved.\");\n\t\tif ((await ask(\"Save these settings? yes/no\", \"yes\")) !== \"yes\") {\n\t\t\tconsole.log(\"Cancelled. Nothing saved.\");\n\t\t\treturn;\n\t\t}\n\t\tsaveGatewayConfig(cfg);\n\t\tsettings.setDefaultModelAndProvider(model.provider, model.id);\n\t\tconst features = loadInstallFeatures();\n\t\tfeatures.features[\"chat-platforms\"] = {\n\t\t\tenabled: true,\n\t\t\toptions: {\n\t\t\t\t...features.features[\"chat-platforms\"]?.options,\n\t\t\t\tautostart: loadServiceSettings().startup !== \"off\",\n\t\t\t},\n\t\t};\n\t\tsaveInstallFeatures(features);\n\t\ttry {\n\t\t\tawait configureStartup(startup as StartupMode);\n\t\t} finally {\n\t\t\tfeatures.features[\"chat-platforms\"].options.autostart = loadServiceSettings().startup !== \"off\";\n\t\t\tsaveInstallFeatures(features);\n\t\t}\n\t\tif ((await ask(\"Start the gateway now? yes/no\", \"yes\")) === \"yes\") console.log(await startGatewayService());\n\t\tconsole.log(\n\t\t\t\"\\nSend /whoami to your bot. To approve your own pairing code with access to projects and TUI sessions, run:\\nlunr gateway pair approve <telegram|discord> <code> --owner\\nThen use /project, /sessions, or /continue on your phone.\",\n\t\t);\n\t} finally {\n\t\trl.close();\n\t}\n}\n\nexport function approveGatewayOwner(platform: string, code: string): string {\n\tif (platform !== \"telegram\" && platform !== \"discord\") throw new Error(\"Choose telegram or discord.\");\n\tconst pairing = createPairingStore();\n\tconst user = pairing.approve(platform, code);\n\tif (!user) throw new Error(\"Pairing code is invalid or expired.\");\n\tconst cfg = loadGatewayConfig();\n\tcfg.owners ??= { telegram: [], discord: [] };\n\tcfg.owners[platform] = [...new Set([...cfg.owners[platform], user])];\n\tcfg[platform].allowedUsers = [...new Set([...cfg[platform].allowedUsers, user])];\n\tsaveGatewayConfig(cfg);\n\treturn `Approved ${platform} owner ${user}. Owner access includes local projects and TUI session history.`;\n}\n"]}
1
+ {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/gateway/setup.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAM9D,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,UAAU,GAAG,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAqBvG;AAED,wBAAsB,iBAAiB,CAAC,CAAC,EACxC,QAAQ,EAAE,eAAe,EACzB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAE,CAAC,EAC3C,OAAO,CAAC,EAAE,CAAC,GACT,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAgCxB;AAED,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CA6JlD;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAW1E","sourcesContent":["import { existsSync, realpathSync, statSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { Container, SelectList, Spacer, Text } from \"@ashx-j/lunr-tui\";\nimport { readSecret } from \"../cli/read-secret.ts\";\nimport { createStartupTui, showStartupInput, startStartupTui } from \"../cli/startup-ui.ts\";\nimport { loadInstallFeatures, saveInstallFeatures } from \"../core/install-features.ts\";\nimport { SettingsManager } from \"../core/settings-manager.ts\";\nimport { getSelectListTheme, theme } from \"../modes/interactive/theme/theme.ts\";\nimport { loadGatewayConfig, saveGatewayConfig } from \"./config.ts\";\nimport { createPairingStore } from \"./pairing.ts\";\nimport { configureStartup, loadServiceSettings, type StartupMode, startGatewayService } from \"./service.ts\";\n\nexport async function validateBotToken(platform: \"telegram\" | \"discord\", token: string): Promise<string> {\n\tconst url =\n\t\tplatform === \"telegram\" ? `https://api.telegram.org/bot${token}/getMe` : \"https://discord.com/api/v10/users/@me\";\n\tlet response: Response;\n\ttry {\n\t\tresponse = await fetch(url, {\n\t\t\theaders: platform === \"discord\" ? { Authorization: `Bot ${token}` } : {},\n\t\t\tsignal: AbortSignal.timeout(15_000),\n\t\t});\n\t} catch {\n\t\tthrow new Error(`${platform}: could not reach the bot API. Check your connection and try again.`);\n\t}\n\tif (!response.ok)\n\t\tthrow new Error(\n\t\t\t`${platform}: token check failed with HTTP ${response.status}. Check the token and bot permissions.`,\n\t\t);\n\tconst value: unknown = await response.json();\n\tif (!value || typeof value !== \"object\") throw new Error(`${platform}: unexpected bot API response.`);\n\tconst user = platform === \"telegram\" && \"result\" in value ? value.result : value;\n\tif (!user || typeof user !== \"object\" || !(\"id\" in user)) throw new Error(`${platform}: bot identity was missing.`);\n\treturn \"username\" in user && typeof user.username === \"string\" ? user.username : String(user.id);\n}\n\nexport async function selectSetupOption<T>(\n\tsettings: SettingsManager,\n\ttitle: string,\n\toptions: Array<{ label: string; value: T }>,\n\tinitial?: T,\n): Promise<T | undefined> {\n\tconst ui = await createStartupTui(settings);\n\ttry {\n\t\treturn await new Promise<T | undefined>((resolve) => {\n\t\t\tconst list = new SelectList(\n\t\t\t\toptions.map((option, index) => ({ label: option.label, value: String(index) })),\n\t\t\t\t8,\n\t\t\t\tgetSelectListTheme(),\n\t\t\t);\n\t\t\tlist.setSelectedIndex(\n\t\t\t\tMath.max(\n\t\t\t\t\t0,\n\t\t\t\t\toptions.findIndex((option) => option.value === initial),\n\t\t\t\t),\n\t\t\t);\n\t\t\tlist.onSelect = (item) => resolve(options[Number(item.value)].value);\n\t\t\tlist.onCancel = () => resolve(undefined);\n\t\t\tconst panel = new Container();\n\t\t\tpanel.addChild(new Text(theme.fg(\"accent\", title), 1, 0));\n\t\t\tpanel.addChild(new Spacer(1));\n\t\t\tpanel.addChild(list);\n\t\t\tpanel.addChild(new Text(\"Up/Down to navigate, Enter to select, Esc to cancel\", 1, 1));\n\t\t\tui.addChild(panel);\n\t\t\tui.setFocus(list);\n\t\t\tstartStartupTui(ui, settings);\n\t\t});\n\t} finally {\n\t\tui.clear();\n\t\tui.requestRender();\n\t\tawait new Promise((resolve) => setTimeout(resolve, 25));\n\t\tui.stop();\n\t}\n}\n\nexport async function setupGateway(): Promise<void> {\n\tif (!process.stdin.isTTY || !process.stdout.isTTY)\n\t\tthrow new Error(\n\t\t\t\"Run lunr gateway setup in a terminal. Bot tokens are entered privately, not as command arguments.\",\n\t\t);\n\tconst uiSettings = SettingsManager.inMemory({ theme: \"moon\" });\n\tconst cancelled = new Error(\"Setup cancelled.\");\n\tlet saved = false;\n\tconst choose = async <T>(title: string, options: Array<{ label: string; value: T }>, initial?: T) => {\n\t\tconst value = await selectSetupOption(uiSettings, title, options, initial);\n\t\tif (value === undefined) throw cancelled;\n\t\treturn value;\n\t};\n\tconst ask = async (title: string) => {\n\t\tconst value = await showStartupInput(uiSettings, title);\n\t\tif (value === undefined) throw cancelled;\n\t\treturn value.trim();\n\t};\n\tconst cfg = loadGatewayConfig();\n\ttry {\n\t\tconsole.log(\"Set up lunR on your phone\\nYour computer must stay awake and connected to the internet.\\n\");\n\t\tconst choice = await choose(\n\t\t\t\"Connect a chat platform\",\n\t\t\t[\n\t\t\t\t{ label: \"Telegram\", value: \"telegram\" },\n\t\t\t\t{ label: \"Discord\", value: \"discord\" },\n\t\t\t\t{ label: \"Both\", value: \"both\" },\n\t\t\t],\n\t\t\tcfg.discord.enabled ? (cfg.telegram.enabled ? \"both\" : \"discord\") : \"telegram\",\n\t\t);\n\t\tfor (const platform of [\"telegram\", \"discord\"] as const) {\n\t\t\tif (choice !== platform && choice !== \"both\") continue;\n\t\t\tconsole.log(\n\t\t\t\tplatform === \"telegram\"\n\t\t\t\t\t? \"\\nTelegram\\n1. Open https://t.me/BotFather and send /newbot.\\n2. Follow its prompts and copy the bot token.\\n3. Open your new bot and send /whoami. If your ID was not configured, it sends a pairing code for local approval.\\nGuide: https://core.telegram.org/bots/tutorial\"\n\t\t\t\t\t: \"\\nDiscord\\n1. Open https://discord.com/developers/applications and create an application.\\n2. Open Bot, create or reset its token, and enable Message Content Intent for ordinary chat.\\n3. Under Installation, add bot and applications.commands scopes. Grant View Channels, Send Messages, Read Message History, Attach Files, and thread permissions if needed.\\n4. Use the install link to add your bot. In Discord, enable Developer Mode and copy your user ID.\\nGuide: https://docs.discord.com/developers/quick-start/getting-started\",\n\t\t\t);\n\t\t\tlet token = cfg[platform].token;\n\t\t\tif (\n\t\t\t\t!token ||\n\t\t\t\t(await choose(`${platform} bot token`, [\n\t\t\t\t\t{ label: \"Keep the saved token\", value: false },\n\t\t\t\t\t{ label: \"Enter a different token\", value: true },\n\t\t\t\t]))\n\t\t\t) {\n\t\t\t\ttoken = (await readSecret(`${platform} bot token`))?.trim();\n\t\t\t}\n\t\t\tif (!token) throw new Error(\"No token entered. Existing configuration was not changed.\");\n\t\t\tconsole.log(`Connected bot: ${await validateBotToken(platform, token)}`);\n\t\t\tcfg[platform].token = token;\n\t\t\tcfg[platform].enabled = true;\n\t\t\tcfg.owners ??= { telegram: [], discord: [] };\n\t\t\tconst ownerChoice = await choose(`${platform} gateway access`, [\n\t\t\t\t...(cfg.owners[platform].length || cfg[platform].allowedUsers.length\n\t\t\t\t\t? [{ label: \"Keep the approved users\", value: \"keep\" }]\n\t\t\t\t\t: []),\n\t\t\t\t{ label: \"Enter my user ID\", value: \"enter\" },\n\t\t\t\t{ label: \"Approve a pairing code later on this computer\", value: \"later\" },\n\t\t\t]);\n\t\t\tconst owner = ownerChoice === \"enter\" ? await ask(`Your ${platform} user ID`) : \"\";\n\t\t\tif (ownerChoice === \"enter\" && !/^\\d+$/.test(owner)) throw new Error(\"User IDs contain digits only.\");\n\t\t\tif (owner) {\n\t\t\t\tcfg.owners[platform] = [...new Set([...cfg.owners[platform], owner])];\n\t\t\t\tcfg[platform].allowedUsers = [...new Set([...cfg[platform].allowedUsers, owner])];\n\t\t\t}\n\t\t}\n\t\tconst folders = [...new Set([cfg.defaultProject, ...(cfg.projectRoots ?? []), process.cwd()])].filter(\n\t\t\t(folder): folder is string => !!folder,\n\t\t);\n\t\tconst folder = await choose<string | null>(\"Default project\", [\n\t\t\t...folders.map((value) => ({ label: value, value })),\n\t\t\t{ label: \"Enter another folder path\", value: null },\n\t\t]);\n\t\tconst root = folder ?? (await ask(\"Project folder path\"));\n\t\tif (!root) throw new Error(\"Enter a project folder. Nothing saved.\");\n\t\tconst path = resolve(root);\n\t\tif (!existsSync(path) || !statSync(path).isDirectory()) throw new Error(\"That project folder does not exist.\");\n\t\tcfg.defaultProject = realpathSync(path);\n\t\tcfg.projectRoots = [...new Set([...(cfg.projectRoots ?? []), cfg.defaultProject])];\n\t\tconst startup = await choose<StartupMode>(\n\t\t\t\"Automatic startup\",\n\t\t\t[\n\t\t\t\t{ label: \"Off. Start manually\", value: \"off\" },\n\t\t\t\t{ label: \"When I sign in\", value: \"login\" },\n\t\t\t\t{ label: \"When the computer boots\", value: \"boot\" },\n\t\t\t],\n\t\t\tloadServiceSettings().startup,\n\t\t);\n\t\tif (startup === \"boot\")\n\t\t\tconsole.log(\n\t\t\t\t\"Boot startup may require administrator permission or OS-managed account credentials. lunR does not save your account password.\",\n\t\t\t);\n\t\tconst { ModelRuntime } = await import(\"../core/model-runtime.ts\");\n\t\tconst runtime = await ModelRuntime.create({ allowModelNetwork: false });\n\t\tconst models = await runtime.getAvailable();\n\t\tif (!models.length)\n\t\t\tthrow new Error(\n\t\t\t\t\"No saved model credentials found. Open lunr locally and use /login, then rerun gateway setup. Nothing saved.\",\n\t\t\t);\n\t\tconst settings = SettingsManager.create(cfg.defaultProject);\n\t\tconst providers = [...new Set(models.map((model) => model.provider))];\n\t\tconst provider = await choose(\n\t\t\t\"Model provider\",\n\t\t\tproviders.map((value) => ({ label: value, value })),\n\t\t\tsettings.getDefaultProvider(),\n\t\t);\n\t\tconst choices = models.filter((model) => model.provider === provider);\n\t\tconst model = await choose(\n\t\t\t\"Model\",\n\t\t\tchoices.map((value) => ({ label: value.id, value })),\n\t\t\tchoices.find((model) => model.id === settings.getDefaultModel()),\n\t\t);\n\t\tif (\n\t\t\t!(await choose(\n\t\t\t\t`Save gateway settings?\\nProject: ${cfg.defaultProject}\\nModel: ${model.provider}/${model.id}\\nStartup: ${startup}`,\n\t\t\t\t[\n\t\t\t\t\t{ label: \"Save\", value: true },\n\t\t\t\t\t{ label: \"Cancel\", value: false },\n\t\t\t\t],\n\t\t\t))\n\t\t) {\n\t\t\tconsole.log(\"Cancelled. Nothing saved.\");\n\t\t\treturn;\n\t\t}\n\t\tsaveGatewayConfig(cfg);\n\t\tsaved = true;\n\t\tsettings.setDefaultModelAndProvider(model.provider, model.id);\n\t\tawait settings.flush();\n\t\tconst features = loadInstallFeatures();\n\t\tfeatures.features[\"chat-platforms\"] = {\n\t\t\tenabled: true,\n\t\t\toptions: {\n\t\t\t\t...features.features[\"chat-platforms\"]?.options,\n\t\t\t\tautostart: loadServiceSettings().startup !== \"off\",\n\t\t\t},\n\t\t};\n\t\tsaveInstallFeatures(features);\n\t\ttry {\n\t\t\tawait configureStartup(startup);\n\t\t} finally {\n\t\t\tfeatures.features[\"chat-platforms\"].options.autostart = loadServiceSettings().startup !== \"off\";\n\t\t\tsaveInstallFeatures(features);\n\t\t}\n\t\tif (\n\t\t\tawait choose(\"Start the gateway now?\", [\n\t\t\t\t{ label: \"Start now\", value: true },\n\t\t\t\t{ label: \"Not now\", value: false },\n\t\t\t])\n\t\t)\n\t\t\tconsole.log(await startGatewayService());\n\t\tconsole.log(\n\t\t\t\"\\nIf you entered your user ID, send /start to your bot, then send a task. Otherwise send /whoami, then on this computer run:\\nlunr gateway pair approve <telegram|discord> <code>\\nApproval grants full gateway access, including local projects and saved sessions. Only approve people you trust with this computer.\",\n\t\t);\n\t} catch (error) {\n\t\tif (error !== cancelled) throw error;\n\t\tconsole.log(saved ? \"Settings saved. Start the gateway with lunr gateway start.\" : \"Cancelled. Nothing saved.\");\n\t}\n}\n\nexport function approveGatewayOwner(platform: string, code: string): string {\n\tif (platform !== \"telegram\" && platform !== \"discord\") throw new Error(\"Choose telegram or discord.\");\n\tconst pairing = createPairingStore();\n\tconst user = pairing.approve(platform, code);\n\tif (!user) throw new Error(\"Pairing code is invalid or expired.\");\n\tconst cfg = loadGatewayConfig();\n\tcfg.owners ??= { telegram: [], discord: [] };\n\tcfg.owners[platform] = [...new Set([...cfg.owners[platform], user])];\n\tcfg[platform].allowedUsers = [...new Set([...cfg[platform].allowedUsers, user])];\n\tsaveGatewayConfig(cfg);\n\treturn `Approved ${platform} user ${user}. Gateway access includes local projects and saved sessions.`;\n}\n"]}
@@ -1,8 +1,11 @@
1
1
  import { existsSync, realpathSync, statSync } from "node:fs";
2
2
  import { resolve } from "node:path";
3
- import { createInterface } from "node:readline/promises";
3
+ import { Container, SelectList, Spacer, Text } from "@ashx-j/lunr-tui";
4
4
  import { readSecret } from "../cli/read-secret.js";
5
+ import { createStartupTui, showStartupInput, startStartupTui } from "../cli/startup-ui.js";
5
6
  import { loadInstallFeatures, saveInstallFeatures } from "../core/install-features.js";
7
+ import { SettingsManager } from "../core/settings-manager.js";
8
+ import { getSelectListTheme, theme } from "../modes/interactive/theme/theme.js";
6
9
  import { loadGatewayConfig, saveGatewayConfig } from "./config.js";
7
10
  import { createPairingStore } from "./pairing.js";
8
11
  import { configureStartup, loadServiceSettings, startGatewayService } from "./service.js";
@@ -28,32 +31,70 @@ export async function validateBotToken(platform, token) {
28
31
  throw new Error(`${platform}: bot identity was missing.`);
29
32
  return "username" in user && typeof user.username === "string" ? user.username : String(user.id);
30
33
  }
34
+ export async function selectSetupOption(settings, title, options, initial) {
35
+ const ui = await createStartupTui(settings);
36
+ try {
37
+ return await new Promise((resolve) => {
38
+ const list = new SelectList(options.map((option, index) => ({ label: option.label, value: String(index) })), 8, getSelectListTheme());
39
+ list.setSelectedIndex(Math.max(0, options.findIndex((option) => option.value === initial)));
40
+ list.onSelect = (item) => resolve(options[Number(item.value)].value);
41
+ list.onCancel = () => resolve(undefined);
42
+ const panel = new Container();
43
+ panel.addChild(new Text(theme.fg("accent", title), 1, 0));
44
+ panel.addChild(new Spacer(1));
45
+ panel.addChild(list);
46
+ panel.addChild(new Text("Up/Down to navigate, Enter to select, Esc to cancel", 1, 1));
47
+ ui.addChild(panel);
48
+ ui.setFocus(list);
49
+ startStartupTui(ui, settings);
50
+ });
51
+ }
52
+ finally {
53
+ ui.clear();
54
+ ui.requestRender();
55
+ await new Promise((resolve) => setTimeout(resolve, 25));
56
+ ui.stop();
57
+ }
58
+ }
31
59
  export async function setupGateway() {
32
60
  if (!process.stdin.isTTY || !process.stdout.isTTY)
33
61
  throw new Error("Run lunr gateway setup in a terminal. Bot tokens are entered privately, not as command arguments.");
34
- let rl = createInterface({ input: process.stdin, output: process.stdout });
35
- const ask = async (question, fallback = "") => (await rl.question(`${question}${fallback ? ` [${fallback}]` : ""}: `)).trim() || fallback;
62
+ const uiSettings = SettingsManager.inMemory({ theme: "moon" });
63
+ const cancelled = new Error("Setup cancelled.");
64
+ let saved = false;
65
+ const choose = async (title, options, initial) => {
66
+ const value = await selectSetupOption(uiSettings, title, options, initial);
67
+ if (value === undefined)
68
+ throw cancelled;
69
+ return value;
70
+ };
71
+ const ask = async (title) => {
72
+ const value = await showStartupInput(uiSettings, title);
73
+ if (value === undefined)
74
+ throw cancelled;
75
+ return value.trim();
76
+ };
36
77
  const cfg = loadGatewayConfig();
37
78
  try {
38
- console.log("Set up lunR on your phone\nYour computer must stay awake and connected to the internet. Press Ctrl+C to cancel.\n");
39
- const choice = (await ask("Connect telegram, discord, or both", cfg.discord.enabled ? (cfg.telegram.enabled ? "both" : "discord") : "telegram")).toLowerCase();
40
- if (!["telegram", "discord", "both"].includes(choice))
41
- throw new Error("Choose telegram, discord, or both.");
79
+ console.log("Set up lunR on your phone\nYour computer must stay awake and connected to the internet.\n");
80
+ const choice = await choose("Connect a chat platform", [
81
+ { label: "Telegram", value: "telegram" },
82
+ { label: "Discord", value: "discord" },
83
+ { label: "Both", value: "both" },
84
+ ], cfg.discord.enabled ? (cfg.telegram.enabled ? "both" : "discord") : "telegram");
42
85
  for (const platform of ["telegram", "discord"]) {
43
86
  if (choice !== platform && choice !== "both")
44
87
  continue;
45
88
  console.log(platform === "telegram"
46
- ? "\nTelegram\n1. Open https://t.me/BotFather and send /newbot.\n2. Follow its prompts and copy the bot token.\n3. Open your new bot and send /whoami. After startup it will show your user ID and pairing code.\nGuide: https://core.telegram.org/bots/tutorial"
89
+ ? "\nTelegram\n1. Open https://t.me/BotFather and send /newbot.\n2. Follow its prompts and copy the bot token.\n3. Open your new bot and send /whoami. If your ID was not configured, it sends a pairing code for local approval.\nGuide: https://core.telegram.org/bots/tutorial"
47
90
  : "\nDiscord\n1. Open https://discord.com/developers/applications and create an application.\n2. Open Bot, create or reset its token, and enable Message Content Intent for ordinary chat.\n3. Under Installation, add bot and applications.commands scopes. Grant View Channels, Send Messages, Read Message History, Attach Files, and thread permissions if needed.\n4. Use the install link to add your bot. In Discord, enable Developer Mode and copy your user ID.\nGuide: https://docs.discord.com/developers/quick-start/getting-started");
48
91
  let token = cfg[platform].token;
49
- if (!token || (await ask("Replace the saved token? yes/no", "no")) === "yes") {
50
- rl.close();
51
- try {
52
- token = (await readSecret(`${platform} bot token`))?.trim();
53
- }
54
- finally {
55
- rl = createInterface({ input: process.stdin, output: process.stdout });
56
- }
92
+ if (!token ||
93
+ (await choose(`${platform} bot token`, [
94
+ { label: "Keep the saved token", value: false },
95
+ { label: "Enter a different token", value: true },
96
+ ]))) {
97
+ token = (await readSecret(`${platform} bot token`))?.trim();
57
98
  }
58
99
  if (!token)
59
100
  throw new Error("No token entered. Existing configuration was not changed.");
@@ -61,50 +102,62 @@ export async function setupGateway() {
61
102
  cfg[platform].token = token;
62
103
  cfg[platform].enabled = true;
63
104
  cfg.owners ??= { telegram: [], discord: [] };
64
- const owner = await ask(`Your ${platform} user ID, or leave empty to pair after startup`, cfg.owners[platform][0] ?? "");
65
- if (owner && !/^\d+$/.test(owner))
105
+ const ownerChoice = await choose(`${platform} gateway access`, [
106
+ ...(cfg.owners[platform].length || cfg[platform].allowedUsers.length
107
+ ? [{ label: "Keep the approved users", value: "keep" }]
108
+ : []),
109
+ { label: "Enter my user ID", value: "enter" },
110
+ { label: "Approve a pairing code later on this computer", value: "later" },
111
+ ]);
112
+ const owner = ownerChoice === "enter" ? await ask(`Your ${platform} user ID`) : "";
113
+ if (ownerChoice === "enter" && !/^\d+$/.test(owner))
66
114
  throw new Error("User IDs contain digits only.");
67
115
  if (owner) {
68
116
  cfg.owners[platform] = [...new Set([...cfg.owners[platform], owner])];
69
117
  cfg[platform].allowedUsers = [...new Set([...cfg[platform].allowedUsers, owner])];
70
118
  }
71
119
  }
72
- const root = await ask("Project folder you want to browse from your phone", cfg.projectRoots?.[0] ?? process.cwd());
120
+ const folders = [...new Set([cfg.defaultProject, ...(cfg.projectRoots ?? []), process.cwd()])].filter((folder) => !!folder);
121
+ const folder = await choose("Default project", [
122
+ ...folders.map((value) => ({ label: value, value })),
123
+ { label: "Enter another folder path", value: null },
124
+ ]);
125
+ const root = folder ?? (await ask("Project folder path"));
126
+ if (!root)
127
+ throw new Error("Enter a project folder. Nothing saved.");
73
128
  const path = resolve(root);
74
129
  if (!existsSync(path) || !statSync(path).isDirectory())
75
130
  throw new Error("That project folder does not exist.");
76
- cfg.projectRoots = [...new Set([...(cfg.projectRoots ?? []), realpathSync(path)])];
77
- const startup = await ask("Automatic startup: off, login, or boot", "off");
78
- if (!["off", "login", "boot"].includes(startup))
79
- throw new Error("Choose off, login, or boot.");
131
+ cfg.defaultProject = realpathSync(path);
132
+ cfg.projectRoots = [...new Set([...(cfg.projectRoots ?? []), cfg.defaultProject])];
133
+ const startup = await choose("Automatic startup", [
134
+ { label: "Off. Start manually", value: "off" },
135
+ { label: "When I sign in", value: "login" },
136
+ { label: "When the computer boots", value: "boot" },
137
+ ], loadServiceSettings().startup);
80
138
  if (startup === "boot")
81
139
  console.log("Boot startup may require administrator permission or OS-managed account credentials. lunR does not save your account password.");
82
- const [{ ModelRuntime }, { SettingsManager }] = await Promise.all([
83
- import("../core/model-runtime.js"),
84
- import("../core/settings-manager.js"),
85
- ]);
140
+ const { ModelRuntime } = await import("../core/model-runtime.js");
86
141
  const runtime = await ModelRuntime.create({ allowModelNetwork: false });
87
142
  const models = await runtime.getAvailable();
88
143
  if (!models.length)
89
144
  throw new Error("No saved model credentials found. Open lunr locally and use /login, then rerun gateway setup. Nothing saved.");
90
- const settings = SettingsManager.create(process.cwd());
145
+ const settings = SettingsManager.create(cfg.defaultProject);
91
146
  const providers = [...new Set(models.map((model) => model.provider))];
92
- console.log(`Saved providers: ${providers.join(", ")}`);
93
- const provider = await ask("Model provider", settings.getDefaultProvider() ?? providers[0]);
147
+ const provider = await choose("Model provider", providers.map((value) => ({ label: value, value })), settings.getDefaultProvider());
94
148
  const choices = models.filter((model) => model.provider === provider);
95
- if (!choices.length)
96
- throw new Error("Choose one of the saved providers. Nothing saved.");
97
- console.log(choices.map((model, index) => `${index + 1}. ${model.id}`).join("\n"));
98
- const selected = await ask("Model number or ID", choices.find((model) => model.id === settings.getDefaultModel())?.id ?? choices[0].id);
99
- const model = choices.find((model) => model.id === selected) ?? choices[Number(selected) - 1];
100
- if (!model)
101
- throw new Error("Choose a model from the list. Nothing saved.");
102
- if ((await ask("Save these settings? yes/no", "yes")) !== "yes") {
149
+ const model = await choose("Model", choices.map((value) => ({ label: value.id, value })), choices.find((model) => model.id === settings.getDefaultModel()));
150
+ if (!(await choose(`Save gateway settings?\nProject: ${cfg.defaultProject}\nModel: ${model.provider}/${model.id}\nStartup: ${startup}`, [
151
+ { label: "Save", value: true },
152
+ { label: "Cancel", value: false },
153
+ ]))) {
103
154
  console.log("Cancelled. Nothing saved.");
104
155
  return;
105
156
  }
106
157
  saveGatewayConfig(cfg);
158
+ saved = true;
107
159
  settings.setDefaultModelAndProvider(model.provider, model.id);
160
+ await settings.flush();
108
161
  const features = loadInstallFeatures();
109
162
  features.features["chat-platforms"] = {
110
163
  enabled: true,
@@ -121,12 +174,17 @@ export async function setupGateway() {
121
174
  features.features["chat-platforms"].options.autostart = loadServiceSettings().startup !== "off";
122
175
  saveInstallFeatures(features);
123
176
  }
124
- if ((await ask("Start the gateway now? yes/no", "yes")) === "yes")
177
+ if (await choose("Start the gateway now?", [
178
+ { label: "Start now", value: true },
179
+ { label: "Not now", value: false },
180
+ ]))
125
181
  console.log(await startGatewayService());
126
- console.log("\nSend /whoami to your bot. To approve your own pairing code with access to projects and TUI sessions, run:\nlunr gateway pair approve <telegram|discord> <code> --owner\nThen use /project, /sessions, or /continue on your phone.");
182
+ console.log("\nIf you entered your user ID, send /start to your bot, then send a task. Otherwise send /whoami, then on this computer run:\nlunr gateway pair approve <telegram|discord> <code>\nApproval grants full gateway access, including local projects and saved sessions. Only approve people you trust with this computer.");
127
183
  }
128
- finally {
129
- rl.close();
184
+ catch (error) {
185
+ if (error !== cancelled)
186
+ throw error;
187
+ console.log(saved ? "Settings saved. Start the gateway with lunr gateway start." : "Cancelled. Nothing saved.");
130
188
  }
131
189
  }
132
190
  export function approveGatewayOwner(platform, code) {
@@ -141,6 +199,6 @@ export function approveGatewayOwner(platform, code) {
141
199
  cfg.owners[platform] = [...new Set([...cfg.owners[platform], user])];
142
200
  cfg[platform].allowedUsers = [...new Set([...cfg[platform].allowedUsers, user])];
143
201
  saveGatewayConfig(cfg);
144
- return `Approved ${platform} owner ${user}. Owner access includes local projects and TUI session history.`;
202
+ return `Approved ${platform} user ${user}. Gateway access includes local projects and saved sessions.`;
145
203
  }
146
204
  //# sourceMappingURL=setup.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/gateway/setup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC7D,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AACvF,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACnE,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAoB,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAE5G,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,QAAgC,EAAE,KAAa,EAAmB;IACxG,MAAM,GAAG,GACR,QAAQ,KAAK,UAAU,CAAC,CAAC,CAAC,+BAA+B,KAAK,QAAQ,CAAC,CAAC,CAAC,uCAAuC,CAAC;IAClH,IAAI,QAAkB,CAAC;IACvB,IAAI,CAAC;QACJ,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAC3B,OAAO,EAAE,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,OAAO,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE;YACxE,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC;SACnC,CAAC,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACR,MAAM,IAAI,KAAK,CAAC,GAAG,QAAQ,qEAAqE,CAAC,CAAC;IACnG,CAAC;IACD,IAAI,CAAC,QAAQ,CAAC,EAAE;QACf,MAAM,IAAI,KAAK,CACd,GAAG,QAAQ,kCAAkC,QAAQ,CAAC,MAAM,wCAAwC,CACpG,CAAC;IACH,MAAM,KAAK,GAAY,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IAC7C,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,QAAQ,gCAAgC,CAAC,CAAC;IACtG,MAAM,IAAI,GAAG,QAAQ,KAAK,UAAU,IAAI,QAAQ,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC;IACjF,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,QAAQ,6BAA6B,CAAC,CAAC;IACpH,OAAO,UAAU,IAAI,IAAI,IAAI,OAAO,IAAI,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAAA,CACjG;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,GAAkB;IACnD,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK;QAChD,MAAM,IAAI,KAAK,CACd,mGAAmG,CACnG,CAAC;IACH,IAAI,EAAE,GAAG,eAAe,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC3E,MAAM,GAAG,GAAG,KAAK,EAAE,QAAgB,EAAE,QAAQ,GAAG,EAAE,EAAE,EAAE,CACrD,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,GAAG,QAAQ,GAAG,QAAQ,CAAC,CAAC,CAAC,KAAK,QAAQ,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,QAAQ,CAAC;IAC5F,MAAM,GAAG,GAAG,iBAAiB,EAAE,CAAC;IAChC,IAAI,CAAC;QACJ,OAAO,CAAC,GAAG,CACV,mHAAmH,CACnH,CAAC;QACF,MAAM,MAAM,GAAG,CACd,MAAM,GAAG,CACR,oCAAoC,EACpC,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,UAAU,CAC9E,CACD,CAAC,WAAW,EAAE,CAAC;QAChB,IAAI,CAAC,CAAC,UAAU,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;QAC7G,KAAK,MAAM,QAAQ,IAAI,CAAC,UAAU,EAAE,SAAS,CAAU,EAAE,CAAC;YACzD,IAAI,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,MAAM;gBAAE,SAAS;YACvD,OAAO,CAAC,GAAG,CACV,QAAQ,KAAK,UAAU;gBACtB,CAAC,CAAC,+PAA+P;gBACjQ,CAAC,CAAC,ghBAAghB,CACnhB,CAAC;YACF,IAAI,KAAK,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC;YAChC,IAAI,CAAC,KAAK,IAAI,CAAC,MAAM,GAAG,CAAC,iCAAiC,EAAE,IAAI,CAAC,CAAC,KAAK,KAAK,EAAE,CAAC;gBAC9E,EAAE,CAAC,KAAK,EAAE,CAAC;gBACX,IAAI,CAAC;oBACJ,KAAK,GAAG,CAAC,MAAM,UAAU,CAAC,GAAG,QAAQ,YAAY,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;gBAC7D,CAAC;wBAAS,CAAC;oBACV,EAAE,GAAG,eAAe,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;gBACxE,CAAC;YACF,CAAC;YACD,IAAI,CAAC,KAAK;gBAAE,MAAM,IAAI,KAAK,CAAC,2DAA2D,CAAC,CAAC;YACzF,OAAO,CAAC,GAAG,CAAC,kBAAkB,MAAM,gBAAgB,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;YACzE,GAAG,CAAC,QAAQ,CAAC,CAAC,KAAK,GAAG,KAAK,CAAC;YAC5B,GAAG,CAAC,QAAQ,CAAC,CAAC,OAAO,GAAG,IAAI,CAAC;YAC7B,GAAG,CAAC,MAAM,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;YAC7C,MAAM,KAAK,GAAG,MAAM,GAAG,CACtB,QAAQ,QAAQ,gDAAgD,EAChE,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAC7B,CAAC;YACF,IAAI,KAAK,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC;gBAAE,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;YACpF,IAAI,KAAK,EAAE,CAAC;gBACX,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;gBACtE,GAAG,CAAC,QAAQ,CAAC,CAAC,YAAY,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;YACnF,CAAC;QACF,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,GAAG,CACrB,mDAAmD,EACnD,GAAG,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,GAAG,EAAE,CACtC,CAAC;QACF,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QAC3B,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;QAC/G,GAAG,CAAC,YAAY,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,YAAY,IAAI,EAAE,CAAC,EAAE,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QACnF,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,wCAAwC,EAAE,KAAK,CAAC,CAAC;QAC3E,IAAI,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;QAChG,IAAI,OAAO,KAAK,MAAM;YACrB,OAAO,CAAC,GAAG,CACV,gIAAgI,CAChI,CAAC;QACH,MAAM,CAAC,EAAE,YAAY,EAAE,EAAE,EAAE,eAAe,EAAE,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YACjE,MAAM,CAAC,0BAA0B,CAAC;YAClC,MAAM,CAAC,6BAA6B,CAAC;SACrC,CAAC,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,YAAY,CAAC,MAAM,CAAC,EAAE,iBAAiB,EAAE,KAAK,EAAE,CAAC,CAAC;QACxE,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,YAAY,EAAE,CAAC;QAC5C,IAAI,CAAC,MAAM,CAAC,MAAM;YACjB,MAAM,IAAI,KAAK,CACd,8GAA8G,CAC9G,CAAC;QACH,MAAM,QAAQ,GAAG,eAAe,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;QACvD,MAAM,SAAS,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QACtE,OAAO,CAAC,GAAG,CAAC,oBAAoB,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACxD,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,gBAAgB,EAAE,QAAQ,CAAC,kBAAkB,EAAE,IAAI,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5F,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC;QACtE,IAAI,CAAC,OAAO,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;QAC1F,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,GAAG,KAAK,GAAG,CAAC,KAAK,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QACnF,MAAM,QAAQ,GAAG,MAAM,GAAG,CACzB,oBAAoB,EACpB,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,QAAQ,CAAC,eAAe,EAAE,CAAC,EAAE,EAAE,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CACrF,CAAC;QACF,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,QAAQ,CAAC,IAAI,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;QAC9F,IAAI,CAAC,KAAK;YAAE,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;QAC5E,IAAI,CAAC,MAAM,GAAG,CAAC,6BAA6B,EAAE,KAAK,CAAC,CAAC,KAAK,KAAK,EAAE,CAAC;YACjE,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;YACzC,OAAO;QACR,CAAC;QACD,iBAAiB,CAAC,GAAG,CAAC,CAAC;QACvB,QAAQ,CAAC,0BAA0B,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;QAC9D,MAAM,QAAQ,GAAG,mBAAmB,EAAE,CAAC;QACvC,QAAQ,CAAC,QAAQ,CAAC,gBAAgB,CAAC,GAAG;YACrC,OAAO,EAAE,IAAI;YACb,OAAO,EAAE;gBACR,GAAG,QAAQ,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,OAAO;gBAC/C,SAAS,EAAE,mBAAmB,EAAE,CAAC,OAAO,KAAK,KAAK;aAClD;SACD,CAAC;QACF,mBAAmB,CAAC,QAAQ,CAAC,CAAC;QAC9B,IAAI,CAAC;YACJ,MAAM,gBAAgB,CAAC,OAAsB,CAAC,CAAC;QAChD,CAAC;gBAAS,CAAC;YACV,QAAQ,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC,OAAO,CAAC,SAAS,GAAG,mBAAmB,EAAE,CAAC,OAAO,KAAK,KAAK,CAAC;YAChG,mBAAmB,CAAC,QAAQ,CAAC,CAAC;QAC/B,CAAC;QACD,IAAI,CAAC,MAAM,GAAG,CAAC,+BAA+B,EAAE,KAAK,CAAC,CAAC,KAAK,KAAK;YAAE,OAAO,CAAC,GAAG,CAAC,MAAM,mBAAmB,EAAE,CAAC,CAAC;QAC5G,OAAO,CAAC,GAAG,CACV,qOAAqO,CACrO,CAAC;IACH,CAAC;YAAS,CAAC;QACV,EAAE,CAAC,KAAK,EAAE,CAAC;IACZ,CAAC;AAAA,CACD;AAED,MAAM,UAAU,mBAAmB,CAAC,QAAgB,EAAE,IAAY,EAAU;IAC3E,IAAI,QAAQ,KAAK,UAAU,IAAI,QAAQ,KAAK,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;IACtG,MAAM,OAAO,GAAG,kBAAkB,EAAE,CAAC;IACrC,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IAC7C,IAAI,CAAC,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;IAClE,MAAM,GAAG,GAAG,iBAAiB,EAAE,CAAC;IAChC,GAAG,CAAC,MAAM,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IAC7C,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;IACrE,GAAG,CAAC,QAAQ,CAAC,CAAC,YAAY,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;IACjF,iBAAiB,CAAC,GAAG,CAAC,CAAC;IACvB,OAAO,YAAY,QAAQ,UAAU,IAAI,iEAAiE,CAAC;AAAA,CAC3G","sourcesContent":["import { existsSync, realpathSync, statSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { createInterface } from \"node:readline/promises\";\nimport { readSecret } from \"../cli/read-secret.ts\";\nimport { loadInstallFeatures, saveInstallFeatures } from \"../core/install-features.ts\";\nimport { loadGatewayConfig, saveGatewayConfig } from \"./config.ts\";\nimport { createPairingStore } from \"./pairing.ts\";\nimport { configureStartup, loadServiceSettings, type StartupMode, startGatewayService } from \"./service.ts\";\n\nexport async function validateBotToken(platform: \"telegram\" | \"discord\", token: string): Promise<string> {\n\tconst url =\n\t\tplatform === \"telegram\" ? `https://api.telegram.org/bot${token}/getMe` : \"https://discord.com/api/v10/users/@me\";\n\tlet response: Response;\n\ttry {\n\t\tresponse = await fetch(url, {\n\t\t\theaders: platform === \"discord\" ? { Authorization: `Bot ${token}` } : {},\n\t\t\tsignal: AbortSignal.timeout(15_000),\n\t\t});\n\t} catch {\n\t\tthrow new Error(`${platform}: could not reach the bot API. Check your connection and try again.`);\n\t}\n\tif (!response.ok)\n\t\tthrow new Error(\n\t\t\t`${platform}: token check failed with HTTP ${response.status}. Check the token and bot permissions.`,\n\t\t);\n\tconst value: unknown = await response.json();\n\tif (!value || typeof value !== \"object\") throw new Error(`${platform}: unexpected bot API response.`);\n\tconst user = platform === \"telegram\" && \"result\" in value ? value.result : value;\n\tif (!user || typeof user !== \"object\" || !(\"id\" in user)) throw new Error(`${platform}: bot identity was missing.`);\n\treturn \"username\" in user && typeof user.username === \"string\" ? user.username : String(user.id);\n}\n\nexport async function setupGateway(): Promise<void> {\n\tif (!process.stdin.isTTY || !process.stdout.isTTY)\n\t\tthrow new Error(\n\t\t\t\"Run lunr gateway setup in a terminal. Bot tokens are entered privately, not as command arguments.\",\n\t\t);\n\tlet rl = createInterface({ input: process.stdin, output: process.stdout });\n\tconst ask = async (question: string, fallback = \"\") =>\n\t\t(await rl.question(`${question}${fallback ? ` [${fallback}]` : \"\"}: `)).trim() || fallback;\n\tconst cfg = loadGatewayConfig();\n\ttry {\n\t\tconsole.log(\n\t\t\t\"Set up lunR on your phone\\nYour computer must stay awake and connected to the internet. Press Ctrl+C to cancel.\\n\",\n\t\t);\n\t\tconst choice = (\n\t\t\tawait ask(\n\t\t\t\t\"Connect telegram, discord, or both\",\n\t\t\t\tcfg.discord.enabled ? (cfg.telegram.enabled ? \"both\" : \"discord\") : \"telegram\",\n\t\t\t)\n\t\t).toLowerCase();\n\t\tif (![\"telegram\", \"discord\", \"both\"].includes(choice)) throw new Error(\"Choose telegram, discord, or both.\");\n\t\tfor (const platform of [\"telegram\", \"discord\"] as const) {\n\t\t\tif (choice !== platform && choice !== \"both\") continue;\n\t\t\tconsole.log(\n\t\t\t\tplatform === \"telegram\"\n\t\t\t\t\t? \"\\nTelegram\\n1. Open https://t.me/BotFather and send /newbot.\\n2. Follow its prompts and copy the bot token.\\n3. Open your new bot and send /whoami. After startup it will show your user ID and pairing code.\\nGuide: https://core.telegram.org/bots/tutorial\"\n\t\t\t\t\t: \"\\nDiscord\\n1. Open https://discord.com/developers/applications and create an application.\\n2. Open Bot, create or reset its token, and enable Message Content Intent for ordinary chat.\\n3. Under Installation, add bot and applications.commands scopes. Grant View Channels, Send Messages, Read Message History, Attach Files, and thread permissions if needed.\\n4. Use the install link to add your bot. In Discord, enable Developer Mode and copy your user ID.\\nGuide: https://docs.discord.com/developers/quick-start/getting-started\",\n\t\t\t);\n\t\t\tlet token = cfg[platform].token;\n\t\t\tif (!token || (await ask(\"Replace the saved token? yes/no\", \"no\")) === \"yes\") {\n\t\t\t\trl.close();\n\t\t\t\ttry {\n\t\t\t\t\ttoken = (await readSecret(`${platform} bot token`))?.trim();\n\t\t\t\t} finally {\n\t\t\t\t\trl = createInterface({ input: process.stdin, output: process.stdout });\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!token) throw new Error(\"No token entered. Existing configuration was not changed.\");\n\t\t\tconsole.log(`Connected bot: ${await validateBotToken(platform, token)}`);\n\t\t\tcfg[platform].token = token;\n\t\t\tcfg[platform].enabled = true;\n\t\t\tcfg.owners ??= { telegram: [], discord: [] };\n\t\t\tconst owner = await ask(\n\t\t\t\t`Your ${platform} user ID, or leave empty to pair after startup`,\n\t\t\t\tcfg.owners[platform][0] ?? \"\",\n\t\t\t);\n\t\t\tif (owner && !/^\\d+$/.test(owner)) throw new Error(\"User IDs contain digits only.\");\n\t\t\tif (owner) {\n\t\t\t\tcfg.owners[platform] = [...new Set([...cfg.owners[platform], owner])];\n\t\t\t\tcfg[platform].allowedUsers = [...new Set([...cfg[platform].allowedUsers, owner])];\n\t\t\t}\n\t\t}\n\t\tconst root = await ask(\n\t\t\t\"Project folder you want to browse from your phone\",\n\t\t\tcfg.projectRoots?.[0] ?? process.cwd(),\n\t\t);\n\t\tconst path = resolve(root);\n\t\tif (!existsSync(path) || !statSync(path).isDirectory()) throw new Error(\"That project folder does not exist.\");\n\t\tcfg.projectRoots = [...new Set([...(cfg.projectRoots ?? []), realpathSync(path)])];\n\t\tconst startup = await ask(\"Automatic startup: off, login, or boot\", \"off\");\n\t\tif (![\"off\", \"login\", \"boot\"].includes(startup)) throw new Error(\"Choose off, login, or boot.\");\n\t\tif (startup === \"boot\")\n\t\t\tconsole.log(\n\t\t\t\t\"Boot startup may require administrator permission or OS-managed account credentials. lunR does not save your account password.\",\n\t\t\t);\n\t\tconst [{ ModelRuntime }, { SettingsManager }] = await Promise.all([\n\t\t\timport(\"../core/model-runtime.ts\"),\n\t\t\timport(\"../core/settings-manager.ts\"),\n\t\t]);\n\t\tconst runtime = await ModelRuntime.create({ allowModelNetwork: false });\n\t\tconst models = await runtime.getAvailable();\n\t\tif (!models.length)\n\t\t\tthrow new Error(\n\t\t\t\t\"No saved model credentials found. Open lunr locally and use /login, then rerun gateway setup. Nothing saved.\",\n\t\t\t);\n\t\tconst settings = SettingsManager.create(process.cwd());\n\t\tconst providers = [...new Set(models.map((model) => model.provider))];\n\t\tconsole.log(`Saved providers: ${providers.join(\", \")}`);\n\t\tconst provider = await ask(\"Model provider\", settings.getDefaultProvider() ?? providers[0]);\n\t\tconst choices = models.filter((model) => model.provider === provider);\n\t\tif (!choices.length) throw new Error(\"Choose one of the saved providers. Nothing saved.\");\n\t\tconsole.log(choices.map((model, index) => `${index + 1}. ${model.id}`).join(\"\\n\"));\n\t\tconst selected = await ask(\n\t\t\t\"Model number or ID\",\n\t\t\tchoices.find((model) => model.id === settings.getDefaultModel())?.id ?? choices[0].id,\n\t\t);\n\t\tconst model = choices.find((model) => model.id === selected) ?? choices[Number(selected) - 1];\n\t\tif (!model) throw new Error(\"Choose a model from the list. Nothing saved.\");\n\t\tif ((await ask(\"Save these settings? yes/no\", \"yes\")) !== \"yes\") {\n\t\t\tconsole.log(\"Cancelled. Nothing saved.\");\n\t\t\treturn;\n\t\t}\n\t\tsaveGatewayConfig(cfg);\n\t\tsettings.setDefaultModelAndProvider(model.provider, model.id);\n\t\tconst features = loadInstallFeatures();\n\t\tfeatures.features[\"chat-platforms\"] = {\n\t\t\tenabled: true,\n\t\t\toptions: {\n\t\t\t\t...features.features[\"chat-platforms\"]?.options,\n\t\t\t\tautostart: loadServiceSettings().startup !== \"off\",\n\t\t\t},\n\t\t};\n\t\tsaveInstallFeatures(features);\n\t\ttry {\n\t\t\tawait configureStartup(startup as StartupMode);\n\t\t} finally {\n\t\t\tfeatures.features[\"chat-platforms\"].options.autostart = loadServiceSettings().startup !== \"off\";\n\t\t\tsaveInstallFeatures(features);\n\t\t}\n\t\tif ((await ask(\"Start the gateway now? yes/no\", \"yes\")) === \"yes\") console.log(await startGatewayService());\n\t\tconsole.log(\n\t\t\t\"\\nSend /whoami to your bot. To approve your own pairing code with access to projects and TUI sessions, run:\\nlunr gateway pair approve <telegram|discord> <code> --owner\\nThen use /project, /sessions, or /continue on your phone.\",\n\t\t);\n\t} finally {\n\t\trl.close();\n\t}\n}\n\nexport function approveGatewayOwner(platform: string, code: string): string {\n\tif (platform !== \"telegram\" && platform !== \"discord\") throw new Error(\"Choose telegram or discord.\");\n\tconst pairing = createPairingStore();\n\tconst user = pairing.approve(platform, code);\n\tif (!user) throw new Error(\"Pairing code is invalid or expired.\");\n\tconst cfg = loadGatewayConfig();\n\tcfg.owners ??= { telegram: [], discord: [] };\n\tcfg.owners[platform] = [...new Set([...cfg.owners[platform], user])];\n\tcfg[platform].allowedUsers = [...new Set([...cfg[platform].allowedUsers, user])];\n\tsaveGatewayConfig(cfg);\n\treturn `Approved ${platform} owner ${user}. Owner access includes local projects and TUI session history.`;\n}\n"]}
1
+ {"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/gateway/setup.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, realpathSync, statSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { Container, SelectList, Spacer, Text } from \"@ashx-j/lunr-tui\";\nimport { readSecret } from \"../cli/read-secret.ts\";\nimport { createStartupTui, showStartupInput, startStartupTui } from \"../cli/startup-ui.ts\";\nimport { loadInstallFeatures, saveInstallFeatures } from \"../core/install-features.ts\";\nimport { SettingsManager } from \"../core/settings-manager.ts\";\nimport { getSelectListTheme, theme } from \"../modes/interactive/theme/theme.ts\";\nimport { loadGatewayConfig, saveGatewayConfig } from \"./config.ts\";\nimport { createPairingStore } from \"./pairing.ts\";\nimport { configureStartup, loadServiceSettings, type StartupMode, startGatewayService } from \"./service.ts\";\n\nexport async function validateBotToken(platform: \"telegram\" | \"discord\", token: string): Promise<string> {\n\tconst url =\n\t\tplatform === \"telegram\" ? `https://api.telegram.org/bot${token}/getMe` : \"https://discord.com/api/v10/users/@me\";\n\tlet response: Response;\n\ttry {\n\t\tresponse = await fetch(url, {\n\t\t\theaders: platform === \"discord\" ? { Authorization: `Bot ${token}` } : {},\n\t\t\tsignal: AbortSignal.timeout(15_000),\n\t\t});\n\t} catch {\n\t\tthrow new Error(`${platform}: could not reach the bot API. Check your connection and try again.`);\n\t}\n\tif (!response.ok)\n\t\tthrow new Error(\n\t\t\t`${platform}: token check failed with HTTP ${response.status}. Check the token and bot permissions.`,\n\t\t);\n\tconst value: unknown = await response.json();\n\tif (!value || typeof value !== \"object\") throw new Error(`${platform}: unexpected bot API response.`);\n\tconst user = platform === \"telegram\" && \"result\" in value ? value.result : value;\n\tif (!user || typeof user !== \"object\" || !(\"id\" in user)) throw new Error(`${platform}: bot identity was missing.`);\n\treturn \"username\" in user && typeof user.username === \"string\" ? user.username : String(user.id);\n}\n\nexport async function selectSetupOption<T>(\n\tsettings: SettingsManager,\n\ttitle: string,\n\toptions: Array<{ label: string; value: T }>,\n\tinitial?: T,\n): Promise<T | undefined> {\n\tconst ui = await createStartupTui(settings);\n\ttry {\n\t\treturn await new Promise<T | undefined>((resolve) => {\n\t\t\tconst list = new SelectList(\n\t\t\t\toptions.map((option, index) => ({ label: option.label, value: String(index) })),\n\t\t\t\t8,\n\t\t\t\tgetSelectListTheme(),\n\t\t\t);\n\t\t\tlist.setSelectedIndex(\n\t\t\t\tMath.max(\n\t\t\t\t\t0,\n\t\t\t\t\toptions.findIndex((option) => option.value === initial),\n\t\t\t\t),\n\t\t\t);\n\t\t\tlist.onSelect = (item) => resolve(options[Number(item.value)].value);\n\t\t\tlist.onCancel = () => resolve(undefined);\n\t\t\tconst panel = new Container();\n\t\t\tpanel.addChild(new Text(theme.fg(\"accent\", title), 1, 0));\n\t\t\tpanel.addChild(new Spacer(1));\n\t\t\tpanel.addChild(list);\n\t\t\tpanel.addChild(new Text(\"Up/Down to navigate, Enter to select, Esc to cancel\", 1, 1));\n\t\t\tui.addChild(panel);\n\t\t\tui.setFocus(list);\n\t\t\tstartStartupTui(ui, settings);\n\t\t});\n\t} finally {\n\t\tui.clear();\n\t\tui.requestRender();\n\t\tawait new Promise((resolve) => setTimeout(resolve, 25));\n\t\tui.stop();\n\t}\n}\n\nexport async function setupGateway(): Promise<void> {\n\tif (!process.stdin.isTTY || !process.stdout.isTTY)\n\t\tthrow new Error(\n\t\t\t\"Run lunr gateway setup in a terminal. Bot tokens are entered privately, not as command arguments.\",\n\t\t);\n\tconst uiSettings = SettingsManager.inMemory({ theme: \"moon\" });\n\tconst cancelled = new Error(\"Setup cancelled.\");\n\tlet saved = false;\n\tconst choose = async <T>(title: string, options: Array<{ label: string; value: T }>, initial?: T) => {\n\t\tconst value = await selectSetupOption(uiSettings, title, options, initial);\n\t\tif (value === undefined) throw cancelled;\n\t\treturn value;\n\t};\n\tconst ask = async (title: string) => {\n\t\tconst value = await showStartupInput(uiSettings, title);\n\t\tif (value === undefined) throw cancelled;\n\t\treturn value.trim();\n\t};\n\tconst cfg = loadGatewayConfig();\n\ttry {\n\t\tconsole.log(\"Set up lunR on your phone\\nYour computer must stay awake and connected to the internet.\\n\");\n\t\tconst choice = await choose(\n\t\t\t\"Connect a chat platform\",\n\t\t\t[\n\t\t\t\t{ label: \"Telegram\", value: \"telegram\" },\n\t\t\t\t{ label: \"Discord\", value: \"discord\" },\n\t\t\t\t{ label: \"Both\", value: \"both\" },\n\t\t\t],\n\t\t\tcfg.discord.enabled ? (cfg.telegram.enabled ? \"both\" : \"discord\") : \"telegram\",\n\t\t);\n\t\tfor (const platform of [\"telegram\", \"discord\"] as const) {\n\t\t\tif (choice !== platform && choice !== \"both\") continue;\n\t\t\tconsole.log(\n\t\t\t\tplatform === \"telegram\"\n\t\t\t\t\t? \"\\nTelegram\\n1. Open https://t.me/BotFather and send /newbot.\\n2. Follow its prompts and copy the bot token.\\n3. Open your new bot and send /whoami. If your ID was not configured, it sends a pairing code for local approval.\\nGuide: https://core.telegram.org/bots/tutorial\"\n\t\t\t\t\t: \"\\nDiscord\\n1. Open https://discord.com/developers/applications and create an application.\\n2. Open Bot, create or reset its token, and enable Message Content Intent for ordinary chat.\\n3. Under Installation, add bot and applications.commands scopes. Grant View Channels, Send Messages, Read Message History, Attach Files, and thread permissions if needed.\\n4. Use the install link to add your bot. In Discord, enable Developer Mode and copy your user ID.\\nGuide: https://docs.discord.com/developers/quick-start/getting-started\",\n\t\t\t);\n\t\t\tlet token = cfg[platform].token;\n\t\t\tif (\n\t\t\t\t!token ||\n\t\t\t\t(await choose(`${platform} bot token`, [\n\t\t\t\t\t{ label: \"Keep the saved token\", value: false },\n\t\t\t\t\t{ label: \"Enter a different token\", value: true },\n\t\t\t\t]))\n\t\t\t) {\n\t\t\t\ttoken = (await readSecret(`${platform} bot token`))?.trim();\n\t\t\t}\n\t\t\tif (!token) throw new Error(\"No token entered. Existing configuration was not changed.\");\n\t\t\tconsole.log(`Connected bot: ${await validateBotToken(platform, token)}`);\n\t\t\tcfg[platform].token = token;\n\t\t\tcfg[platform].enabled = true;\n\t\t\tcfg.owners ??= { telegram: [], discord: [] };\n\t\t\tconst ownerChoice = await choose(`${platform} gateway access`, [\n\t\t\t\t...(cfg.owners[platform].length || cfg[platform].allowedUsers.length\n\t\t\t\t\t? [{ label: \"Keep the approved users\", value: \"keep\" }]\n\t\t\t\t\t: []),\n\t\t\t\t{ label: \"Enter my user ID\", value: \"enter\" },\n\t\t\t\t{ label: \"Approve a pairing code later on this computer\", value: \"later\" },\n\t\t\t]);\n\t\t\tconst owner = ownerChoice === \"enter\" ? await ask(`Your ${platform} user ID`) : \"\";\n\t\t\tif (ownerChoice === \"enter\" && !/^\\d+$/.test(owner)) throw new Error(\"User IDs contain digits only.\");\n\t\t\tif (owner) {\n\t\t\t\tcfg.owners[platform] = [...new Set([...cfg.owners[platform], owner])];\n\t\t\t\tcfg[platform].allowedUsers = [...new Set([...cfg[platform].allowedUsers, owner])];\n\t\t\t}\n\t\t}\n\t\tconst folders = [...new Set([cfg.defaultProject, ...(cfg.projectRoots ?? []), process.cwd()])].filter(\n\t\t\t(folder): folder is string => !!folder,\n\t\t);\n\t\tconst folder = await choose<string | null>(\"Default project\", [\n\t\t\t...folders.map((value) => ({ label: value, value })),\n\t\t\t{ label: \"Enter another folder path\", value: null },\n\t\t]);\n\t\tconst root = folder ?? (await ask(\"Project folder path\"));\n\t\tif (!root) throw new Error(\"Enter a project folder. Nothing saved.\");\n\t\tconst path = resolve(root);\n\t\tif (!existsSync(path) || !statSync(path).isDirectory()) throw new Error(\"That project folder does not exist.\");\n\t\tcfg.defaultProject = realpathSync(path);\n\t\tcfg.projectRoots = [...new Set([...(cfg.projectRoots ?? []), cfg.defaultProject])];\n\t\tconst startup = await choose<StartupMode>(\n\t\t\t\"Automatic startup\",\n\t\t\t[\n\t\t\t\t{ label: \"Off. Start manually\", value: \"off\" },\n\t\t\t\t{ label: \"When I sign in\", value: \"login\" },\n\t\t\t\t{ label: \"When the computer boots\", value: \"boot\" },\n\t\t\t],\n\t\t\tloadServiceSettings().startup,\n\t\t);\n\t\tif (startup === \"boot\")\n\t\t\tconsole.log(\n\t\t\t\t\"Boot startup may require administrator permission or OS-managed account credentials. lunR does not save your account password.\",\n\t\t\t);\n\t\tconst { ModelRuntime } = await import(\"../core/model-runtime.ts\");\n\t\tconst runtime = await ModelRuntime.create({ allowModelNetwork: false });\n\t\tconst models = await runtime.getAvailable();\n\t\tif (!models.length)\n\t\t\tthrow new Error(\n\t\t\t\t\"No saved model credentials found. Open lunr locally and use /login, then rerun gateway setup. Nothing saved.\",\n\t\t\t);\n\t\tconst settings = SettingsManager.create(cfg.defaultProject);\n\t\tconst providers = [...new Set(models.map((model) => model.provider))];\n\t\tconst provider = await choose(\n\t\t\t\"Model provider\",\n\t\t\tproviders.map((value) => ({ label: value, value })),\n\t\t\tsettings.getDefaultProvider(),\n\t\t);\n\t\tconst choices = models.filter((model) => model.provider === provider);\n\t\tconst model = await choose(\n\t\t\t\"Model\",\n\t\t\tchoices.map((value) => ({ label: value.id, value })),\n\t\t\tchoices.find((model) => model.id === settings.getDefaultModel()),\n\t\t);\n\t\tif (\n\t\t\t!(await choose(\n\t\t\t\t`Save gateway settings?\\nProject: ${cfg.defaultProject}\\nModel: ${model.provider}/${model.id}\\nStartup: ${startup}`,\n\t\t\t\t[\n\t\t\t\t\t{ label: \"Save\", value: true },\n\t\t\t\t\t{ label: \"Cancel\", value: false },\n\t\t\t\t],\n\t\t\t))\n\t\t) {\n\t\t\tconsole.log(\"Cancelled. Nothing saved.\");\n\t\t\treturn;\n\t\t}\n\t\tsaveGatewayConfig(cfg);\n\t\tsaved = true;\n\t\tsettings.setDefaultModelAndProvider(model.provider, model.id);\n\t\tawait settings.flush();\n\t\tconst features = loadInstallFeatures();\n\t\tfeatures.features[\"chat-platforms\"] = {\n\t\t\tenabled: true,\n\t\t\toptions: {\n\t\t\t\t...features.features[\"chat-platforms\"]?.options,\n\t\t\t\tautostart: loadServiceSettings().startup !== \"off\",\n\t\t\t},\n\t\t};\n\t\tsaveInstallFeatures(features);\n\t\ttry {\n\t\t\tawait configureStartup(startup);\n\t\t} finally {\n\t\t\tfeatures.features[\"chat-platforms\"].options.autostart = loadServiceSettings().startup !== \"off\";\n\t\t\tsaveInstallFeatures(features);\n\t\t}\n\t\tif (\n\t\t\tawait choose(\"Start the gateway now?\", [\n\t\t\t\t{ label: \"Start now\", value: true },\n\t\t\t\t{ label: \"Not now\", value: false },\n\t\t\t])\n\t\t)\n\t\t\tconsole.log(await startGatewayService());\n\t\tconsole.log(\n\t\t\t\"\\nIf you entered your user ID, send /start to your bot, then send a task. Otherwise send /whoami, then on this computer run:\\nlunr gateway pair approve <telegram|discord> <code>\\nApproval grants full gateway access, including local projects and saved sessions. Only approve people you trust with this computer.\",\n\t\t);\n\t} catch (error) {\n\t\tif (error !== cancelled) throw error;\n\t\tconsole.log(saved ? \"Settings saved. Start the gateway with lunr gateway start.\" : \"Cancelled. Nothing saved.\");\n\t}\n}\n\nexport function approveGatewayOwner(platform: string, code: string): string {\n\tif (platform !== \"telegram\" && platform !== \"discord\") throw new Error(\"Choose telegram or discord.\");\n\tconst pairing = createPairingStore();\n\tconst user = pairing.approve(platform, code);\n\tif (!user) throw new Error(\"Pairing code is invalid or expired.\");\n\tconst cfg = loadGatewayConfig();\n\tcfg.owners ??= { telegram: [], discord: [] };\n\tcfg.owners[platform] = [...new Set([...cfg.owners[platform], user])];\n\tcfg[platform].allowedUsers = [...new Set([...cfg[platform].allowedUsers, user])];\n\tsaveGatewayConfig(cfg);\n\treturn `Approved ${platform} user ${user}. Gateway access includes local projects and saved sessions.`;\n}\n"]}