@ashx-j/lunr 0.2.21 → 0.2.23

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 (461) hide show
  1. package/CHANGELOG.md +4 -2
  2. package/README.md +23 -5
  3. package/dist/builtin-extensions/index.d.ts.map +1 -1
  4. package/dist/builtin-extensions/index.js +1 -0
  5. package/dist/builtin-extensions/index.js.map +1 -1
  6. package/dist/builtin-extensions/lunr-browser.d.ts +9 -0
  7. package/dist/builtin-extensions/lunr-browser.d.ts.map +1 -0
  8. package/dist/builtin-extensions/lunr-browser.js +169 -0
  9. package/dist/builtin-extensions/lunr-browser.js.map +1 -0
  10. package/dist/builtin-extensions/lunr-todos.d.ts.map +1 -1
  11. package/dist/builtin-extensions/lunr-todos.js +15 -0
  12. package/dist/builtin-extensions/lunr-todos.js.map +1 -1
  13. package/dist/builtin-extensions/pi-intercom/index.d.ts.map +1 -1
  14. package/dist/builtin-extensions/pi-intercom/index.js +3 -0
  15. package/dist/builtin-extensions/pi-intercom/index.js.map +1 -1
  16. package/dist/builtin-extensions/pi-subagents/src/extension/control-notices.d.ts +1 -1
  17. package/dist/builtin-extensions/pi-subagents/src/extension/control-notices.d.ts.map +1 -1
  18. package/dist/builtin-extensions/pi-subagents/src/extension/control-notices.js +5 -1
  19. package/dist/builtin-extensions/pi-subagents/src/extension/control-notices.js.map +1 -1
  20. package/dist/builtin-extensions/pi-subagents/src/extension/index.d.ts +2 -2
  21. package/dist/builtin-extensions/pi-subagents/src/extension/index.d.ts.map +1 -1
  22. package/dist/builtin-extensions/pi-subagents/src/extension/index.js +18 -5
  23. package/dist/builtin-extensions/pi-subagents/src/extension/index.js.map +1 -1
  24. package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.d.ts +4 -3
  25. package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.d.ts.map +1 -1
  26. package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.js +3 -0
  27. package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.js.map +1 -1
  28. package/dist/builtin-extensions/pi-subagents/src/intercom/communication.d.ts +17 -0
  29. package/dist/builtin-extensions/pi-subagents/src/intercom/communication.d.ts.map +1 -0
  30. package/dist/builtin-extensions/pi-subagents/src/intercom/communication.js +45 -0
  31. package/dist/builtin-extensions/pi-subagents/src/intercom/communication.js.map +1 -0
  32. package/dist/builtin-extensions/pi-subagents/src/intercom/intercom-bridge.d.ts.map +1 -1
  33. package/dist/builtin-extensions/pi-subagents/src/intercom/intercom-bridge.js +4 -11
  34. package/dist/builtin-extensions/pi-subagents/src/intercom/intercom-bridge.js.map +1 -1
  35. package/dist/builtin-extensions/pi-subagents/src/intercom/native-supervisor-channel.d.ts +4 -1
  36. package/dist/builtin-extensions/pi-subagents/src/intercom/native-supervisor-channel.d.ts.map +1 -1
  37. package/dist/builtin-extensions/pi-subagents/src/intercom/native-supervisor-channel.js +160 -51
  38. package/dist/builtin-extensions/pi-subagents/src/intercom/native-supervisor-channel.js.map +1 -1
  39. package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-ask.d.ts.map +1 -1
  40. package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-ask.js +5 -0
  41. package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-ask.js.map +1 -1
  42. package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-questions.d.ts +2 -0
  43. package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-questions.d.ts.map +1 -1
  44. package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-questions.js +3 -2
  45. package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-questions.js.map +1 -1
  46. package/dist/builtin-extensions/pi-subagents/src/runs/background/auto-drain.d.ts +1 -0
  47. package/dist/builtin-extensions/pi-subagents/src/runs/background/auto-drain.d.ts.map +1 -1
  48. package/dist/builtin-extensions/pi-subagents/src/runs/background/auto-drain.js +2 -1
  49. package/dist/builtin-extensions/pi-subagents/src/runs/background/auto-drain.js.map +1 -1
  50. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-wait.d.ts +3 -0
  51. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-wait.d.ts.map +1 -1
  52. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-wait.js +11 -0
  53. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-wait.js.map +1 -1
  54. package/dist/builtin-extensions/pi-subagents/src/runs/background/wait-tool.d.ts.map +1 -1
  55. package/dist/builtin-extensions/pi-subagents/src/runs/background/wait-tool.js +41 -3
  56. package/dist/builtin-extensions/pi-subagents/src/runs/background/wait-tool.js.map +1 -1
  57. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.d.ts.map +1 -1
  58. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.js +4 -0
  59. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.js.map +1 -1
  60. package/dist/builtin-extensions/pi-subagents/src/runs/shared/pi-args.d.ts.map +1 -1
  61. package/dist/builtin-extensions/pi-subagents/src/runs/shared/pi-args.js +3 -0
  62. package/dist/builtin-extensions/pi-subagents/src/runs/shared/pi-args.js.map +1 -1
  63. package/dist/builtin-extensions/pi-subagents/src/runs/shared/subagent-control.d.ts +1 -0
  64. package/dist/builtin-extensions/pi-subagents/src/runs/shared/subagent-control.d.ts.map +1 -1
  65. package/dist/builtin-extensions/pi-subagents/src/runs/shared/subagent-control.js +3 -0
  66. package/dist/builtin-extensions/pi-subagents/src/runs/shared/subagent-control.js.map +1 -1
  67. package/dist/builtin-extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.d.ts.map +1 -1
  68. package/dist/builtin-extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.js +1 -1
  69. package/dist/builtin-extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.js.map +1 -1
  70. package/dist/builtin-extensions/pi-subagents/src/shared/types.d.ts +1 -0
  71. package/dist/builtin-extensions/pi-subagents/src/shared/types.d.ts.map +1 -1
  72. package/dist/builtin-extensions/pi-subagents/src/shared/types.js.map +1 -1
  73. package/dist/builtin-extensions/pi-subagents/src/tui/communication.d.ts +18 -0
  74. package/dist/builtin-extensions/pi-subagents/src/tui/communication.d.ts.map +1 -0
  75. package/dist/builtin-extensions/pi-subagents/src/tui/communication.js +48 -0
  76. package/dist/builtin-extensions/pi-subagents/src/tui/communication.js.map +1 -0
  77. package/dist/builtin-extensions/pi-web-access/index.d.ts.map +1 -1
  78. package/dist/builtin-extensions/pi-web-access/index.js +11 -7
  79. package/dist/builtin-extensions/pi-web-access/index.js.map +1 -1
  80. package/dist/cli/args.d.ts.map +1 -1
  81. package/dist/cli/args.js +2 -1
  82. package/dist/cli/args.js.map +1 -1
  83. package/dist/cli/install-cli.d.ts.map +1 -1
  84. package/dist/cli/install-cli.js +15 -45
  85. package/dist/cli/install-cli.js.map +1 -1
  86. package/dist/core/agent-session-runtime.d.ts +9 -0
  87. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  88. package/dist/core/agent-session-runtime.js +126 -29
  89. package/dist/core/agent-session-runtime.js.map +1 -1
  90. package/dist/core/agent-session.d.ts +22 -0
  91. package/dist/core/agent-session.d.ts.map +1 -1
  92. package/dist/core/agent-session.js +250 -105
  93. package/dist/core/agent-session.js.map +1 -1
  94. package/dist/core/browser/network.d.ts +9 -0
  95. package/dist/core/browser/network.d.ts.map +1 -0
  96. package/dist/core/browser/network.js +146 -0
  97. package/dist/core/browser/network.js.map +1 -0
  98. package/dist/core/browser/runtime.d.ts +24 -0
  99. package/dist/core/browser/runtime.d.ts.map +1 -0
  100. package/dist/core/browser/runtime.js +289 -0
  101. package/dist/core/browser/runtime.js.map +1 -0
  102. package/dist/core/browser/schema.d.ts +16 -0
  103. package/dist/core/browser/schema.d.ts.map +1 -0
  104. package/dist/core/browser/schema.js +36 -0
  105. package/dist/core/browser/schema.js.map +1 -0
  106. package/dist/core/browser/settings.d.ts +8 -0
  107. package/dist/core/browser/settings.d.ts.map +1 -0
  108. package/dist/core/browser/settings.js +30 -0
  109. package/dist/core/browser/settings.js.map +1 -0
  110. package/dist/core/browser/setup.d.ts +2 -0
  111. package/dist/core/browser/setup.d.ts.map +1 -0
  112. package/dist/core/browser/setup.js +16 -0
  113. package/dist/core/browser/setup.js.map +1 -0
  114. package/dist/core/customize.d.ts.map +1 -1
  115. package/dist/core/customize.js +15 -14
  116. package/dist/core/customize.js.map +1 -1
  117. package/dist/core/export-html/index.d.ts.map +1 -1
  118. package/dist/core/export-html/index.js +1 -1
  119. package/dist/core/export-html/index.js.map +1 -1
  120. package/dist/core/extensions/runner.d.ts +1 -0
  121. package/dist/core/extensions/runner.d.ts.map +1 -1
  122. package/dist/core/extensions/runner.js +1 -1
  123. package/dist/core/extensions/runner.js.map +1 -1
  124. package/dist/core/extensions/types.d.ts +1 -1
  125. package/dist/core/extensions/types.d.ts.map +1 -1
  126. package/dist/core/extensions/types.js.map +1 -1
  127. package/dist/core/install-features.d.ts.map +1 -1
  128. package/dist/core/install-features.js +10 -8
  129. package/dist/core/install-features.js.map +1 -1
  130. package/dist/core/memory-cap.d.ts.map +1 -1
  131. package/dist/core/memory-cap.js +5 -3
  132. package/dist/core/memory-cap.js.map +1 -1
  133. package/dist/core/model-tiers.d.ts.map +1 -1
  134. package/dist/core/model-tiers.js +9 -6
  135. package/dist/core/model-tiers.js.map +1 -1
  136. package/dist/core/permissions.d.ts.map +1 -1
  137. package/dist/core/permissions.js +9 -0
  138. package/dist/core/permissions.js.map +1 -1
  139. package/dist/core/plan-mode.d.ts.map +1 -1
  140. package/dist/core/plan-mode.js +3 -0
  141. package/dist/core/plan-mode.js.map +1 -1
  142. package/dist/core/process-registry.d.ts.map +1 -1
  143. package/dist/core/process-registry.js +6 -4
  144. package/dist/core/process-registry.js.map +1 -1
  145. package/dist/core/runtime-scope.d.ts +11 -0
  146. package/dist/core/runtime-scope.d.ts.map +1 -0
  147. package/dist/core/runtime-scope.js +3 -0
  148. package/dist/core/runtime-scope.js.map +1 -0
  149. package/dist/core/sdk.d.ts.map +1 -1
  150. package/dist/core/sdk.js +13 -0
  151. package/dist/core/sdk.js.map +1 -1
  152. package/dist/core/session-handoff.d.ts +35 -0
  153. package/dist/core/session-handoff.d.ts.map +1 -0
  154. package/dist/core/session-handoff.js +214 -0
  155. package/dist/core/session-handoff.js.map +1 -0
  156. package/dist/core/session-manager.d.ts +20 -0
  157. package/dist/core/session-manager.d.ts.map +1 -1
  158. package/dist/core/session-manager.js +184 -22
  159. package/dist/core/session-manager.js.map +1 -1
  160. package/dist/core/session-ownership.d.ts +28 -0
  161. package/dist/core/session-ownership.d.ts.map +1 -0
  162. package/dist/core/session-ownership.js +138 -0
  163. package/dist/core/session-ownership.js.map +1 -0
  164. package/dist/core/session-retention.d.ts.map +1 -1
  165. package/dist/core/session-retention.js +11 -2
  166. package/dist/core/session-retention.js.map +1 -1
  167. package/dist/core/settings-manager.d.ts +11 -0
  168. package/dist/core/settings-manager.d.ts.map +1 -1
  169. package/dist/core/settings-manager.js +27 -0
  170. package/dist/core/settings-manager.js.map +1 -1
  171. package/dist/core/slash-commands.d.ts.map +1 -1
  172. package/dist/core/slash-commands.js +2 -0
  173. package/dist/core/slash-commands.js.map +1 -1
  174. package/dist/core/subagent-wait-interruption.d.ts +11 -0
  175. package/dist/core/subagent-wait-interruption.d.ts.map +1 -0
  176. package/dist/core/subagent-wait-interruption.js +19 -0
  177. package/dist/core/subagent-wait-interruption.js.map +1 -0
  178. package/dist/core/system-prompt.d.ts.map +1 -1
  179. package/dist/core/system-prompt.js +7 -2
  180. package/dist/core/system-prompt.js.map +1 -1
  181. package/dist/core/todo-settings.d.ts +5 -0
  182. package/dist/core/todo-settings.d.ts.map +1 -0
  183. package/dist/core/todo-settings.js +7 -0
  184. package/dist/core/todo-settings.js.map +1 -0
  185. package/dist/core/tools/bash.d.ts.map +1 -1
  186. package/dist/core/tools/bash.js +4 -4
  187. package/dist/core/tools/bash.js.map +1 -1
  188. package/dist/core/tools/edit.d.ts.map +1 -1
  189. package/dist/core/tools/edit.js +5 -3
  190. package/dist/core/tools/edit.js.map +1 -1
  191. package/dist/core/tools/find.d.ts.map +1 -1
  192. package/dist/core/tools/find.js +4 -4
  193. package/dist/core/tools/find.js.map +1 -1
  194. package/dist/core/tools/grep.d.ts.map +1 -1
  195. package/dist/core/tools/grep.js +4 -4
  196. package/dist/core/tools/grep.js.map +1 -1
  197. package/dist/core/tools/ls.d.ts.map +1 -1
  198. package/dist/core/tools/ls.js +4 -4
  199. package/dist/core/tools/ls.js.map +1 -1
  200. package/dist/core/tools/read.d.ts.map +1 -1
  201. package/dist/core/tools/read.js +4 -4
  202. package/dist/core/tools/read.js.map +1 -1
  203. package/dist/core/tools/render-utils.d.ts +14 -5
  204. package/dist/core/tools/render-utils.d.ts.map +1 -1
  205. package/dist/core/tools/render-utils.js +34 -7
  206. package/dist/core/tools/render-utils.js.map +1 -1
  207. package/dist/core/tools/write.d.ts.map +1 -1
  208. package/dist/core/tools/write.js +4 -4
  209. package/dist/core/tools/write.js.map +1 -1
  210. package/dist/core/usage-service.d.ts.map +1 -1
  211. package/dist/core/usage-service.js +5 -3
  212. package/dist/core/usage-service.js.map +1 -1
  213. package/dist/gateway/adapters/discord.d.ts +12 -1
  214. package/dist/gateway/adapters/discord.d.ts.map +1 -1
  215. package/dist/gateway/adapters/discord.js +112 -17
  216. package/dist/gateway/adapters/discord.js.map +1 -1
  217. package/dist/gateway/adapters/telegram.d.ts +4 -2
  218. package/dist/gateway/adapters/telegram.d.ts.map +1 -1
  219. package/dist/gateway/adapters/telegram.js +34 -11
  220. package/dist/gateway/adapters/telegram.js.map +1 -1
  221. package/dist/gateway/agent-bridge.d.ts +14 -3
  222. package/dist/gateway/agent-bridge.d.ts.map +1 -1
  223. package/dist/gateway/agent-bridge.js +252 -60
  224. package/dist/gateway/agent-bridge.js.map +1 -1
  225. package/dist/gateway/approval.d.ts +1 -0
  226. package/dist/gateway/approval.d.ts.map +1 -1
  227. package/dist/gateway/approval.js +60 -18
  228. package/dist/gateway/approval.js.map +1 -1
  229. package/dist/gateway/authz.d.ts +2 -0
  230. package/dist/gateway/authz.d.ts.map +1 -1
  231. package/dist/gateway/authz.js +13 -0
  232. package/dist/gateway/authz.js.map +1 -1
  233. package/dist/gateway/buttons.d.ts +3 -1
  234. package/dist/gateway/buttons.d.ts.map +1 -1
  235. package/dist/gateway/buttons.js +18 -3
  236. package/dist/gateway/buttons.js.map +1 -1
  237. package/dist/gateway/command.d.ts.map +1 -1
  238. package/dist/gateway/command.js +49 -4
  239. package/dist/gateway/command.js.map +1 -1
  240. package/dist/gateway/commands.d.ts.map +1 -1
  241. package/dist/gateway/commands.js +18 -3
  242. package/dist/gateway/commands.js.map +1 -1
  243. package/dist/gateway/config.d.ts +5 -0
  244. package/dist/gateway/config.d.ts.map +1 -1
  245. package/dist/gateway/config.js +5 -0
  246. package/dist/gateway/config.js.map +1 -1
  247. package/dist/gateway/conversations.d.ts +14 -0
  248. package/dist/gateway/conversations.d.ts.map +1 -0
  249. package/dist/gateway/conversations.js +30 -0
  250. package/dist/gateway/conversations.js.map +1 -0
  251. package/dist/gateway/download.d.ts +2 -0
  252. package/dist/gateway/download.d.ts.map +1 -0
  253. package/dist/gateway/download.js +36 -0
  254. package/dist/gateway/download.js.map +1 -0
  255. package/dist/gateway/index.d.ts.map +1 -1
  256. package/dist/gateway/index.js +85 -26
  257. package/dist/gateway/index.js.map +1 -1
  258. package/dist/gateway/mobile-commands.d.ts +24 -0
  259. package/dist/gateway/mobile-commands.d.ts.map +1 -0
  260. package/dist/gateway/mobile-commands.js +422 -0
  261. package/dist/gateway/mobile-commands.js.map +1 -0
  262. package/dist/gateway/presenter.d.ts +16 -0
  263. package/dist/gateway/presenter.d.ts.map +1 -0
  264. package/dist/gateway/presenter.js +210 -0
  265. package/dist/gateway/presenter.js.map +1 -0
  266. package/dist/gateway/router.d.ts +1 -0
  267. package/dist/gateway/router.d.ts.map +1 -1
  268. package/dist/gateway/router.js +32 -3
  269. package/dist/gateway/router.js.map +1 -1
  270. package/dist/gateway/service.d.ts +46 -0
  271. package/dist/gateway/service.d.ts.map +1 -0
  272. package/dist/gateway/service.js +395 -0
  273. package/dist/gateway/service.js.map +1 -0
  274. package/dist/gateway/setup.d.ts +4 -0
  275. package/dist/gateway/setup.d.ts.map +1 -0
  276. package/dist/gateway/setup.js +146 -0
  277. package/dist/gateway/setup.js.map +1 -0
  278. package/dist/gateway/types.d.ts +4 -2
  279. package/dist/gateway/types.d.ts.map +1 -1
  280. package/dist/gateway/types.js.map +1 -1
  281. package/dist/index.d.ts +2 -0
  282. package/dist/index.d.ts.map +1 -1
  283. package/dist/index.js +2 -0
  284. package/dist/index.js.map +1 -1
  285. package/dist/main.d.ts.map +1 -1
  286. package/dist/main.js +2 -1
  287. package/dist/main.js.map +1 -1
  288. package/dist/modes/interactive/components/assistant-message.d.ts +19 -2
  289. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  290. package/dist/modes/interactive/components/assistant-message.js +78 -17
  291. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  292. package/dist/modes/interactive/components/copyable-text.d.ts +27 -0
  293. package/dist/modes/interactive/components/copyable-text.d.ts.map +1 -0
  294. package/dist/modes/interactive/components/copyable-text.js +156 -0
  295. package/dist/modes/interactive/components/copyable-text.js.map +1 -0
  296. package/dist/modes/interactive/components/custom-entry.d.ts +1 -0
  297. package/dist/modes/interactive/components/custom-entry.d.ts.map +1 -1
  298. package/dist/modes/interactive/components/custom-entry.js +8 -0
  299. package/dist/modes/interactive/components/custom-entry.js.map +1 -1
  300. package/dist/modes/interactive/components/custom-message.d.ts +1 -0
  301. package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
  302. package/dist/modes/interactive/components/custom-message.js +8 -0
  303. package/dist/modes/interactive/components/custom-message.js.map +1 -1
  304. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  305. package/dist/modes/interactive/components/session-selector.js +16 -0
  306. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  307. package/dist/modes/interactive/components/settings-selector.d.ts +8 -1
  308. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  309. package/dist/modes/interactive/components/settings-selector.js +51 -0
  310. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  311. package/dist/modes/interactive/components/thinking-tail.d.ts +9 -2
  312. package/dist/modes/interactive/components/thinking-tail.d.ts.map +1 -1
  313. package/dist/modes/interactive/components/thinking-tail.js +43 -1
  314. package/dist/modes/interactive/components/thinking-tail.js.map +1 -1
  315. package/dist/modes/interactive/components/tool-execution.d.ts +4 -3
  316. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  317. package/dist/modes/interactive/components/tool-execution.js +34 -45
  318. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  319. package/dist/modes/interactive/interactive-mode.d.ts +9 -0
  320. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  321. package/dist/modes/interactive/interactive-mode.js +267 -44
  322. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  323. package/dist/modes/interactive/theme/theme.d.ts +1 -0
  324. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  325. package/dist/modes/interactive/theme/theme.js +23 -0
  326. package/dist/modes/interactive/theme/theme.js.map +1 -1
  327. package/dist/node-runtime/agent-session-services-GZVSOGYR.js +49 -0
  328. package/dist/node-runtime/{builtin-extensions-JCOPAAB5.js → builtin-extensions-QVCXNQT4.js} +6 -5
  329. package/dist/node-runtime/{chunk-LTYWTR3V.js → chunk-2MI5OPMN.js} +17 -2
  330. package/dist/node-runtime/{chunk-W3CVH5RX.js → chunk-2TKODGBZ.js} +11 -6
  331. package/dist/node-runtime/chunk-4EULYYR4.js +62 -0
  332. package/dist/node-runtime/{chunk-6N22HULO.js → chunk-5D7LC2ZQ.js} +7 -2
  333. package/dist/node-runtime/{chunk-KBKMCJDU.js → chunk-5ZQXRPMC.js} +19 -4
  334. package/dist/node-runtime/{chunk-BOHIDQT4.js → chunk-6VYZ5UFP.js} +1 -1
  335. package/dist/node-runtime/chunk-AZJHNQKQ.js +205 -0
  336. package/dist/node-runtime/{chunk-A3KMVBZV.js → chunk-BBUVIEZB.js} +1 -10
  337. package/dist/node-runtime/{chunk-IRPJXI6U.js → chunk-BX2RB477.js} +1 -1
  338. package/dist/node-runtime/chunk-CCCN2UCX.js +14 -0
  339. package/dist/node-runtime/{chunk-25I2BHAA.js → chunk-CSUZVNYE.js} +1 -1
  340. package/dist/node-runtime/chunk-DD5YWFSJ.js +708 -0
  341. package/dist/node-runtime/chunk-DQMGU675.js +3409 -0
  342. package/dist/node-runtime/{chunk-QZMODZQ2.js → chunk-E24EO34J.js} +2 -1
  343. package/dist/node-runtime/chunk-EKVFP6YF.js +355 -0
  344. package/dist/node-runtime/chunk-GJ2RDBRL.js +672 -0
  345. package/dist/node-runtime/{chunk-W3SILANP.js → chunk-GMHJCCEN.js} +8 -8
  346. package/dist/node-runtime/{chunk-DDWHZ633.js → chunk-GS42T6MX.js} +1 -1
  347. package/dist/node-runtime/chunk-GS66LV4M.js +2830 -0
  348. package/dist/node-runtime/chunk-H4K3JDRB.js +47 -0
  349. package/dist/node-runtime/{chunk-2SJB2AWP.js → chunk-HMBGROQK.js} +3 -3
  350. package/dist/node-runtime/{chunk-GB2MGFLI.js → chunk-HPUP7E4T.js} +216 -201
  351. package/dist/node-runtime/{chunk-YMEAYRBE.js → chunk-HTFRRDSF.js} +2 -7
  352. package/dist/node-runtime/{chunk-OPEK5RRY.js → chunk-IF24A3FH.js} +1 -1
  353. package/dist/node-runtime/chunk-IMLCWLPI.js +9 -0
  354. package/dist/node-runtime/chunk-KKUTQQV7.js +144 -0
  355. package/dist/node-runtime/chunk-LFZDVKSP.js +521 -0
  356. package/dist/node-runtime/{chunk-2BUAYZ7K.js → chunk-LLUIPGDR.js} +581 -197
  357. package/dist/node-runtime/{chunk-7NBZ5P7I.js → chunk-NAY6UUQZ.js} +1 -1
  358. package/dist/node-runtime/chunk-OAR4TYZE.js +146 -0
  359. package/dist/node-runtime/{chunk-STERBGUB.js → chunk-OFKSVRV7.js} +2 -2
  360. package/dist/node-runtime/{chunk-JZQ7F36T.js → chunk-PCEW76PM.js} +19 -3
  361. package/dist/node-runtime/{chunk-WLLDXJRT.js → chunk-QAZOULTU.js} +29 -1014
  362. package/dist/node-runtime/{chunk-6KDIOJL3.js → chunk-QH6YL7VK.js} +3 -3
  363. package/dist/node-runtime/chunk-R3K2F5GI.js +122 -0
  364. package/dist/node-runtime/{chunk-RNBHABBA.js → chunk-RDDAZOMU.js} +23 -0
  365. package/dist/node-runtime/{chunk-SY2TFMLO.js → chunk-RIR5EDDJ.js} +46 -151
  366. package/dist/node-runtime/chunk-RMQZU2YU.js +117 -0
  367. package/dist/node-runtime/{chunk-6BEIBLQ3.js → chunk-RWTKOC3B.js} +1 -1
  368. package/dist/node-runtime/{chunk-G6LRAP36.js → chunk-TQGPP4SC.js} +1 -1
  369. package/dist/node-runtime/{chunk-Y5KOEMBH.js → chunk-TVJUOJZJ.js} +9 -674
  370. package/dist/node-runtime/chunk-UAEOTO52.js +119 -0
  371. package/dist/node-runtime/{chunk-AY6CAJSL.js → chunk-UJOCPOMX.js} +6 -3
  372. package/dist/node-runtime/chunk-UP2XBVH5.js +40 -0
  373. package/dist/node-runtime/{chunk-WJVFOIB5.js → chunk-UQUCFAJ3.js} +1 -1
  374. package/dist/node-runtime/chunk-URD2SLIT.js +1019 -0
  375. package/dist/node-runtime/chunk-US544NN6.js +13 -0
  376. package/dist/node-runtime/chunk-UWPJL22I.js +341 -0
  377. package/dist/node-runtime/{chunk-4I23VTC4.js → chunk-VWCE2HSZ.js} +21 -124
  378. package/dist/node-runtime/{chunk-VZR3NCM7.js → chunk-W64JC4E7.js} +18 -14
  379. package/dist/node-runtime/{chunk-AWVD5IEY.js → chunk-X3URCYCU.js} +23 -12
  380. package/dist/node-runtime/{chunk-GKLEQ3I4.js → chunk-XLTL257W.js} +126 -27
  381. package/dist/node-runtime/{chunk-WKDK4C5P.js → chunk-YDO2F2IA.js} +38 -164
  382. package/dist/node-runtime/{chunk-PDNXVXMD.js → chunk-YHQ3NBB3.js} +58 -48
  383. package/dist/node-runtime/chunk-YPHAIRZT.js +10 -0
  384. package/dist/node-runtime/cli-runtime.js +2 -2
  385. package/dist/node-runtime/command-PDVTBRWA.js +45 -0
  386. package/dist/node-runtime/{commands-MV5KOZ64.js → commands-KAMO2T6P.js} +10 -10
  387. package/dist/node-runtime/commands-XDCFGIGW.js +36 -0
  388. package/dist/node-runtime/config-RORQUQFG.js +20 -0
  389. package/dist/node-runtime/{customize-LF5VST47.js → customize-VFJV3U6A.js} +2 -1
  390. package/dist/node-runtime/{direct-tool-executor-BK7CLEBX.js → direct-tool-executor-YAVOLDFY.js} +8 -8
  391. package/dist/node-runtime/{export-html-TEXVV5RP.js → export-html-KSOIMVPI.js} +4 -3
  392. package/dist/node-runtime/{extension-input-O4HSAEM4.js → extension-input-E7BJZ35H.js} +4 -4
  393. package/dist/node-runtime/{extension-selector-X5FCX43D.js → extension-selector-WU42XDTU.js} +4 -4
  394. package/dist/node-runtime/{extract-XLQSJN4V.js → extract-EQJE7FZZ.js} +2 -2
  395. package/dist/node-runtime/{gateway-BM6NLOH4.js → gateway-AYWM5DIO.js} +275 -994
  396. package/dist/node-runtime/{gemini-search-U7SUMPQA.js → gemini-search-35OCRFLN.js} +1 -1
  397. package/dist/node-runtime/{gemini-url-context-PXWCBQHK.js → gemini-url-context-UQY3PHHW.js} +2 -2
  398. package/dist/node-runtime/index.js +104 -65
  399. package/dist/node-runtime/{init-3C7Z24OI.js → init-X2LIUB2H.js} +3 -3
  400. package/dist/node-runtime/{install-cli-EXMJQESX.js → install-cli-3BO4MMQ6.js} +21 -82
  401. package/dist/node-runtime/interactive-mode-4MFRKAHG.js +72 -0
  402. package/dist/node-runtime/{interactive-view-ILS6TAN5.js → interactive-view-TUZHCQM3.js} +8 -8
  403. package/dist/node-runtime/lunr-browser-RYFIIVJN.js +174 -0
  404. package/dist/node-runtime/{lunr-cron-4VHP4E4B.js → lunr-cron-YWXEPZMQ.js} +19 -5
  405. package/dist/node-runtime/main.js +44 -31
  406. package/dist/node-runtime/{memory-cap-3S4XRLNP.js → memory-cap-EL3KL4JJ.js} +2 -1
  407. package/dist/node-runtime/mobile-commands-LVHDAUDP.js +32 -0
  408. package/dist/node-runtime/model-runtime-PLQKAG4B.js +16 -0
  409. package/dist/node-runtime/{model-tiers-NJLHUEGK.js → model-tiers-OU3U5CZG.js} +2 -1
  410. package/dist/node-runtime/{package-manager-cli-N37546V5.js → package-manager-cli-6GT3Z3CK.js} +22 -15
  411. package/dist/node-runtime/{pi-intercom-NV2LW6X7.js → pi-intercom-HBPK5HSJ.js} +4 -1
  412. package/dist/node-runtime/{pi-mcp-adapter-GUFZWW54.js → pi-mcp-adapter-E6WULBKF.js} +4 -4
  413. package/dist/node-runtime/{pi-subagents-6MUIFNDM.js → pi-subagents-CDWK2AKY.js} +236 -79
  414. package/dist/node-runtime/{pi-web-access-2CQGFLT2.js → pi-web-access-WTGMNZ32.js} +15 -15
  415. package/dist/node-runtime/process-registry-4FAKZQOL.js +31 -0
  416. package/dist/node-runtime/{proxy-modes-V6YVFH3C.js → proxy-modes-OSQCWRBI.js} +9 -9
  417. package/dist/node-runtime/rpc-entry.js +44 -31
  418. package/dist/node-runtime/{rpc-mode-W5ZTLTMZ.js → rpc-mode-O3XV4SID.js} +2 -2
  419. package/dist/node-runtime/runtime-4VA6JKNF.js +373 -0
  420. package/dist/node-runtime/{runtime-bridges-2VQTLPOZ.js → runtime-bridges-3XUQ46XW.js} +6 -5
  421. package/dist/node-runtime/service-ISSP6VHE.js +36 -0
  422. package/dist/node-runtime/session-handoff-HC7R5E24.js +33 -0
  423. package/dist/node-runtime/{session-manager-E7AREDTV.js → session-manager-CFN4UFM2.js} +2 -1
  424. package/dist/node-runtime/{session-selector-FJ7M2AIX.js → session-selector-GIM4DHQ2.js} +5 -4
  425. package/dist/node-runtime/{settings-manager-CUGAZWAB.js → settings-manager-6VEMXRDL.js} +7 -2
  426. package/dist/node-runtime/setup-5SR2J35A.js +155 -0
  427. package/dist/node-runtime/setup-JBKOLJ6F.js +18 -0
  428. package/dist/node-runtime/{subagent-executor-MH4A7CCF.js → subagent-executor-M5VWB3D3.js} +26 -18
  429. package/dist/node-runtime/theme-UOO5RVFN.js +68 -0
  430. package/dist/node-runtime/trust-manager-MMISNCYO.js +17 -0
  431. package/dist/node-runtime/{update-cli-XTZMZGOL.js → update-cli-UVKJWRRJ.js} +7 -2
  432. package/dist/node-runtime/usage-service-LFB2SWYV.js +37 -0
  433. package/dist/node-runtime/{video-extract-OYT5WKS5.js → video-extract-OOZHR7SU.js} +2 -2
  434. package/dist/node-runtime/{youtube-extract-TQYKGFGS.js → youtube-extract-FNPAUNHU.js} +6 -6
  435. package/docs/browser.md +86 -0
  436. package/docs/extensions.md +2 -0
  437. package/docs/features.md +96 -16
  438. package/docs/interactive-startup.md +2 -1
  439. package/docs/sessions.md +10 -0
  440. package/docs/settings.md +2 -0
  441. package/docs/tui.md +2 -0
  442. package/docs/usage.md +16 -0
  443. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  444. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  445. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  446. package/examples/extensions/gondolin/package-lock.json +2 -2
  447. package/examples/extensions/gondolin/package.json +1 -1
  448. package/examples/extensions/sandbox/package-lock.json +2 -2
  449. package/examples/extensions/sandbox/package.json +1 -1
  450. package/examples/extensions/with-deps/package-lock.json +2 -2
  451. package/examples/extensions/with-deps/package.json +1 -1
  452. package/package.json +7 -4
  453. package/scripts/install-browser.mjs +20 -0
  454. package/dist/node-runtime/agent-session-services-C743TYQE.js +0 -37
  455. package/dist/node-runtime/chunk-VGYZ3APQ.js +0 -59
  456. package/dist/node-runtime/chunk-XI77KVKA.js +0 -6009
  457. package/dist/node-runtime/command-P4NYCJ2M.js +0 -13
  458. package/dist/node-runtime/interactive-mode-EVVBA64D.js +0 -59
  459. package/dist/node-runtime/{chunk-UWQYRSYQ.js → chunk-YJMMG7C6.js} +25 -25
  460. package/dist/node-runtime/{mcp-panel-IIGMXQGP.js → mcp-panel-KTTFXJZ4.js} +3 -3
  461. package/dist/node-runtime/{src-BPQFJR76.js → src-IVPNZ2BX.js} +9 -9
@@ -1 +1 @@
1
- {"version":3,"file":"install-features.js","sourceRoot":"","sources":["../../src/core/install-features.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Install-time feature catalog. Persistence is ~/.lunr/agent/install-features.json\n * (getAgentDir()). Secrets never land here — they go to gateway.json.\n */\n\nimport { chmodSync, existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { appendDebugLog, getAgentDir, VERSION } from \"../config.ts\";\nimport { loadGatewayConfig, saveGatewayConfig } from \"../gateway/config.ts\";\n\nexport type FeatureId = \"chat-platforms\";\n\nexport interface FeatureOptionSpec {\n\tid: string;\n\ttype: \"boolean\" | \"secret\";\n\tprompt: string;\n\tdefault?: boolean;\n\taskWhen?: FeatureId;\n}\n\nexport interface FeatureSpec {\n\tid: FeatureId;\n\ttitle: string;\n\tsummary: string;\n\tdefaultEnabled: boolean;\n\toptions: FeatureOptionSpec[];\n}\n\nexport const FEATURE_CATALOG: FeatureSpec[] = [\n\t{\n\t\tid: \"chat-platforms\",\n\t\ttitle: \"Chat platforms\",\n\t\tsummary: \"Discord + Telegram gateway so lunR can talk in chat apps.\",\n\t\tdefaultEnabled: false,\n\t\toptions: [\n\t\t\t{\n\t\t\t\tid: \"autostart\",\n\t\t\t\ttype: \"boolean\",\n\t\t\t\tprompt: \"Auto-start the lunR gateway daemon when you log in?\",\n\t\t\t\tdefault: false,\n\t\t\t\taskWhen: \"chat-platforms\",\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"telegram-token\",\n\t\t\t\ttype: \"secret\",\n\t\t\t\tprompt: \"Telegram bot token (empty skips; stored in gateway.json)\",\n\t\t\t\taskWhen: \"chat-platforms\",\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"discord-token\",\n\t\t\t\ttype: \"secret\",\n\t\t\t\tprompt: \"Discord bot token (empty skips; stored in gateway.json)\",\n\t\t\t\taskWhen: \"chat-platforms\",\n\t\t\t},\n\t\t],\n\t},\n];\n\nexport interface InstalledFeatureState {\n\tenabled: boolean;\n\toptions: Record<string, boolean | string | number>;\n}\n\nexport interface InstallFeaturesFile {\n\tschemaVersion: 1;\n\tinstallerVersion: string;\n\tinstallMethod: \"binary\";\n\tinstalledAt: string;\n\tupdatedAt: string;\n\tinferUntil?: string;\n\tfeatures: Record<string, InstalledFeatureState>;\n}\n\nexport const CHAT_PLATFORMS_INFER_UNTIL = \"0.2.0\";\n\nexport function installFeaturesPath(): string {\n\treturn join(getAgentDir(), \"install-features.json\");\n}\n\nexport function getFeatureSpec(id: string): FeatureSpec | undefined {\n\treturn FEATURE_CATALOG.find((f) => f.id === id);\n}\n\nexport function getFeatureOptionSpec(id: string, option: string): FeatureOptionSpec | undefined {\n\treturn getFeatureSpec(id)?.options.find((o) => o.id === option);\n}\n\n/** Compare x.y.z; missing parts count as 0. */\nexport function versionGte(a: string, b: string): boolean {\n\tconst pa = a.split(\".\").map((p) => Number.parseInt(p, 10) || 0);\n\tconst pb = b.split(\".\").map((p) => Number.parseInt(p, 10) || 0);\n\tfor (let i = 0; i < 3; i++) {\n\t\tconst d = (pa[i] ?? 0) - (pb[i] ?? 0);\n\t\tif (d !== 0) return d > 0;\n\t}\n\treturn true;\n}\n\nfunction emptyFile(now = new Date().toISOString()): InstallFeaturesFile {\n\treturn {\n\t\tschemaVersion: 1,\n\t\tinstallerVersion: VERSION,\n\t\tinstallMethod: \"binary\",\n\t\tinstalledAt: now,\n\t\tupdatedAt: now,\n\t\tfeatures: {},\n\t};\n}\n\nfunction sanitizeState(raw: unknown): InstalledFeatureState | undefined {\n\tif (raw == null || typeof raw !== \"object\" || Array.isArray(raw)) return undefined;\n\tconst r = raw as Record<string, unknown>;\n\tif (typeof r.enabled !== \"boolean\") return undefined;\n\tconst options: Record<string, boolean | string | number> = {};\n\tif (r.options != null && typeof r.options === \"object\" && !Array.isArray(r.options)) {\n\t\tfor (const [k, v] of Object.entries(r.options as Record<string, unknown>)) {\n\t\t\tif (typeof v === \"boolean\" || typeof v === \"string\" || typeof v === \"number\") {\n\t\t\t\toptions[k] = v;\n\t\t\t}\n\t\t}\n\t}\n\treturn { enabled: r.enabled, options };\n}\n\nfunction sanitizeFile(raw: unknown): InstallFeaturesFile | undefined {\n\tif (raw == null || typeof raw !== \"object\" || Array.isArray(raw)) return undefined;\n\tconst r = raw as Record<string, unknown>;\n\tif (r.schemaVersion !== 1) return undefined;\n\tconst features: Record<string, InstalledFeatureState> = {};\n\tif (r.features != null && typeof r.features === \"object\" && !Array.isArray(r.features)) {\n\t\tfor (const [id, state] of Object.entries(r.features as Record<string, unknown>)) {\n\t\t\tconst sanitized = sanitizeState(state);\n\t\t\tif (sanitized) features[id] = sanitized;\n\t\t}\n\t}\n\tconst now = new Date().toISOString();\n\treturn {\n\t\tschemaVersion: 1,\n\t\tinstallerVersion: typeof r.installerVersion === \"string\" ? r.installerVersion : VERSION,\n\t\tinstallMethod: \"binary\",\n\t\tinstalledAt: typeof r.installedAt === \"string\" ? r.installedAt : now,\n\t\tupdatedAt: typeof r.updatedAt === \"string\" ? r.updatedAt : now,\n\t\tinferUntil: typeof r.inferUntil === \"string\" ? r.inferUntil : undefined,\n\t\tfeatures,\n\t};\n}\n\n/** True when gateway.json has at least one platform enabled with a file token. */\nexport function gatewayHasEnabledFileToken(): boolean {\n\tconst cfg = loadGatewayConfig();\n\tfor (const platform of [cfg.telegram, cfg.discord]) {\n\t\tif (platform.enabled && typeof platform.token === \"string\" && platform.token.length > 0) {\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\nfunction inferPathActive(): boolean {\n\t// Pre-public 0.80.x is numerically > 0.2.0; still infer so dogfooders work\n\t// until PR 7 rewrites the version line to 0.1.0.\n\tif (VERSION.startsWith(\"0.80.\")) return true;\n\treturn !versionGte(VERSION, CHAT_PLATFORMS_INFER_UNTIL);\n}\n\nfunction inferFromGateway(): InstallFeaturesFile | undefined {\n\tif (!inferPathActive()) return undefined;\n\tif (!gatewayHasEnabledFileToken()) return undefined;\n\tconst now = new Date().toISOString();\n\tconst file: InstallFeaturesFile = {\n\t\t...emptyFile(now),\n\t\tinferUntil: CHAT_PLATFORMS_INFER_UNTIL,\n\t\tfeatures: {\n\t\t\t\"chat-platforms\": { enabled: true, options: { autostart: false } },\n\t\t},\n\t};\n\tsaveInstallFeatures(file);\n\tappendDebugLog(\"install-features: inferred chat-platforms enabled (file token, autostart false)\");\n\treturn file;\n}\n\nexport function loadInstallFeatures(): InstallFeaturesFile {\n\tconst path = installFeaturesPath();\n\tif (!existsSync(path)) {\n\t\treturn inferFromGateway() ?? emptyFile();\n\t}\n\ttry {\n\t\tconst parsed = sanitizeFile(JSON.parse(readFileSync(path, \"utf-8\")));\n\t\treturn parsed ?? inferFromGateway() ?? emptyFile();\n\t} catch {\n\t\treturn inferFromGateway() ?? emptyFile();\n\t}\n}\n\nexport function saveInstallFeatures(file: InstallFeaturesFile): void {\n\tconst path = installFeaturesPath();\n\tconst dir = getAgentDir();\n\tif (!existsSync(dir)) mkdirSync(dir, { recursive: true });\n\tconst tmp = `${path}.tmp-${process.pid}`;\n\twriteFileSync(tmp, `${JSON.stringify(file, null, 2)}\\n`, \"utf-8\");\n\trenameSync(tmp, path);\n\ttry {\n\t\tchmodSync(path, 0o644);\n\t} catch {\n\t\t// best-effort (Windows ACLs)\n\t}\n}\n\nexport function isFeatureEnabled(id: FeatureId): boolean {\n\tconst file = loadInstallFeatures();\n\tconst state = file.features[id];\n\tif (state) return state.enabled;\n\treturn getFeatureSpec(id)?.defaultEnabled ?? false;\n}\n\nexport function getFeatureOption(id: FeatureId, option: string): unknown {\n\treturn loadInstallFeatures().features[id]?.options[option];\n}\n\nexport function coerceBooleanSetValue(raw: string): boolean | undefined {\n\tif (raw === \"true\" || raw === \"1\") return true;\n\tif (raw === \"false\" || raw === \"0\") return false;\n\treturn undefined;\n}\n\nexport interface ParsedSet {\n\tid: string;\n\toption: string;\n\tvalue: string;\n}\n\nexport function parseSetAssignment(raw: string): ParsedSet | undefined {\n\tconst eq = raw.indexOf(\"=\");\n\tif (eq <= 0) return undefined;\n\tconst lhs = raw.slice(0, eq);\n\tconst value = raw.slice(eq + 1);\n\tconst dot = lhs.indexOf(\".\");\n\tif (dot <= 0 || dot === lhs.length - 1) return undefined;\n\treturn { id: lhs.slice(0, dot), option: lhs.slice(dot + 1), value };\n}\n\nexport type SetupParseResult =\n\t| {\n\t\t\tok: true;\n\t\t\tyes: boolean;\n\t\t\treconfigure: boolean;\n\t\t\tfeatures: string[];\n\t\t\tnoFeatures: string[];\n\t\t\tsets: ParsedSet[];\n\t }\n\t| { ok: false; error: string };\n\n/** Parse setup / features-enable flags. Unknown flags are an error. */\nexport function parseFeatureFlags(argv: string[]): SetupParseResult {\n\tlet yes = false;\n\tlet reconfigure = false;\n\tconst features: string[] = [];\n\tconst noFeatures: string[] = [];\n\tconst sets: ParsedSet[] = [];\n\n\tfor (let i = 0; i < argv.length; i++) {\n\t\tconst arg = argv[i];\n\t\tif (arg === \"--yes\" || arg === \"-y\") {\n\t\t\tyes = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (arg === \"--reconfigure\") {\n\t\t\treconfigure = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (arg === \"--feature\") {\n\t\t\tconst id = argv[++i];\n\t\t\tif (!id) return { ok: false, error: \"--feature requires an id\" };\n\t\t\tfeatures.push(id);\n\t\t\tcontinue;\n\t\t}\n\t\tif (arg === \"--no-feature\") {\n\t\t\tconst id = argv[++i];\n\t\t\tif (!id) return { ok: false, error: \"--no-feature requires an id\" };\n\t\t\tnoFeatures.push(id);\n\t\t\tcontinue;\n\t\t}\n\t\tif (arg === \"--set\") {\n\t\t\tconst raw = argv[++i];\n\t\t\tif (!raw) return { ok: false, error: \"--set requires <id.option>=<value>\" };\n\t\t\tconst parsed = parseSetAssignment(raw);\n\t\t\tif (!parsed) return { ok: false, error: `invalid --set ${raw}` };\n\t\t\tsets.push(parsed);\n\t\t\tcontinue;\n\t\t}\n\t\tif (arg.startsWith(\"--feature=\")) {\n\t\t\tfeatures.push(arg.slice(\"--feature=\".length));\n\t\t\tcontinue;\n\t\t}\n\t\tif (arg.startsWith(\"--no-feature=\")) {\n\t\t\tnoFeatures.push(arg.slice(\"--no-feature=\".length));\n\t\t\tcontinue;\n\t\t}\n\t\tif (arg.startsWith(\"--set=\")) {\n\t\t\tconst parsed = parseSetAssignment(arg.slice(\"--set=\".length));\n\t\t\tif (!parsed) return { ok: false, error: `invalid --set ${arg}` };\n\t\t\tsets.push(parsed);\n\t\t\tcontinue;\n\t\t}\n\t\treturn { ok: false, error: `unknown flag ${arg}` };\n\t}\n\n\treturn { ok: true, yes, reconfigure, features, noFeatures, sets };\n}\n\nexport type ApplyFlagsError = { ok: false; error: string; exitCode: 2 };\nexport type ApplyFlagsOk = {\n\tok: true;\n\tnext: InstallFeaturesFile;\n\tsecrets: Record<string, string>;\n\tenabledIds: FeatureId[];\n\tdisabledIds: FeatureId[];\n};\n\n/**\n * Validate --feature / --no-feature / --set against the catalog and produce\n * the next install-features.json. Secret --set is rejected. --set on a\n * feature that is not being enabled this invocation is rejected.\n */\nexport function applyFeatureFlags(\n\tcurrent: InstallFeaturesFile,\n\tflags: Extract<SetupParseResult, { ok: true }>,\n): ApplyFlagsOk | ApplyFlagsError {\n\tconst next: InstallFeaturesFile = {\n\t\t...current,\n\t\tinstallerVersion: VERSION,\n\t\tupdatedAt: new Date().toISOString(),\n\t\tfeatures: { ...current.features },\n\t};\n\tconst secrets: Record<string, string> = {};\n\tconst enabledIds: FeatureId[] = [];\n\tconst disabledIds: FeatureId[] = [];\n\n\tfor (const id of flags.features) {\n\t\tif (!getFeatureSpec(id)) return { ok: false, error: `unknown feature ${id}`, exitCode: 2 };\n\t\tconst prev = next.features[id];\n\t\tnext.features[id] = { enabled: true, options: { ...prev?.options } };\n\t\tenabledIds.push(id as FeatureId);\n\t}\n\tfor (const id of flags.noFeatures) {\n\t\tif (!getFeatureSpec(id)) return { ok: false, error: `unknown feature ${id}`, exitCode: 2 };\n\t\tconst prev = next.features[id];\n\t\tnext.features[id] = { enabled: false, options: { ...prev?.options } };\n\t\tdisabledIds.push(id as FeatureId);\n\t}\n\n\tfor (const set of flags.sets) {\n\t\tconst spec = getFeatureSpec(set.id);\n\t\tif (!spec) return { ok: false, error: `unknown feature ${set.id}`, exitCode: 2 };\n\t\tconst option = getFeatureOptionSpec(set.id, set.option);\n\t\tif (!option) return { ok: false, error: `unknown option ${set.id}.${set.option}`, exitCode: 2 };\n\t\tif (option.type === \"secret\") {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: `cannot --set a secret option (${set.id}.${set.option}). set LUNR_TELEGRAM_BOT_TOKEN / LUNR_DISCORD_BOT_TOKEN, or run setup in a TTY`,\n\t\t\t\texitCode: 2,\n\t\t\t};\n\t\t}\n\t\tconst enablingNow = flags.features.includes(set.id) || next.features[set.id]?.enabled === true;\n\t\tif (!enablingNow) {\n\t\t\treturn { ok: false, error: `enable the feature first (${set.id})`, exitCode: 2 };\n\t\t}\n\t\tif (option.type === \"boolean\") {\n\t\t\tconst coerced = coerceBooleanSetValue(set.value);\n\t\t\tif (coerced === undefined) {\n\t\t\t\treturn { ok: false, error: `${set.id}.${set.option} must be true|false|1|0`, exitCode: 2 };\n\t\t\t}\n\t\t\tconst prev = next.features[set.id] ?? { enabled: true, options: {} };\n\t\t\tnext.features[set.id] = { ...prev, enabled: true, options: { ...prev.options, [set.option]: coerced } };\n\t\t}\n\t}\n\n\treturn { ok: true, next, secrets, enabledIds, disabledIds };\n}\n\nexport interface FeatureApplyContext {\n\tprevious: InstalledFeatureState | undefined;\n\tnext: InstalledFeatureState;\n\tsecrets: Record<string, string>;\n\tnonInteractive: boolean;\n}\n\nexport interface FeatureHandler {\n\tapply(ctx: FeatureApplyContext): Promise<void>;\n\tdisable(opts: { purgeSecrets: boolean }): Promise<void>;\n}\n\nfunction persistEnvAndSecretTokens(secrets: Record<string, string>): void {\n\tconst cfg = loadGatewayConfig();\n\tconst telegram = secrets[\"telegram-token\"] || process.env.LUNR_TELEGRAM_BOT_TOKEN || process.env.TELEGRAM_BOT_TOKEN;\n\tconst discord = secrets[\"discord-token\"] || process.env.LUNR_DISCORD_BOT_TOKEN || process.env.DISCORD_BOT_TOKEN;\n\tif (telegram) {\n\t\tcfg.telegram.token = telegram;\n\t\tcfg.telegram.enabled = true;\n\t}\n\tif (discord) {\n\t\tcfg.discord.token = discord;\n\t\tcfg.discord.enabled = true;\n\t}\n\tsaveGatewayConfig(cfg);\n}\n\nexport const chatPlatformsHandler: FeatureHandler = {\n\tasync apply(ctx) {\n\t\tpersistEnvAndSecretTokens(ctx.secrets);\n\t\tconst cfg = loadGatewayConfig();\n\t\tif (cfg.telegram.token) cfg.telegram.enabled = true;\n\t\tif (cfg.discord.token) cfg.discord.enabled = true;\n\t\tsaveGatewayConfig(cfg);\n\t\t// Autostart OS units land in a follow-up PR. The option is persisted.\n\t\tif (ctx.next.options.autostart === true) {\n\t\t\tconst hasFileToken = Boolean(cfg.telegram.token || cfg.discord.token);\n\t\t\tif (!hasFileToken) {\n\t\t\t\tconsole.error(\"chat-platforms: autostart requested but no file token in gateway.json — unit not enabled.\");\n\t\t\t} else {\n\t\t\t\tconsole.error(\"chat-platforms: autostart recorded; login item install is not in this build yet.\");\n\t\t\t}\n\t\t}\n\t},\n\tasync disable(opts) {\n\t\tconst cfg = loadGatewayConfig();\n\t\tcfg.telegram.enabled = false;\n\t\tcfg.discord.enabled = false;\n\t\tif (opts.purgeSecrets) {\n\t\t\tdelete cfg.telegram.token;\n\t\t\tdelete cfg.discord.token;\n\t\t}\n\t\tsaveGatewayConfig(cfg);\n\t},\n};\n\nexport const FEATURE_HANDLERS: Record<FeatureId, FeatureHandler> = {\n\t\"chat-platforms\": chatPlatformsHandler,\n};\n\nexport function appendInstallLog(line: string): void {\n\ttry {\n\t\tconst dir = getAgentDir();\n\t\tif (!existsSync(dir)) mkdirSync(dir, { recursive: true });\n\t\tconst path = join(dir, \"install.log\");\n\t\twriteFileSync(path, `${new Date().toISOString()} ${line}\\n`, { encoding: \"utf-8\", flag: \"a\" });\n\t} catch {\n\t\t// best-effort\n\t}\n}\n\nexport const PRODUCT_UNINSTALL_FLAGS = new Set([\"--purge\", \"--yes\", \"-y\"]);\n\n/** Product uninstall only when every remaining argv is empty or a product flag. */\nexport function isProductUninstallArgv(rest: string[]): boolean {\n\treturn rest.every((arg) => PRODUCT_UNINSTALL_FLAGS.has(arg));\n}\n\nexport function deliverMentionsChatPlatform(deliver: string): boolean {\n\treturn deliver.split(\",\").some((part) => {\n\t\tconst name = part.trim().split(\":\")[0]?.toLowerCase();\n\t\treturn name === \"telegram\" || name === \"discord\";\n\t});\n}\n\nexport function chatPlatformDeliverBlockedMessage(): string {\n\treturn \"chat platforms are not enabled. Enable with: lunr features enable chat-platforms\";\n}\n"]}
1
+ {"version":3,"file":"install-features.js","sourceRoot":"","sources":["../../src/core/install-features.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Install-time feature catalog. Persistence is ~/.lunr/agent/install-features.json\n * (getAgentDir()). Secrets never land here — they go to gateway.json.\n */\n\nimport { chmodSync, existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { appendDebugLog, getAgentDir, VERSION } from \"../config.ts\";\nimport { loadGatewayConfig, saveGatewayConfig } from \"../gateway/config.ts\";\n\nexport type FeatureId = \"chat-platforms\";\n\nexport interface FeatureOptionSpec {\n\tid: string;\n\ttype: \"boolean\" | \"secret\";\n\tprompt: string;\n\tdefault?: boolean;\n\taskWhen?: FeatureId;\n}\n\nexport interface FeatureSpec {\n\tid: FeatureId;\n\ttitle: string;\n\tsummary: string;\n\tdefaultEnabled: boolean;\n\toptions: FeatureOptionSpec[];\n}\n\nexport const FEATURE_CATALOG: FeatureSpec[] = [\n\t{\n\t\tid: \"chat-platforms\",\n\t\ttitle: \"Chat platforms\",\n\t\tsummary: \"Discord + Telegram gateway so lunR can talk in chat apps.\",\n\t\tdefaultEnabled: false,\n\t\toptions: [\n\t\t\t{\n\t\t\t\tid: \"autostart\",\n\t\t\t\ttype: \"boolean\",\n\t\t\t\tprompt: \"Auto-start the lunR gateway daemon when you log in?\",\n\t\t\t\tdefault: false,\n\t\t\t\taskWhen: \"chat-platforms\",\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"telegram-token\",\n\t\t\t\ttype: \"secret\",\n\t\t\t\tprompt: \"Telegram bot token (empty skips; stored in gateway.json)\",\n\t\t\t\taskWhen: \"chat-platforms\",\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: \"discord-token\",\n\t\t\t\ttype: \"secret\",\n\t\t\t\tprompt: \"Discord bot token (empty skips; stored in gateway.json)\",\n\t\t\t\taskWhen: \"chat-platforms\",\n\t\t\t},\n\t\t],\n\t},\n];\n\nexport interface InstalledFeatureState {\n\tenabled: boolean;\n\toptions: Record<string, boolean | string | number>;\n}\n\nexport interface InstallFeaturesFile {\n\tschemaVersion: 1;\n\tinstallerVersion: string;\n\tinstallMethod: \"binary\";\n\tinstalledAt: string;\n\tupdatedAt: string;\n\tinferUntil?: string;\n\tfeatures: Record<string, InstalledFeatureState>;\n}\n\nexport const CHAT_PLATFORMS_INFER_UNTIL = \"0.2.0\";\n\nexport function installFeaturesPath(): string {\n\treturn join(getAgentDir(), \"install-features.json\");\n}\n\nexport function getFeatureSpec(id: string): FeatureSpec | undefined {\n\treturn FEATURE_CATALOG.find((f) => f.id === id);\n}\n\nexport function getFeatureOptionSpec(id: string, option: string): FeatureOptionSpec | undefined {\n\treturn getFeatureSpec(id)?.options.find((o) => o.id === option);\n}\n\n/** Compare x.y.z; missing parts count as 0. */\nexport function versionGte(a: string, b: string): boolean {\n\tconst pa = a.split(\".\").map((p) => Number.parseInt(p, 10) || 0);\n\tconst pb = b.split(\".\").map((p) => Number.parseInt(p, 10) || 0);\n\tfor (let i = 0; i < 3; i++) {\n\t\tconst d = (pa[i] ?? 0) - (pb[i] ?? 0);\n\t\tif (d !== 0) return d > 0;\n\t}\n\treturn true;\n}\n\nfunction emptyFile(now = new Date().toISOString()): InstallFeaturesFile {\n\treturn {\n\t\tschemaVersion: 1,\n\t\tinstallerVersion: VERSION,\n\t\tinstallMethod: \"binary\",\n\t\tinstalledAt: now,\n\t\tupdatedAt: now,\n\t\tfeatures: {},\n\t};\n}\n\nfunction sanitizeState(raw: unknown): InstalledFeatureState | undefined {\n\tif (raw == null || typeof raw !== \"object\" || Array.isArray(raw)) return undefined;\n\tconst r = raw as Record<string, unknown>;\n\tif (typeof r.enabled !== \"boolean\") return undefined;\n\tconst options: Record<string, boolean | string | number> = {};\n\tif (r.options != null && typeof r.options === \"object\" && !Array.isArray(r.options)) {\n\t\tfor (const [k, v] of Object.entries(r.options as Record<string, unknown>)) {\n\t\t\tif (typeof v === \"boolean\" || typeof v === \"string\" || typeof v === \"number\") {\n\t\t\t\toptions[k] = v;\n\t\t\t}\n\t\t}\n\t}\n\treturn { enabled: r.enabled, options };\n}\n\nfunction sanitizeFile(raw: unknown): InstallFeaturesFile | undefined {\n\tif (raw == null || typeof raw !== \"object\" || Array.isArray(raw)) return undefined;\n\tconst r = raw as Record<string, unknown>;\n\tif (r.schemaVersion !== 1) return undefined;\n\tconst features: Record<string, InstalledFeatureState> = {};\n\tif (r.features != null && typeof r.features === \"object\" && !Array.isArray(r.features)) {\n\t\tfor (const [id, state] of Object.entries(r.features as Record<string, unknown>)) {\n\t\t\tconst sanitized = sanitizeState(state);\n\t\t\tif (sanitized) features[id] = sanitized;\n\t\t}\n\t}\n\tconst now = new Date().toISOString();\n\treturn {\n\t\tschemaVersion: 1,\n\t\tinstallerVersion: typeof r.installerVersion === \"string\" ? r.installerVersion : VERSION,\n\t\tinstallMethod: \"binary\",\n\t\tinstalledAt: typeof r.installedAt === \"string\" ? r.installedAt : now,\n\t\tupdatedAt: typeof r.updatedAt === \"string\" ? r.updatedAt : now,\n\t\tinferUntil: typeof r.inferUntil === \"string\" ? r.inferUntil : undefined,\n\t\tfeatures,\n\t};\n}\n\n/** True when gateway.json has at least one platform enabled with a file token. */\nexport function gatewayHasEnabledFileToken(): boolean {\n\tconst cfg = loadGatewayConfig();\n\tfor (const platform of [cfg.telegram, cfg.discord]) {\n\t\tif (platform.enabled && typeof platform.token === \"string\" && platform.token.length > 0) {\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\nfunction inferPathActive(): boolean {\n\t// Pre-public 0.80.x is numerically > 0.2.0; still infer so dogfooders work\n\t// until PR 7 rewrites the version line to 0.1.0.\n\tif (VERSION.startsWith(\"0.80.\")) return true;\n\treturn !versionGte(VERSION, CHAT_PLATFORMS_INFER_UNTIL);\n}\n\nfunction inferFromGateway(): InstallFeaturesFile | undefined {\n\tif (!inferPathActive()) return undefined;\n\tif (!gatewayHasEnabledFileToken()) return undefined;\n\tconst now = new Date().toISOString();\n\tconst file: InstallFeaturesFile = {\n\t\t...emptyFile(now),\n\t\tinferUntil: CHAT_PLATFORMS_INFER_UNTIL,\n\t\tfeatures: {\n\t\t\t\"chat-platforms\": { enabled: true, options: { autostart: false } },\n\t\t},\n\t};\n\tsaveInstallFeatures(file);\n\tappendDebugLog(\"install-features: inferred chat-platforms enabled (file token, autostart false)\");\n\treturn file;\n}\n\nexport function loadInstallFeatures(): InstallFeaturesFile {\n\tconst path = installFeaturesPath();\n\tif (!existsSync(path)) {\n\t\treturn inferFromGateway() ?? emptyFile();\n\t}\n\ttry {\n\t\tconst parsed = sanitizeFile(JSON.parse(readFileSync(path, \"utf-8\")));\n\t\treturn parsed ?? inferFromGateway() ?? emptyFile();\n\t} catch {\n\t\treturn inferFromGateway() ?? emptyFile();\n\t}\n}\n\nexport function saveInstallFeatures(file: InstallFeaturesFile): void {\n\tconst path = installFeaturesPath();\n\tconst dir = getAgentDir();\n\tif (!existsSync(dir)) mkdirSync(dir, { recursive: true });\n\tconst tmp = `${path}.tmp-${process.pid}`;\n\twriteFileSync(tmp, `${JSON.stringify(file, null, 2)}\\n`, \"utf-8\");\n\trenameSync(tmp, path);\n\ttry {\n\t\tchmodSync(path, 0o644);\n\t} catch {\n\t\t// best-effort (Windows ACLs)\n\t}\n}\n\nexport function isFeatureEnabled(id: FeatureId): boolean {\n\tconst file = loadInstallFeatures();\n\tconst state = file.features[id];\n\tif (state) return state.enabled;\n\treturn getFeatureSpec(id)?.defaultEnabled ?? false;\n}\n\nexport function getFeatureOption(id: FeatureId, option: string): unknown {\n\treturn loadInstallFeatures().features[id]?.options[option];\n}\n\nexport function coerceBooleanSetValue(raw: string): boolean | undefined {\n\tif (raw === \"true\" || raw === \"1\") return true;\n\tif (raw === \"false\" || raw === \"0\") return false;\n\treturn undefined;\n}\n\nexport interface ParsedSet {\n\tid: string;\n\toption: string;\n\tvalue: string;\n}\n\nexport function parseSetAssignment(raw: string): ParsedSet | undefined {\n\tconst eq = raw.indexOf(\"=\");\n\tif (eq <= 0) return undefined;\n\tconst lhs = raw.slice(0, eq);\n\tconst value = raw.slice(eq + 1);\n\tconst dot = lhs.indexOf(\".\");\n\tif (dot <= 0 || dot === lhs.length - 1) return undefined;\n\treturn { id: lhs.slice(0, dot), option: lhs.slice(dot + 1), value };\n}\n\nexport type SetupParseResult =\n\t| {\n\t\t\tok: true;\n\t\t\tyes: boolean;\n\t\t\treconfigure: boolean;\n\t\t\tfeatures: string[];\n\t\t\tnoFeatures: string[];\n\t\t\tsets: ParsedSet[];\n\t }\n\t| { ok: false; error: string };\n\n/** Parse setup / features-enable flags. Unknown flags are an error. */\nexport function parseFeatureFlags(argv: string[]): SetupParseResult {\n\tlet yes = false;\n\tlet reconfigure = false;\n\tconst features: string[] = [];\n\tconst noFeatures: string[] = [];\n\tconst sets: ParsedSet[] = [];\n\n\tfor (let i = 0; i < argv.length; i++) {\n\t\tconst arg = argv[i];\n\t\tif (arg === \"--yes\" || arg === \"-y\") {\n\t\t\tyes = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (arg === \"--reconfigure\") {\n\t\t\treconfigure = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (arg === \"--feature\") {\n\t\t\tconst id = argv[++i];\n\t\t\tif (!id) return { ok: false, error: \"--feature requires an id\" };\n\t\t\tfeatures.push(id);\n\t\t\tcontinue;\n\t\t}\n\t\tif (arg === \"--no-feature\") {\n\t\t\tconst id = argv[++i];\n\t\t\tif (!id) return { ok: false, error: \"--no-feature requires an id\" };\n\t\t\tnoFeatures.push(id);\n\t\t\tcontinue;\n\t\t}\n\t\tif (arg === \"--set\") {\n\t\t\tconst raw = argv[++i];\n\t\t\tif (!raw) return { ok: false, error: \"--set requires <id.option>=<value>\" };\n\t\t\tconst parsed = parseSetAssignment(raw);\n\t\t\tif (!parsed) return { ok: false, error: `invalid --set ${raw}` };\n\t\t\tsets.push(parsed);\n\t\t\tcontinue;\n\t\t}\n\t\tif (arg.startsWith(\"--feature=\")) {\n\t\t\tfeatures.push(arg.slice(\"--feature=\".length));\n\t\t\tcontinue;\n\t\t}\n\t\tif (arg.startsWith(\"--no-feature=\")) {\n\t\t\tnoFeatures.push(arg.slice(\"--no-feature=\".length));\n\t\t\tcontinue;\n\t\t}\n\t\tif (arg.startsWith(\"--set=\")) {\n\t\t\tconst parsed = parseSetAssignment(arg.slice(\"--set=\".length));\n\t\t\tif (!parsed) return { ok: false, error: `invalid --set ${arg}` };\n\t\t\tsets.push(parsed);\n\t\t\tcontinue;\n\t\t}\n\t\treturn { ok: false, error: `unknown flag ${arg}` };\n\t}\n\n\treturn { ok: true, yes, reconfigure, features, noFeatures, sets };\n}\n\nexport type ApplyFlagsError = { ok: false; error: string; exitCode: 2 };\nexport type ApplyFlagsOk = {\n\tok: true;\n\tnext: InstallFeaturesFile;\n\tsecrets: Record<string, string>;\n\tenabledIds: FeatureId[];\n\tdisabledIds: FeatureId[];\n};\n\n/**\n * Validate --feature / --no-feature / --set against the catalog and produce\n * the next install-features.json. Secret --set is rejected. --set on a\n * feature that is not being enabled this invocation is rejected.\n */\nexport function applyFeatureFlags(\n\tcurrent: InstallFeaturesFile,\n\tflags: Extract<SetupParseResult, { ok: true }>,\n): ApplyFlagsOk | ApplyFlagsError {\n\tconst next: InstallFeaturesFile = {\n\t\t...current,\n\t\tinstallerVersion: VERSION,\n\t\tupdatedAt: new Date().toISOString(),\n\t\tfeatures: { ...current.features },\n\t};\n\tconst secrets: Record<string, string> = {};\n\tconst enabledIds: FeatureId[] = [];\n\tconst disabledIds: FeatureId[] = [];\n\n\tfor (const id of flags.features) {\n\t\tif (!getFeatureSpec(id)) return { ok: false, error: `unknown feature ${id}`, exitCode: 2 };\n\t\tconst prev = next.features[id];\n\t\tnext.features[id] = { enabled: true, options: { ...prev?.options } };\n\t\tenabledIds.push(id as FeatureId);\n\t}\n\tfor (const id of flags.noFeatures) {\n\t\tif (!getFeatureSpec(id)) return { ok: false, error: `unknown feature ${id}`, exitCode: 2 };\n\t\tconst prev = next.features[id];\n\t\tnext.features[id] = { enabled: false, options: { ...prev?.options } };\n\t\tdisabledIds.push(id as FeatureId);\n\t}\n\n\tfor (const set of flags.sets) {\n\t\tconst spec = getFeatureSpec(set.id);\n\t\tif (!spec) return { ok: false, error: `unknown feature ${set.id}`, exitCode: 2 };\n\t\tconst option = getFeatureOptionSpec(set.id, set.option);\n\t\tif (!option) return { ok: false, error: `unknown option ${set.id}.${set.option}`, exitCode: 2 };\n\t\tif (option.type === \"secret\") {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: `cannot --set a secret option (${set.id}.${set.option}). set LUNR_TELEGRAM_BOT_TOKEN / LUNR_DISCORD_BOT_TOKEN, or run setup in a TTY`,\n\t\t\t\texitCode: 2,\n\t\t\t};\n\t\t}\n\t\tconst enablingNow = flags.features.includes(set.id) || next.features[set.id]?.enabled === true;\n\t\tif (!enablingNow) {\n\t\t\treturn { ok: false, error: `enable the feature first (${set.id})`, exitCode: 2 };\n\t\t}\n\t\tif (option.type === \"boolean\") {\n\t\t\tconst coerced = coerceBooleanSetValue(set.value);\n\t\t\tif (coerced === undefined) {\n\t\t\t\treturn { ok: false, error: `${set.id}.${set.option} must be true|false|1|0`, exitCode: 2 };\n\t\t\t}\n\t\t\tconst prev = next.features[set.id] ?? { enabled: true, options: {} };\n\t\t\tnext.features[set.id] = { ...prev, enabled: true, options: { ...prev.options, [set.option]: coerced } };\n\t\t}\n\t}\n\n\treturn { ok: true, next, secrets, enabledIds, disabledIds };\n}\n\nexport interface FeatureApplyContext {\n\tprevious: InstalledFeatureState | undefined;\n\tnext: InstalledFeatureState;\n\tsecrets: Record<string, string>;\n\tnonInteractive: boolean;\n}\n\nexport interface FeatureHandler {\n\tapply(ctx: FeatureApplyContext): Promise<void>;\n\tdisable(opts: { purgeSecrets: boolean }): Promise<void>;\n}\n\nfunction persistEnvAndSecretTokens(secrets: Record<string, string>): void {\n\tconst cfg = loadGatewayConfig();\n\tconst telegram = secrets[\"telegram-token\"] || process.env.LUNR_TELEGRAM_BOT_TOKEN || process.env.TELEGRAM_BOT_TOKEN;\n\tconst discord = secrets[\"discord-token\"] || process.env.LUNR_DISCORD_BOT_TOKEN || process.env.DISCORD_BOT_TOKEN;\n\tif (telegram) {\n\t\tcfg.telegram.token = telegram;\n\t\tcfg.telegram.enabled = true;\n\t}\n\tif (discord) {\n\t\tcfg.discord.token = discord;\n\t\tcfg.discord.enabled = true;\n\t}\n\tsaveGatewayConfig(cfg);\n}\n\nexport const chatPlatformsHandler: FeatureHandler = {\n\tasync apply(ctx) {\n\t\tpersistEnvAndSecretTokens(ctx.secrets);\n\t\tconst cfg = loadGatewayConfig();\n\t\tif (cfg.telegram.token) cfg.telegram.enabled = true;\n\t\tif (cfg.discord.token) cfg.discord.enabled = true;\n\t\tsaveGatewayConfig(cfg);\n\t\tif (ctx.next.options.autostart === true) {\n\t\t\tif (!cfg.telegram.token && !cfg.discord.token)\n\t\t\t\tthrow new Error(\"Configure a bot token with lunr gateway setup before enabling automatic startup.\");\n\t\t\tawait (await import(\"../gateway/service.ts\")).configureStartup(\"login\");\n\t\t} else if (ctx.previous?.options.autostart === true) {\n\t\t\tawait (await import(\"../gateway/service.ts\")).configureStartup(\"off\");\n\t\t}\n\t},\n\tasync disable(opts) {\n\t\tconst service = await import(\"../gateway/service.ts\");\n\t\tif (service.loadServiceSettings().startup !== \"off\") await service.configureStartup(\"off\");\n\t\tawait service.stopGatewayService();\n\t\tconst cfg = loadGatewayConfig();\n\t\tcfg.telegram.enabled = false;\n\t\tcfg.discord.enabled = false;\n\t\tif (opts.purgeSecrets) {\n\t\t\tdelete cfg.telegram.token;\n\t\t\tdelete cfg.discord.token;\n\t\t}\n\t\tsaveGatewayConfig(cfg);\n\t},\n};\n\nexport const FEATURE_HANDLERS: Record<FeatureId, FeatureHandler> = {\n\t\"chat-platforms\": chatPlatformsHandler,\n};\n\nexport function appendInstallLog(line: string): void {\n\ttry {\n\t\tconst dir = getAgentDir();\n\t\tif (!existsSync(dir)) mkdirSync(dir, { recursive: true });\n\t\tconst path = join(dir, \"install.log\");\n\t\twriteFileSync(path, `${new Date().toISOString()} ${line}\\n`, { encoding: \"utf-8\", flag: \"a\" });\n\t} catch {\n\t\t// best-effort\n\t}\n}\n\nexport const PRODUCT_UNINSTALL_FLAGS = new Set([\"--purge\", \"--yes\", \"-y\"]);\n\n/** Product uninstall only when every remaining argv is empty or a product flag. */\nexport function isProductUninstallArgv(rest: string[]): boolean {\n\treturn rest.every((arg) => PRODUCT_UNINSTALL_FLAGS.has(arg));\n}\n\nexport function deliverMentionsChatPlatform(deliver: string): boolean {\n\treturn deliver.split(\",\").some((part) => {\n\t\tconst name = part.trim().split(\":\")[0]?.toLowerCase();\n\t\treturn name === \"telegram\" || name === \"discord\";\n\t});\n}\n\nexport function chatPlatformDeliverBlockedMessage(): string {\n\treturn \"chat platforms are not enabled. Enable with: lunr features enable chat-platforms\";\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"memory-cap.d.ts","sourceRoot":"","sources":["../../src/core/memory-cap.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D,wEAAwE;AAExE,eAAO,MAAM,wBAAwB,eAAiC,CAAC;AAEvE,eAAO,MAAM,uBAAuB,OAAO,CAAC;AAC5C,eAAO,MAAM,mBAAmB,IAAI,CAAC;AACrC,eAAO,MAAM,mBAAmB,QAAQ,CAAC;AACzC,eAAO,MAAM,iBAAiB,aAA0D,CAAC;AAEzF,MAAM,WAAW,eAAe;IAC/B,SAAS,IAAI,OAAO,CAAC;IACrB,mDAAmD;IACnD,UAAU,IAAI,MAAM,CAAC;IACrB,sDAAsD;IACtD,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAgBD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,eAAe,EAAE,eAAe,GAAG,IAAI,CAG9E;AAED,wBAAgB,kBAAkB,IAAI,eAAe,GAAG,SAAS,CAEhE","sourcesContent":["import type { SettingsManager } from \"./settings-manager.ts\";\n\n/** Memory settings shared with the baked-in simple-memory extension. */\n\nexport const MEMORY_CAP_BRIDGE_SYMBOL = Symbol.for(\"@lunr/memory-cap\");\n\nexport const MEMORY_CHAR_CAP_DEFAULT = 5000;\nexport const MEMORY_CHAR_CAP_MIN = 1;\nexport const MEMORY_CHAR_CAP_MAX = 30000;\nexport const MEMORY_TOOL_NAMES = new Set([\"memory_add\", \"memory_remove\", \"memory_load\"]);\n\nexport interface MemoryCapBridge {\n\tisEnabled(): boolean;\n\t/** Current character cap (clamped to 1..30000). */\n\tgetCharCap(): number;\n\t/** Persist a new character cap into lunR settings. */\n\tsetCharCap(cap: number): void;\n}\n\nlet activeSettingsManager: SettingsManager | undefined;\n\nconst bridge: MemoryCapBridge = {\n\tisEnabled(): boolean {\n\t\treturn activeSettingsManager?.getMemoryEnabled() ?? true;\n\t},\n\tgetCharCap(): number {\n\t\treturn activeSettingsManager?.getMemoryCharCap() ?? MEMORY_CHAR_CAP_DEFAULT;\n\t},\n\tsetCharCap(cap: number): void {\n\t\tactiveSettingsManager?.setMemoryCharCap(cap);\n\t},\n};\n\n/**\n * Register (or re-point) the global memory-cap bridge.\n * Safe to call multiple times — later calls only swap the settings source, so an\n * early startup registration (before extensions load) can be replaced by the live\n * runtime settings manager.\n */\nexport function registerMemoryCapBridge(settingsManager: SettingsManager): void {\n\tactiveSettingsManager = settingsManager;\n\t(globalThis as Record<symbol, unknown>)[MEMORY_CAP_BRIDGE_SYMBOL] = bridge;\n}\n\nexport function getMemoryCapBridge(): MemoryCapBridge | undefined {\n\treturn (globalThis as Record<symbol, unknown>)[MEMORY_CAP_BRIDGE_SYMBOL] as MemoryCapBridge | undefined;\n}\n"]}
1
+ {"version":3,"file":"memory-cap.d.ts","sourceRoot":"","sources":["../../src/core/memory-cap.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D,wEAAwE;AAExE,eAAO,MAAM,wBAAwB,eAAiC,CAAC;AAEvE,eAAO,MAAM,uBAAuB,OAAO,CAAC;AAC5C,eAAO,MAAM,mBAAmB,IAAI,CAAC;AACrC,eAAO,MAAM,mBAAmB,QAAQ,CAAC;AACzC,eAAO,MAAM,iBAAiB,aAA0D,CAAC;AAEzF,MAAM,WAAW,eAAe;IAC/B,SAAS,IAAI,OAAO,CAAC;IACrB,mDAAmD;IACnD,UAAU,IAAI,MAAM,CAAC;IACrB,sDAAsD;IACtD,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAmBD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,eAAe,EAAE,eAAe,GAAG,IAAI,CAG9E;AAED,wBAAgB,kBAAkB,IAAI,eAAe,GAAG,SAAS,CAEhE","sourcesContent":["import { runtimeScope } from \"./runtime-scope.ts\";\nimport type { SettingsManager } from \"./settings-manager.ts\";\n\n/** Memory settings shared with the baked-in simple-memory extension. */\n\nexport const MEMORY_CAP_BRIDGE_SYMBOL = Symbol.for(\"@lunr/memory-cap\");\n\nexport const MEMORY_CHAR_CAP_DEFAULT = 5000;\nexport const MEMORY_CHAR_CAP_MIN = 1;\nexport const MEMORY_CHAR_CAP_MAX = 30000;\nexport const MEMORY_TOOL_NAMES = new Set([\"memory_add\", \"memory_remove\", \"memory_load\"]);\n\nexport interface MemoryCapBridge {\n\tisEnabled(): boolean;\n\t/** Current character cap (clamped to 1..30000). */\n\tgetCharCap(): number;\n\t/** Persist a new character cap into lunR settings. */\n\tsetCharCap(cap: number): void;\n}\n\nlet activeSettingsManager: SettingsManager | undefined;\n\nconst bridge: MemoryCapBridge = {\n\tisEnabled(): boolean {\n\t\treturn (runtimeScope.getStore()?.settingsManager ?? activeSettingsManager)?.getMemoryEnabled() ?? true;\n\t},\n\tgetCharCap(): number {\n\t\treturn (\n\t\t\t(runtimeScope.getStore()?.settingsManager ?? activeSettingsManager)?.getMemoryCharCap() ??\n\t\t\tMEMORY_CHAR_CAP_DEFAULT\n\t\t);\n\t},\n\tsetCharCap(cap: number): void {\n\t\t(runtimeScope.getStore()?.settingsManager ?? activeSettingsManager)?.setMemoryCharCap(cap);\n\t},\n};\n\n/**\n * Register (or re-point) the global memory-cap bridge.\n * Safe to call multiple times — later calls only swap the settings source, so an\n * early startup registration (before extensions load) can be replaced by the live\n * runtime settings manager.\n */\nexport function registerMemoryCapBridge(settingsManager: SettingsManager): void {\n\tactiveSettingsManager = settingsManager;\n\t(globalThis as Record<symbol, unknown>)[MEMORY_CAP_BRIDGE_SYMBOL] = bridge;\n}\n\nexport function getMemoryCapBridge(): MemoryCapBridge | undefined {\n\treturn (globalThis as Record<symbol, unknown>)[MEMORY_CAP_BRIDGE_SYMBOL] as MemoryCapBridge | undefined;\n}\n"]}
@@ -1,3 +1,4 @@
1
+ import { runtimeScope } from "./runtime-scope.js";
1
2
  /** Memory settings shared with the baked-in simple-memory extension. */
2
3
  export const MEMORY_CAP_BRIDGE_SYMBOL = Symbol.for("@lunr/memory-cap");
3
4
  export const MEMORY_CHAR_CAP_DEFAULT = 5000;
@@ -7,13 +8,14 @@ export const MEMORY_TOOL_NAMES = new Set(["memory_add", "memory_remove", "memory
7
8
  let activeSettingsManager;
8
9
  const bridge = {
9
10
  isEnabled() {
10
- return activeSettingsManager?.getMemoryEnabled() ?? true;
11
+ return (runtimeScope.getStore()?.settingsManager ?? activeSettingsManager)?.getMemoryEnabled() ?? true;
11
12
  },
12
13
  getCharCap() {
13
- return activeSettingsManager?.getMemoryCharCap() ?? MEMORY_CHAR_CAP_DEFAULT;
14
+ return ((runtimeScope.getStore()?.settingsManager ?? activeSettingsManager)?.getMemoryCharCap() ??
15
+ MEMORY_CHAR_CAP_DEFAULT);
14
16
  },
15
17
  setCharCap(cap) {
16
- activeSettingsManager?.setMemoryCharCap(cap);
18
+ (runtimeScope.getStore()?.settingsManager ?? activeSettingsManager)?.setMemoryCharCap(cap);
17
19
  },
18
20
  };
19
21
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"memory-cap.js","sourceRoot":"","sources":["../../src/core/memory-cap.ts"],"names":[],"mappings":"AAEA,wEAAwE;AAExE,MAAM,CAAC,MAAM,wBAAwB,GAAG,MAAM,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;AAEvE,MAAM,CAAC,MAAM,uBAAuB,GAAG,IAAI,CAAC;AAC5C,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC;AACrC,MAAM,CAAC,MAAM,mBAAmB,GAAG,KAAK,CAAC;AACzC,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC,CAAC,YAAY,EAAE,eAAe,EAAE,aAAa,CAAC,CAAC,CAAC;AAUzF,IAAI,qBAAkD,CAAC;AAEvD,MAAM,MAAM,GAAoB;IAC/B,SAAS,GAAY;QACpB,OAAO,qBAAqB,EAAE,gBAAgB,EAAE,IAAI,IAAI,CAAC;IAAA,CACzD;IACD,UAAU,GAAW;QACpB,OAAO,qBAAqB,EAAE,gBAAgB,EAAE,IAAI,uBAAuB,CAAC;IAAA,CAC5E;IACD,UAAU,CAAC,GAAW,EAAQ;QAC7B,qBAAqB,EAAE,gBAAgB,CAAC,GAAG,CAAC,CAAC;IAAA,CAC7C;CACD,CAAC;AAEF;;;;;GAKG;AACH,MAAM,UAAU,uBAAuB,CAAC,eAAgC,EAAQ;IAC/E,qBAAqB,GAAG,eAAe,CAAC;IACvC,UAAsC,CAAC,wBAAwB,CAAC,GAAG,MAAM,CAAC;AAAA,CAC3E;AAED,MAAM,UAAU,kBAAkB,GAAgC;IACjE,OAAQ,UAAsC,CAAC,wBAAwB,CAAgC,CAAC;AAAA,CACxG","sourcesContent":["import type { SettingsManager } from \"./settings-manager.ts\";\n\n/** Memory settings shared with the baked-in simple-memory extension. */\n\nexport const MEMORY_CAP_BRIDGE_SYMBOL = Symbol.for(\"@lunr/memory-cap\");\n\nexport const MEMORY_CHAR_CAP_DEFAULT = 5000;\nexport const MEMORY_CHAR_CAP_MIN = 1;\nexport const MEMORY_CHAR_CAP_MAX = 30000;\nexport const MEMORY_TOOL_NAMES = new Set([\"memory_add\", \"memory_remove\", \"memory_load\"]);\n\nexport interface MemoryCapBridge {\n\tisEnabled(): boolean;\n\t/** Current character cap (clamped to 1..30000). */\n\tgetCharCap(): number;\n\t/** Persist a new character cap into lunR settings. */\n\tsetCharCap(cap: number): void;\n}\n\nlet activeSettingsManager: SettingsManager | undefined;\n\nconst bridge: MemoryCapBridge = {\n\tisEnabled(): boolean {\n\t\treturn activeSettingsManager?.getMemoryEnabled() ?? true;\n\t},\n\tgetCharCap(): number {\n\t\treturn activeSettingsManager?.getMemoryCharCap() ?? MEMORY_CHAR_CAP_DEFAULT;\n\t},\n\tsetCharCap(cap: number): void {\n\t\tactiveSettingsManager?.setMemoryCharCap(cap);\n\t},\n};\n\n/**\n * Register (or re-point) the global memory-cap bridge.\n * Safe to call multiple times — later calls only swap the settings source, so an\n * early startup registration (before extensions load) can be replaced by the live\n * runtime settings manager.\n */\nexport function registerMemoryCapBridge(settingsManager: SettingsManager): void {\n\tactiveSettingsManager = settingsManager;\n\t(globalThis as Record<symbol, unknown>)[MEMORY_CAP_BRIDGE_SYMBOL] = bridge;\n}\n\nexport function getMemoryCapBridge(): MemoryCapBridge | undefined {\n\treturn (globalThis as Record<symbol, unknown>)[MEMORY_CAP_BRIDGE_SYMBOL] as MemoryCapBridge | undefined;\n}\n"]}
1
+ {"version":3,"file":"memory-cap.js","sourceRoot":"","sources":["../../src/core/memory-cap.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAGlD,wEAAwE;AAExE,MAAM,CAAC,MAAM,wBAAwB,GAAG,MAAM,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;AAEvE,MAAM,CAAC,MAAM,uBAAuB,GAAG,IAAI,CAAC;AAC5C,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC;AACrC,MAAM,CAAC,MAAM,mBAAmB,GAAG,KAAK,CAAC;AACzC,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC,CAAC,YAAY,EAAE,eAAe,EAAE,aAAa,CAAC,CAAC,CAAC;AAUzF,IAAI,qBAAkD,CAAC;AAEvD,MAAM,MAAM,GAAoB;IAC/B,SAAS,GAAY;QACpB,OAAO,CAAC,YAAY,CAAC,QAAQ,EAAE,EAAE,eAAe,IAAI,qBAAqB,CAAC,EAAE,gBAAgB,EAAE,IAAI,IAAI,CAAC;IAAA,CACvG;IACD,UAAU,GAAW;QACpB,OAAO,CACN,CAAC,YAAY,CAAC,QAAQ,EAAE,EAAE,eAAe,IAAI,qBAAqB,CAAC,EAAE,gBAAgB,EAAE;YACvF,uBAAuB,CACvB,CAAC;IAAA,CACF;IACD,UAAU,CAAC,GAAW,EAAQ;QAC7B,CAAC,YAAY,CAAC,QAAQ,EAAE,EAAE,eAAe,IAAI,qBAAqB,CAAC,EAAE,gBAAgB,CAAC,GAAG,CAAC,CAAC;IAAA,CAC3F;CACD,CAAC;AAEF;;;;;GAKG;AACH,MAAM,UAAU,uBAAuB,CAAC,eAAgC,EAAQ;IAC/E,qBAAqB,GAAG,eAAe,CAAC;IACvC,UAAsC,CAAC,wBAAwB,CAAC,GAAG,MAAM,CAAC;AAAA,CAC3E;AAED,MAAM,UAAU,kBAAkB,GAAgC;IACjE,OAAQ,UAAsC,CAAC,wBAAwB,CAAgC,CAAC;AAAA,CACxG","sourcesContent":["import { runtimeScope } from \"./runtime-scope.ts\";\nimport type { SettingsManager } from \"./settings-manager.ts\";\n\n/** Memory settings shared with the baked-in simple-memory extension. */\n\nexport const MEMORY_CAP_BRIDGE_SYMBOL = Symbol.for(\"@lunr/memory-cap\");\n\nexport const MEMORY_CHAR_CAP_DEFAULT = 5000;\nexport const MEMORY_CHAR_CAP_MIN = 1;\nexport const MEMORY_CHAR_CAP_MAX = 30000;\nexport const MEMORY_TOOL_NAMES = new Set([\"memory_add\", \"memory_remove\", \"memory_load\"]);\n\nexport interface MemoryCapBridge {\n\tisEnabled(): boolean;\n\t/** Current character cap (clamped to 1..30000). */\n\tgetCharCap(): number;\n\t/** Persist a new character cap into lunR settings. */\n\tsetCharCap(cap: number): void;\n}\n\nlet activeSettingsManager: SettingsManager | undefined;\n\nconst bridge: MemoryCapBridge = {\n\tisEnabled(): boolean {\n\t\treturn (runtimeScope.getStore()?.settingsManager ?? activeSettingsManager)?.getMemoryEnabled() ?? true;\n\t},\n\tgetCharCap(): number {\n\t\treturn (\n\t\t\t(runtimeScope.getStore()?.settingsManager ?? activeSettingsManager)?.getMemoryCharCap() ??\n\t\t\tMEMORY_CHAR_CAP_DEFAULT\n\t\t);\n\t},\n\tsetCharCap(cap: number): void {\n\t\t(runtimeScope.getStore()?.settingsManager ?? activeSettingsManager)?.setMemoryCharCap(cap);\n\t},\n};\n\n/**\n * Register (or re-point) the global memory-cap bridge.\n * Safe to call multiple times — later calls only swap the settings source, so an\n * early startup registration (before extensions load) can be replaced by the live\n * runtime settings manager.\n */\nexport function registerMemoryCapBridge(settingsManager: SettingsManager): void {\n\tactiveSettingsManager = settingsManager;\n\t(globalThis as Record<symbol, unknown>)[MEMORY_CAP_BRIDGE_SYMBOL] = bridge;\n}\n\nexport function getMemoryCapBridge(): MemoryCapBridge | undefined {\n\treturn (globalThis as Record<symbol, unknown>)[MEMORY_CAP_BRIDGE_SYMBOL] as MemoryCapBridge | undefined;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"model-tiers.d.ts","sourceRoot":"","sources":["../../src/core/model-tiers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE5E;;;;;;GAMG;AAEH,eAAO,MAAM,UAAU,EAAE,SAAS,aAAa,EAAmC,CAAC;AAEnF,eAAO,MAAM,yBAAyB,eAAkC,CAAC;AAEzE,MAAM,WAAW,gBAAgB;IAChC,+FAA+F;IAC/F,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IAC/C,2EAA2E;IAC3E,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAAC;IACzD,gFAAgF;IAChF,iBAAiB,IAAI,aAAa,GAAG,SAAS,CAAC;IAC/C,+DAA+D;IAC/D,yBAAyB,CAAC,QAAQ,EAAE,CAAC,MAAM,aAAa,GAAG,SAAS,CAAC,GAAG,SAAS,GAAG,IAAI,CAAC;IACzF,kEAAkE;IAClE,iBAAiB,IAAI,OAAO,CAAC;IAC7B,4FAA4F;IAC5F,sBAAsB,IAAI,IAAI,CAAC;IAC/B,qHAAqH;IACrH,gCAAgC,CAAC,SAAS,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,GAAG,IAAI,CAAC;CAC5E;AA6CD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,eAAe,EAAE,eAAe,GAAG,IAAI,CAG9E;AAED,4FAA4F;AAC5F,wBAAgB,mBAAmB,IAAI,gBAAgB,GAAG,SAAS,CAElE;AAED,+FAA+F;AAC/F,wBAAgB,YAAY,CAAC,IAAI,EAAE,aAAa,GAAG,MAAM,GAAG,SAAS,CAEpE;AAED,kEAAkE;AAClE,wBAAgB,iBAAiB,IAAI,OAAO,CAE3C;AAED,qEAAqE;AACrE,wBAAgB,eAAe,CAAC,IAAI,EAAE,aAAa,GAAG,aAAa,GAAG,SAAS,CAE9E","sourcesContent":["import type { ThinkingLevel } from \"@ashx-j/lunr-agent\";\nimport type { ModelTierName, SettingsManager } from \"./settings-manager.ts\";\n\n/**\n * 3-tier subagent model routing (light / standard / heavy).\n *\n * The bridge is exposed on `globalThis` under `Symbol.for(\"@lunr/model-tiers\")` so\n * builtin extensions (pi-subagents) can resolve `tier` params without importing core\n * code (avoids import cycles and keeps upstream diffs minimal).\n */\n\nexport const TIER_NAMES: readonly ModelTierName[] = [\"light\", \"standard\", \"heavy\"];\n\nexport const MODEL_TIERS_BRIDGE_SYMBOL = Symbol.for(\"@lunr/model-tiers\");\n\nexport interface ModelTiersBridge {\n\t/** Resolve a tier to its configured \"provider/model\" string, or undefined if unset/unknown. */\n\tgetTierModel(tier: string): string | undefined;\n\t/** Per-tier thinking level, or undefined to inherit the parent session. */\n\tgetTierThinking(tier: string): ThinkingLevel | undefined;\n\t/** Parent session thinking level (live). Undefined when no session is bound. */\n\tgetParentThinking(): ThinkingLevel | undefined;\n\t/** Bind (or clear) the live parent-session thinking reader. */\n\tsetParentThinkingProvider(provider: (() => ThinkingLevel | undefined) | undefined): void;\n\t/** Whether tier-based subagent routing is enabled in settings. */\n\tisTierModeEnabled(): boolean;\n\t/** Ask the pi-subagents extension to rebuild its tool description from current settings. */\n\trefreshToolDescription(): void;\n\t/** Register (or clear) the callback used by {@link refreshToolDescription}. Called by the extension once at load. */\n\tregisterToolDescriptionRefresher(refresher: (() => void) | undefined): void;\n}\n\nfunction isModelTierName(tier: string): tier is ModelTierName {\n\treturn tier === \"light\" || tier === \"standard\" || tier === \"heavy\";\n}\n\nlet activeSettingsManager: SettingsManager | undefined;\nlet toolDescriptionRefresher: (() => void) | undefined;\nlet parentThinkingProvider: (() => ThinkingLevel | undefined) | undefined;\n\nconst bridge: ModelTiersBridge = {\n\tgetTierModel(tier: string): string | undefined {\n\t\tif (!activeSettingsManager || !isModelTierName(tier)) return undefined;\n\t\treturn activeSettingsManager.getTierModel(tier);\n\t},\n\tgetTierThinking(tier: string): ThinkingLevel | undefined {\n\t\tif (!activeSettingsManager || !isModelTierName(tier)) return undefined;\n\t\treturn activeSettingsManager.getTierThinking(tier);\n\t},\n\tgetParentThinking(): ThinkingLevel | undefined {\n\t\treturn parentThinkingProvider?.();\n\t},\n\tsetParentThinkingProvider(provider: (() => ThinkingLevel | undefined) | undefined): void {\n\t\tparentThinkingProvider = provider;\n\t},\n\tisTierModeEnabled(): boolean {\n\t\treturn activeSettingsManager?.getModelTiersEnabled() ?? false;\n\t},\n\trefreshToolDescription(): void {\n\t\tif (!toolDescriptionRefresher) return;\n\t\ttry {\n\t\t\ttoolDescriptionRefresher();\n\t\t} catch (error) {\n\t\t\t// Settings UI is on the uncaughtException path; a stale/broken refresher\n\t\t\t// must not kill the process. persist of the toggle already happened.\n\t\t\tconsole.warn(\n\t\t\t\t`[model-tiers] refreshToolDescription failed: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t);\n\t\t}\n\t},\n\tregisterToolDescriptionRefresher(refresher: (() => void) | undefined): void {\n\t\ttoolDescriptionRefresher = refresher;\n\t},\n};\n\n/**\n * Register (or re-point) the global model-tier bridge.\n * Safe to call multiple times — later calls only swap the settings source, so an\n * early startup registration (before extensions load) can be replaced by the live\n * runtime settings manager.\n */\nexport function registerModelTierBridge(settingsManager: SettingsManager): void {\n\tactiveSettingsManager = settingsManager;\n\t(globalThis as Record<symbol, unknown>)[MODEL_TIERS_BRIDGE_SYMBOL] = bridge;\n}\n\n/** Read the bridge from `globalThis`, or undefined when not registered (extension-safe). */\nexport function getModelTiersBridge(): ModelTiersBridge | undefined {\n\treturn (globalThis as Record<symbol, unknown>)[MODEL_TIERS_BRIDGE_SYMBOL] as ModelTiersBridge | undefined;\n}\n\n/** Resolve a tier to its configured \"provider/model\" string, or undefined if unset/unknown. */\nexport function getTierModel(tier: ModelTierName): string | undefined {\n\treturn bridge.getTierModel(tier);\n}\n\n/** Whether tier-based subagent routing is enabled in settings. */\nexport function isTierModeEnabled(): boolean {\n\treturn bridge.isTierModeEnabled();\n}\n\n/** Per-tier thinking, or undefined to inherit the parent session. */\nexport function getTierThinking(tier: ModelTierName): ThinkingLevel | undefined {\n\treturn bridge.getTierThinking(tier);\n}\n"]}
1
+ {"version":3,"file":"model-tiers.d.ts","sourceRoot":"","sources":["../../src/core/model-tiers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAEnE,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE5E;;;;;;GAMG;AAEH,eAAO,MAAM,UAAU,EAAE,SAAS,aAAa,EAAmC,CAAC;AAEnF,eAAO,MAAM,yBAAyB,eAAkC,CAAC;AAEzE,MAAM,WAAW,gBAAgB;IAChC,+FAA+F;IAC/F,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IAC/C,2EAA2E;IAC3E,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAAC;IACzD,gFAAgF;IAChF,iBAAiB,IAAI,aAAa,GAAG,SAAS,CAAC;IAC/C,+DAA+D;IAC/D,yBAAyB,CAAC,QAAQ,EAAE,CAAC,MAAM,aAAa,GAAG,SAAS,CAAC,GAAG,SAAS,GAAG,IAAI,CAAC;IACzF,kEAAkE;IAClE,iBAAiB,IAAI,OAAO,CAAC;IAC7B,4FAA4F;IAC5F,sBAAsB,IAAI,IAAI,CAAC;IAC/B,qHAAqH;IACrH,gCAAgC,CAAC,SAAS,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,GAAG,IAAI,CAAC;CAC5E;AA+CD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,eAAe,EAAE,eAAe,GAAG,IAAI,CAG9E;AAED,4FAA4F;AAC5F,wBAAgB,mBAAmB,IAAI,gBAAgB,GAAG,SAAS,CAElE;AAED,+FAA+F;AAC/F,wBAAgB,YAAY,CAAC,IAAI,EAAE,aAAa,GAAG,MAAM,GAAG,SAAS,CAEpE;AAED,kEAAkE;AAClE,wBAAgB,iBAAiB,IAAI,OAAO,CAE3C;AAED,qEAAqE;AACrE,wBAAgB,eAAe,CAAC,IAAI,EAAE,aAAa,GAAG,aAAa,GAAG,SAAS,CAE9E","sourcesContent":["import type { ThinkingLevel } from \"@ashx-j/lunr-agent\";\nimport { runtimeScope } from \"./runtime-scope.ts\";\nimport type { ModelTierName, SettingsManager } from \"./settings-manager.ts\";\n\n/**\n * 3-tier subagent model routing (light / standard / heavy).\n *\n * The bridge is exposed on `globalThis` under `Symbol.for(\"@lunr/model-tiers\")` so\n * builtin extensions (pi-subagents) can resolve `tier` params without importing core\n * code (avoids import cycles and keeps upstream diffs minimal).\n */\n\nexport const TIER_NAMES: readonly ModelTierName[] = [\"light\", \"standard\", \"heavy\"];\n\nexport const MODEL_TIERS_BRIDGE_SYMBOL = Symbol.for(\"@lunr/model-tiers\");\n\nexport interface ModelTiersBridge {\n\t/** Resolve a tier to its configured \"provider/model\" string, or undefined if unset/unknown. */\n\tgetTierModel(tier: string): string | undefined;\n\t/** Per-tier thinking level, or undefined to inherit the parent session. */\n\tgetTierThinking(tier: string): ThinkingLevel | undefined;\n\t/** Parent session thinking level (live). Undefined when no session is bound. */\n\tgetParentThinking(): ThinkingLevel | undefined;\n\t/** Bind (or clear) the live parent-session thinking reader. */\n\tsetParentThinkingProvider(provider: (() => ThinkingLevel | undefined) | undefined): void;\n\t/** Whether tier-based subagent routing is enabled in settings. */\n\tisTierModeEnabled(): boolean;\n\t/** Ask the pi-subagents extension to rebuild its tool description from current settings. */\n\trefreshToolDescription(): void;\n\t/** Register (or clear) the callback used by {@link refreshToolDescription}. Called by the extension once at load. */\n\tregisterToolDescriptionRefresher(refresher: (() => void) | undefined): void;\n}\n\nfunction isModelTierName(tier: string): tier is ModelTierName {\n\treturn tier === \"light\" || tier === \"standard\" || tier === \"heavy\";\n}\n\nlet activeSettingsManager: SettingsManager | undefined;\nlet toolDescriptionRefresher: (() => void) | undefined;\nlet parentThinkingProvider: (() => ThinkingLevel | undefined) | undefined;\n\nconst bridge: ModelTiersBridge = {\n\tgetTierModel(tier: string): string | undefined {\n\t\tconst settings = runtimeScope.getStore()?.settingsManager ?? activeSettingsManager;\n\t\tif (!settings || !isModelTierName(tier)) return undefined;\n\t\treturn settings.getTierModel(tier);\n\t},\n\tgetTierThinking(tier: string): ThinkingLevel | undefined {\n\t\tconst settings = runtimeScope.getStore()?.settingsManager ?? activeSettingsManager;\n\t\tif (!settings || !isModelTierName(tier)) return undefined;\n\t\treturn settings.getTierThinking(tier);\n\t},\n\tgetParentThinking(): ThinkingLevel | undefined {\n\t\treturn runtimeScope.getStore()?.thinking?.() ?? parentThinkingProvider?.();\n\t},\n\tsetParentThinkingProvider(provider: (() => ThinkingLevel | undefined) | undefined): void {\n\t\tparentThinkingProvider = provider;\n\t},\n\tisTierModeEnabled(): boolean {\n\t\treturn (runtimeScope.getStore()?.settingsManager ?? activeSettingsManager)?.getModelTiersEnabled() ?? false;\n\t},\n\trefreshToolDescription(): void {\n\t\tif (!toolDescriptionRefresher) return;\n\t\ttry {\n\t\t\ttoolDescriptionRefresher();\n\t\t} catch (error) {\n\t\t\t// Settings UI is on the uncaughtException path; a stale/broken refresher\n\t\t\t// must not kill the process. persist of the toggle already happened.\n\t\t\tconsole.warn(\n\t\t\t\t`[model-tiers] refreshToolDescription failed: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t);\n\t\t}\n\t},\n\tregisterToolDescriptionRefresher(refresher: (() => void) | undefined): void {\n\t\ttoolDescriptionRefresher = refresher;\n\t},\n};\n\n/**\n * Register (or re-point) the global model-tier bridge.\n * Safe to call multiple times — later calls only swap the settings source, so an\n * early startup registration (before extensions load) can be replaced by the live\n * runtime settings manager.\n */\nexport function registerModelTierBridge(settingsManager: SettingsManager): void {\n\tactiveSettingsManager = settingsManager;\n\t(globalThis as Record<symbol, unknown>)[MODEL_TIERS_BRIDGE_SYMBOL] = bridge;\n}\n\n/** Read the bridge from `globalThis`, or undefined when not registered (extension-safe). */\nexport function getModelTiersBridge(): ModelTiersBridge | undefined {\n\treturn (globalThis as Record<symbol, unknown>)[MODEL_TIERS_BRIDGE_SYMBOL] as ModelTiersBridge | undefined;\n}\n\n/** Resolve a tier to its configured \"provider/model\" string, or undefined if unset/unknown. */\nexport function getTierModel(tier: ModelTierName): string | undefined {\n\treturn bridge.getTierModel(tier);\n}\n\n/** Whether tier-based subagent routing is enabled in settings. */\nexport function isTierModeEnabled(): boolean {\n\treturn bridge.isTierModeEnabled();\n}\n\n/** Per-tier thinking, or undefined to inherit the parent session. */\nexport function getTierThinking(tier: ModelTierName): ThinkingLevel | undefined {\n\treturn bridge.getTierThinking(tier);\n}\n"]}
@@ -1,3 +1,4 @@
1
+ import { runtimeScope } from "./runtime-scope.js";
1
2
  /**
2
3
  * 3-tier subagent model routing (light / standard / heavy).
3
4
  *
@@ -15,23 +16,25 @@ let toolDescriptionRefresher;
15
16
  let parentThinkingProvider;
16
17
  const bridge = {
17
18
  getTierModel(tier) {
18
- if (!activeSettingsManager || !isModelTierName(tier))
19
+ const settings = runtimeScope.getStore()?.settingsManager ?? activeSettingsManager;
20
+ if (!settings || !isModelTierName(tier))
19
21
  return undefined;
20
- return activeSettingsManager.getTierModel(tier);
22
+ return settings.getTierModel(tier);
21
23
  },
22
24
  getTierThinking(tier) {
23
- if (!activeSettingsManager || !isModelTierName(tier))
25
+ const settings = runtimeScope.getStore()?.settingsManager ?? activeSettingsManager;
26
+ if (!settings || !isModelTierName(tier))
24
27
  return undefined;
25
- return activeSettingsManager.getTierThinking(tier);
28
+ return settings.getTierThinking(tier);
26
29
  },
27
30
  getParentThinking() {
28
- return parentThinkingProvider?.();
31
+ return runtimeScope.getStore()?.thinking?.() ?? parentThinkingProvider?.();
29
32
  },
30
33
  setParentThinkingProvider(provider) {
31
34
  parentThinkingProvider = provider;
32
35
  },
33
36
  isTierModeEnabled() {
34
- return activeSettingsManager?.getModelTiersEnabled() ?? false;
37
+ return (runtimeScope.getStore()?.settingsManager ?? activeSettingsManager)?.getModelTiersEnabled() ?? false;
35
38
  },
36
39
  refreshToolDescription() {
37
40
  if (!toolDescriptionRefresher)
@@ -1 +1 @@
1
- {"version":3,"file":"model-tiers.js","sourceRoot":"","sources":["../../src/core/model-tiers.ts"],"names":[],"mappings":"AAGA;;;;;;GAMG;AAEH,MAAM,CAAC,MAAM,UAAU,GAA6B,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;AAEnF,MAAM,CAAC,MAAM,yBAAyB,GAAG,MAAM,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;AAmBzE,SAAS,eAAe,CAAC,IAAY,EAAyB;IAC7D,OAAO,IAAI,KAAK,OAAO,IAAI,IAAI,KAAK,UAAU,IAAI,IAAI,KAAK,OAAO,CAAC;AAAA,CACnE;AAED,IAAI,qBAAkD,CAAC;AACvD,IAAI,wBAAkD,CAAC;AACvD,IAAI,sBAAqE,CAAC;AAE1E,MAAM,MAAM,GAAqB;IAChC,YAAY,CAAC,IAAY,EAAsB;QAC9C,IAAI,CAAC,qBAAqB,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC;YAAE,OAAO,SAAS,CAAC;QACvE,OAAO,qBAAqB,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;IAAA,CAChD;IACD,eAAe,CAAC,IAAY,EAA6B;QACxD,IAAI,CAAC,qBAAqB,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC;YAAE,OAAO,SAAS,CAAC;QACvE,OAAO,qBAAqB,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;IAAA,CACnD;IACD,iBAAiB,GAA8B;QAC9C,OAAO,sBAAsB,EAAE,EAAE,CAAC;IAAA,CAClC;IACD,yBAAyB,CAAC,QAAuD,EAAQ;QACxF,sBAAsB,GAAG,QAAQ,CAAC;IAAA,CAClC;IACD,iBAAiB,GAAY;QAC5B,OAAO,qBAAqB,EAAE,oBAAoB,EAAE,IAAI,KAAK,CAAC;IAAA,CAC9D;IACD,sBAAsB,GAAS;QAC9B,IAAI,CAAC,wBAAwB;YAAE,OAAO;QACtC,IAAI,CAAC;YACJ,wBAAwB,EAAE,CAAC;QAC5B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,yEAAyE;YACzE,qEAAqE;YACrE,OAAO,CAAC,IAAI,CACX,gDAAgD,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CACxG,CAAC;QACH,CAAC;IAAA,CACD;IACD,gCAAgC,CAAC,SAAmC,EAAQ;QAC3E,wBAAwB,GAAG,SAAS,CAAC;IAAA,CACrC;CACD,CAAC;AAEF;;;;;GAKG;AACH,MAAM,UAAU,uBAAuB,CAAC,eAAgC,EAAQ;IAC/E,qBAAqB,GAAG,eAAe,CAAC;IACvC,UAAsC,CAAC,yBAAyB,CAAC,GAAG,MAAM,CAAC;AAAA,CAC5E;AAED,4FAA4F;AAC5F,MAAM,UAAU,mBAAmB,GAAiC;IACnE,OAAQ,UAAsC,CAAC,yBAAyB,CAAiC,CAAC;AAAA,CAC1G;AAED,+FAA+F;AAC/F,MAAM,UAAU,YAAY,CAAC,IAAmB,EAAsB;IACrE,OAAO,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;AAAA,CACjC;AAED,kEAAkE;AAClE,MAAM,UAAU,iBAAiB,GAAY;IAC5C,OAAO,MAAM,CAAC,iBAAiB,EAAE,CAAC;AAAA,CAClC;AAED,qEAAqE;AACrE,MAAM,UAAU,eAAe,CAAC,IAAmB,EAA6B;IAC/E,OAAO,MAAM,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;AAAA,CACpC","sourcesContent":["import type { ThinkingLevel } from \"@ashx-j/lunr-agent\";\nimport type { ModelTierName, SettingsManager } from \"./settings-manager.ts\";\n\n/**\n * 3-tier subagent model routing (light / standard / heavy).\n *\n * The bridge is exposed on `globalThis` under `Symbol.for(\"@lunr/model-tiers\")` so\n * builtin extensions (pi-subagents) can resolve `tier` params without importing core\n * code (avoids import cycles and keeps upstream diffs minimal).\n */\n\nexport const TIER_NAMES: readonly ModelTierName[] = [\"light\", \"standard\", \"heavy\"];\n\nexport const MODEL_TIERS_BRIDGE_SYMBOL = Symbol.for(\"@lunr/model-tiers\");\n\nexport interface ModelTiersBridge {\n\t/** Resolve a tier to its configured \"provider/model\" string, or undefined if unset/unknown. */\n\tgetTierModel(tier: string): string | undefined;\n\t/** Per-tier thinking level, or undefined to inherit the parent session. */\n\tgetTierThinking(tier: string): ThinkingLevel | undefined;\n\t/** Parent session thinking level (live). Undefined when no session is bound. */\n\tgetParentThinking(): ThinkingLevel | undefined;\n\t/** Bind (or clear) the live parent-session thinking reader. */\n\tsetParentThinkingProvider(provider: (() => ThinkingLevel | undefined) | undefined): void;\n\t/** Whether tier-based subagent routing is enabled in settings. */\n\tisTierModeEnabled(): boolean;\n\t/** Ask the pi-subagents extension to rebuild its tool description from current settings. */\n\trefreshToolDescription(): void;\n\t/** Register (or clear) the callback used by {@link refreshToolDescription}. Called by the extension once at load. */\n\tregisterToolDescriptionRefresher(refresher: (() => void) | undefined): void;\n}\n\nfunction isModelTierName(tier: string): tier is ModelTierName {\n\treturn tier === \"light\" || tier === \"standard\" || tier === \"heavy\";\n}\n\nlet activeSettingsManager: SettingsManager | undefined;\nlet toolDescriptionRefresher: (() => void) | undefined;\nlet parentThinkingProvider: (() => ThinkingLevel | undefined) | undefined;\n\nconst bridge: ModelTiersBridge = {\n\tgetTierModel(tier: string): string | undefined {\n\t\tif (!activeSettingsManager || !isModelTierName(tier)) return undefined;\n\t\treturn activeSettingsManager.getTierModel(tier);\n\t},\n\tgetTierThinking(tier: string): ThinkingLevel | undefined {\n\t\tif (!activeSettingsManager || !isModelTierName(tier)) return undefined;\n\t\treturn activeSettingsManager.getTierThinking(tier);\n\t},\n\tgetParentThinking(): ThinkingLevel | undefined {\n\t\treturn parentThinkingProvider?.();\n\t},\n\tsetParentThinkingProvider(provider: (() => ThinkingLevel | undefined) | undefined): void {\n\t\tparentThinkingProvider = provider;\n\t},\n\tisTierModeEnabled(): boolean {\n\t\treturn activeSettingsManager?.getModelTiersEnabled() ?? false;\n\t},\n\trefreshToolDescription(): void {\n\t\tif (!toolDescriptionRefresher) return;\n\t\ttry {\n\t\t\ttoolDescriptionRefresher();\n\t\t} catch (error) {\n\t\t\t// Settings UI is on the uncaughtException path; a stale/broken refresher\n\t\t\t// must not kill the process. persist of the toggle already happened.\n\t\t\tconsole.warn(\n\t\t\t\t`[model-tiers] refreshToolDescription failed: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t);\n\t\t}\n\t},\n\tregisterToolDescriptionRefresher(refresher: (() => void) | undefined): void {\n\t\ttoolDescriptionRefresher = refresher;\n\t},\n};\n\n/**\n * Register (or re-point) the global model-tier bridge.\n * Safe to call multiple times — later calls only swap the settings source, so an\n * early startup registration (before extensions load) can be replaced by the live\n * runtime settings manager.\n */\nexport function registerModelTierBridge(settingsManager: SettingsManager): void {\n\tactiveSettingsManager = settingsManager;\n\t(globalThis as Record<symbol, unknown>)[MODEL_TIERS_BRIDGE_SYMBOL] = bridge;\n}\n\n/** Read the bridge from `globalThis`, or undefined when not registered (extension-safe). */\nexport function getModelTiersBridge(): ModelTiersBridge | undefined {\n\treturn (globalThis as Record<symbol, unknown>)[MODEL_TIERS_BRIDGE_SYMBOL] as ModelTiersBridge | undefined;\n}\n\n/** Resolve a tier to its configured \"provider/model\" string, or undefined if unset/unknown. */\nexport function getTierModel(tier: ModelTierName): string | undefined {\n\treturn bridge.getTierModel(tier);\n}\n\n/** Whether tier-based subagent routing is enabled in settings. */\nexport function isTierModeEnabled(): boolean {\n\treturn bridge.isTierModeEnabled();\n}\n\n/** Per-tier thinking, or undefined to inherit the parent session. */\nexport function getTierThinking(tier: ModelTierName): ThinkingLevel | undefined {\n\treturn bridge.getTierThinking(tier);\n}\n"]}
1
+ {"version":3,"file":"model-tiers.js","sourceRoot":"","sources":["../../src/core/model-tiers.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ThinkingLevel } from \"@ashx-j/lunr-agent\";\nimport { runtimeScope } from \"./runtime-scope.ts\";\nimport type { ModelTierName, SettingsManager } from \"./settings-manager.ts\";\n\n/**\n * 3-tier subagent model routing (light / standard / heavy).\n *\n * The bridge is exposed on `globalThis` under `Symbol.for(\"@lunr/model-tiers\")` so\n * builtin extensions (pi-subagents) can resolve `tier` params without importing core\n * code (avoids import cycles and keeps upstream diffs minimal).\n */\n\nexport const TIER_NAMES: readonly ModelTierName[] = [\"light\", \"standard\", \"heavy\"];\n\nexport const MODEL_TIERS_BRIDGE_SYMBOL = Symbol.for(\"@lunr/model-tiers\");\n\nexport interface ModelTiersBridge {\n\t/** Resolve a tier to its configured \"provider/model\" string, or undefined if unset/unknown. */\n\tgetTierModel(tier: string): string | undefined;\n\t/** Per-tier thinking level, or undefined to inherit the parent session. */\n\tgetTierThinking(tier: string): ThinkingLevel | undefined;\n\t/** Parent session thinking level (live). Undefined when no session is bound. */\n\tgetParentThinking(): ThinkingLevel | undefined;\n\t/** Bind (or clear) the live parent-session thinking reader. */\n\tsetParentThinkingProvider(provider: (() => ThinkingLevel | undefined) | undefined): void;\n\t/** Whether tier-based subagent routing is enabled in settings. */\n\tisTierModeEnabled(): boolean;\n\t/** Ask the pi-subagents extension to rebuild its tool description from current settings. */\n\trefreshToolDescription(): void;\n\t/** Register (or clear) the callback used by {@link refreshToolDescription}. Called by the extension once at load. */\n\tregisterToolDescriptionRefresher(refresher: (() => void) | undefined): void;\n}\n\nfunction isModelTierName(tier: string): tier is ModelTierName {\n\treturn tier === \"light\" || tier === \"standard\" || tier === \"heavy\";\n}\n\nlet activeSettingsManager: SettingsManager | undefined;\nlet toolDescriptionRefresher: (() => void) | undefined;\nlet parentThinkingProvider: (() => ThinkingLevel | undefined) | undefined;\n\nconst bridge: ModelTiersBridge = {\n\tgetTierModel(tier: string): string | undefined {\n\t\tconst settings = runtimeScope.getStore()?.settingsManager ?? activeSettingsManager;\n\t\tif (!settings || !isModelTierName(tier)) return undefined;\n\t\treturn settings.getTierModel(tier);\n\t},\n\tgetTierThinking(tier: string): ThinkingLevel | undefined {\n\t\tconst settings = runtimeScope.getStore()?.settingsManager ?? activeSettingsManager;\n\t\tif (!settings || !isModelTierName(tier)) return undefined;\n\t\treturn settings.getTierThinking(tier);\n\t},\n\tgetParentThinking(): ThinkingLevel | undefined {\n\t\treturn runtimeScope.getStore()?.thinking?.() ?? parentThinkingProvider?.();\n\t},\n\tsetParentThinkingProvider(provider: (() => ThinkingLevel | undefined) | undefined): void {\n\t\tparentThinkingProvider = provider;\n\t},\n\tisTierModeEnabled(): boolean {\n\t\treturn (runtimeScope.getStore()?.settingsManager ?? activeSettingsManager)?.getModelTiersEnabled() ?? false;\n\t},\n\trefreshToolDescription(): void {\n\t\tif (!toolDescriptionRefresher) return;\n\t\ttry {\n\t\t\ttoolDescriptionRefresher();\n\t\t} catch (error) {\n\t\t\t// Settings UI is on the uncaughtException path; a stale/broken refresher\n\t\t\t// must not kill the process. persist of the toggle already happened.\n\t\t\tconsole.warn(\n\t\t\t\t`[model-tiers] refreshToolDescription failed: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t);\n\t\t}\n\t},\n\tregisterToolDescriptionRefresher(refresher: (() => void) | undefined): void {\n\t\ttoolDescriptionRefresher = refresher;\n\t},\n};\n\n/**\n * Register (or re-point) the global model-tier bridge.\n * Safe to call multiple times — later calls only swap the settings source, so an\n * early startup registration (before extensions load) can be replaced by the live\n * runtime settings manager.\n */\nexport function registerModelTierBridge(settingsManager: SettingsManager): void {\n\tactiveSettingsManager = settingsManager;\n\t(globalThis as Record<symbol, unknown>)[MODEL_TIERS_BRIDGE_SYMBOL] = bridge;\n}\n\n/** Read the bridge from `globalThis`, or undefined when not registered (extension-safe). */\nexport function getModelTiersBridge(): ModelTiersBridge | undefined {\n\treturn (globalThis as Record<symbol, unknown>)[MODEL_TIERS_BRIDGE_SYMBOL] as ModelTiersBridge | undefined;\n}\n\n/** Resolve a tier to its configured \"provider/model\" string, or undefined if unset/unknown. */\nexport function getTierModel(tier: ModelTierName): string | undefined {\n\treturn bridge.getTierModel(tier);\n}\n\n/** Whether tier-based subagent routing is enabled in settings. */\nexport function isTierModeEnabled(): boolean {\n\treturn bridge.isTierModeEnabled();\n}\n\n/** Per-tier thinking, or undefined to inherit the parent session. */\nexport function getTierThinking(tier: ModelTierName): ThinkingLevel | undefined {\n\treturn bridge.getTierThinking(tier);\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../../src/core/permissions.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * lunR: permission modes (Manual / YOLO / Plan / Auto).\n *\n * Per-session only — never persisted per session, but the default mode new\n * sessions start with is configurable in /settings (`defaultPermissionMode`,\n * default \"manual\").\n *\n * - manual: every mutating tool call (bash, edit, write) requires approval.\n * - yolo: auto-approve tools; the agent may still ask questions.\n * - plan: read-only; mutating tools are hard-blocked (planModeBlockReason).\n * - auto: fully autonomous; a system-prompt addendum steers the model to\n * self-decide, and rollback is force-enabled for the session.\n *\n * The gate is wired into `agent-session.ts` `_installAgentToolHooks` before\n * the synchronous `_toolCallGates` loop. beforeToolCall is already async, so\n * awaiting the approval dialog is fine.\n *\n * State (mode + session-scoped approvals) is keyed by session id so\n * concurrent gateway chats do not share permission decisions.\n */\n\nimport { dirname, join, resolve } from \"node:path\";\nimport { CONFIG_DIR_NAME, getAgentDir } from \"../config.ts\";\nimport { effectiveLargeSubagentLaunchCountForTurn, LARGE_SUBAGENT_LAUNCH_THRESHOLD } from \"./large-subagent-launch.ts\";\nimport { isUserInstructionsPath } from \"./model-instructions.ts\";\nimport { isCodeRewriteMutating, planModeBlockReason } from \"./plan-mode.ts\";\n\n/** Shift+Tab cycle order. */\nexport const PERMISSION_MODES = [\"manual\", \"yolo\", \"plan\", \"auto\"] as const;\nexport type PermissionMode = (typeof PERMISSION_MODES)[number];\n\nexport function nextPermissionMode(current: PermissionMode): PermissionMode {\n\tconst i = PERMISSION_MODES.indexOf(current);\n\treturn PERMISSION_MODES[(i + 1) % PERMISSION_MODES.length];\n}\n\n/** True when the (default or session) permission mode is plan. */\nexport function isPlanModeActive(sessionId?: string): boolean {\n\treturn getPermissionMode(sessionId) === \"plan\";\n}\n\n/**\n * Destination mode when leaving plan via approve / `/plan off` / `/plan <text>`.\n * Explicit Shift+Tab or `/mode` picks do not use this — they already chose a mode.\n */\nexport function restorePermissionModeAfterPlan(\n\tprevious: PermissionMode | undefined,\n\tdefaultMode: PermissionMode,\n): PermissionMode {\n\tif (previous && previous !== \"plan\") return previous;\n\treturn defaultMode === \"plan\" ? \"yolo\" : defaultMode;\n}\n\nexport interface ApprovalRequest {\n\ttoolName: string;\n\t/** \"bash\" (detail = command), \"edit\"/\"write\" (detail = path),\n\t * \"edit-outside\"/\"write-outside\" when path escapes cwd,\n\t * \"subagent-full\" for full-access children, or \"large-subagent-launch\" for aggregate confirmation. */\n\taction: string;\n\tdetail: string;\n\t/** \"large-subagent-launch\" for aggregate child confirmation, \"plan\" for the\n\t * present_plan plan-approval prompt — the UI renders a dedicated dialog\n\t * for each instead of the generic tool dialog. */\n\tkind?: \"large-subagent-launch\" | \"plan\";\n}\n\nexport type ApprovalDecision = \"once\" | \"session\" | \"reject\";\n/** Handlers may return a bare decision string, a reject carrying user feedback\n * that becomes the block reason the model sees, or an approve carrying optional\n * feedback (plan approval with comments). */\nexport type ApprovalResponse =\n\t| ApprovalDecision\n\t| { decision: \"reject\"; feedback: string }\n\t| { decision: \"approve\"; feedback?: string };\n\n/** Read-only tools that never need approval. */\nconst READ_ONLY_TOOLS = new Set([\n\t\"read\",\n\t\"grep\",\n\t\"find\",\n\t\"ls\",\n\t\"web_search\",\n\t\"web_fetch\",\n\t\"fetch_content\",\n\t\"get_search_content\",\n\t\"sourcegraph\",\n\t\"repo_map\",\n\t\"symbol_outline\",\n\t\"read_block\",\n\t\"code_overview\",\n\t\"ast_search\",\n\t\"lsp_diagnostics\",\n\t\"lsp_hover\",\n\t\"lsp_definition\",\n\t\"lsp_references\",\n\t\"lsp_symbols\",\n\t\"lsp_code_actions\",\n\t\"lsp_completions\",\n\t\"memory_load\",\n]);\n\n/** Tools that mutate state and must be gated in manual mode. */\nconst MUTATING_TOOLS = new Set([\"bash\", \"edit\", \"write\", \"memory_add\", \"memory_remove\", \"cron\"]);\n\nconst REJECT_REASON = \"Rejected by user (permission mode: manual).\";\nexport const NO_HANDLER_REASON = \"Mutating tool blocked in manual mode: no approval channel available.\";\nexport const LARGE_SUBAGENT_LAUNCH_REJECT_REASON = \"Large subagent launch rejected by user.\";\nexport const NO_LARGE_SUBAGENT_LAUNCH_HANDLER_REASON = \"Large subagent launch blocked: no approval channel available.\";\n/** Session-approval keys for child launches. */\nconst LARGE_SUBAGENT_LAUNCH_ACTION = \"large-subagent-launch\";\nconst FULL_CHILD_ACTION = \"subagent-full\";\n\ninterface PermissionContext {\n\tmode: PermissionMode;\n\tapprovals: Set<string>;\n}\n\nconst contexts = new Map<string, PermissionContext>();\nlet defaultContext: PermissionContext = { mode: \"manual\", approvals: new Set() };\nlet approvalHandler: ((req: ApprovalRequest) => Promise<ApprovalResponse>) | undefined;\n/** One aggregate prompt covers every sibling SINGLE `subagent` on the same assistant message. */\nconst turnLargeLaunchDecisions = new WeakMap<\n\tobject,\n\t{ decision: ApprovalDecision; feedback?: string; fullChildrenApproved: boolean }\n>();\n\nfunction getContext(sessionId?: string): PermissionContext {\n\tif (!sessionId) return defaultContext;\n\treturn contexts.get(sessionId) ?? defaultContext;\n}\n\nexport function createPermissionContext(sessionId: string, mode: PermissionMode = defaultContext.mode): void {\n\tcontexts.set(sessionId, { mode, approvals: new Set() });\n}\n\nexport function deletePermissionContext(sessionId: string): void {\n\tcontexts.delete(sessionId);\n}\n\nexport function getPermissionMode(sessionId?: string): PermissionMode {\n\treturn getContext(sessionId).mode;\n}\n\nexport function setPermissionMode(mode: PermissionMode, sessionId?: string): void {\n\tgetContext(sessionId).mode = mode;\n}\n\nexport function resetPermissions(defaultMode: PermissionMode = \"manual\", sessionId?: string): void {\n\tif (sessionId) {\n\t\tcontexts.set(sessionId, { mode: defaultMode, approvals: new Set() });\n\t} else {\n\t\tdefaultContext = { mode: defaultMode, approvals: new Set() };\n\t}\n}\n\nexport function registerApprovalHandler(fn: ((req: ApprovalRequest) => Promise<ApprovalResponse>) | undefined): void {\n\tapprovalHandler = fn;\n}\n\n/** Model-facing result texts for the present_plan tool. */\nexport const PLAN_APPROVED_TEXT = \"Plan approved — implement it now.\";\nexport const PLAN_DECLINED_TEXT = \"Plan declined — revise the plan and call present_plan again.\";\nexport const PLAN_PASS_THROUGH_TEXT = \"Plan presented. The user will review and reply.\";\n\n/** lunr: map an approval response to the model-facing present_plan result text. */\nexport function planApprovalResultText(resp: ApprovalResponse): string {\n\tconst decision = typeof resp === \"string\" ? resp : resp.decision;\n\tconst feedback = typeof resp === \"string\" ? undefined : resp.feedback?.trim();\n\tif (decision === \"reject\") {\n\t\treturn feedback\n\t\t\t? `Plan declined: ${feedback} — revise the plan and call present_plan again.`\n\t\t\t: PLAN_DECLINED_TEXT;\n\t}\n\treturn feedback ? `Plan approved with feedback: ${feedback} — implement it now.` : PLAN_APPROVED_TEXT;\n}\n\n/**\n * lunr: present_plan approval request. Unlike mutating-tool and aggregate launch gates\n * this fails OPEN when no approval handler is registered (or none is reachable,\n * e.g. a gateway turn without a chat context): headless sessions have no one to\n * show the dialog to, so the plan is presented and the user replies in chat\n * instead of deadlocking the turn. Everything else keeps fail-closed.\n */\nexport async function requestPlanApproval(summary: string): Promise<string> {\n\tif (!approvalHandler) return PLAN_PASS_THROUGH_TEXT;\n\tlet resp: ApprovalResponse;\n\ttry {\n\t\tresp = await approvalHandler({ toolName: \"present_plan\", action: \"plan\", detail: summary, kind: \"plan\" });\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : \"approval request failed\";\n\t\tif (message === NO_HANDLER_REASON) return PLAN_PASS_THROUGH_TEXT;\n\t\treturn `Plan declined: ${message} — revise the plan and call present_plan again.`;\n\t}\n\treturn planApprovalResultText(resp);\n}\n\nexport function clearSessionApprovals(sessionId?: string): void {\n\tgetContext(sessionId).approvals.clear();\n}\n\n/** Test seam: remove every per-session context and restore the default. */\nexport function resetAllPermissionContexts(): void {\n\tcontexts.clear();\n\tdefaultContext = { mode: \"manual\", approvals: new Set() };\n\tapprovalHandler = undefined;\n}\n\n/** Appended to the system prompt while auto mode is active. */\nexport const AUTO_MODE_ADDENDUM =\n\t\"You are running fully autonomously. Do not ask the user questions or wait for confirmation; make reasonable decisions and complete the task end-to-end.\";\n\nfunction isPathOutsideCwd(absPath: string, cwd: string): boolean {\n\tconst norm = (p: string) => p.replace(/\\\\/g, \"/\").replace(/\\/$/, \"\");\n\tconst np = norm(absPath);\n\tconst nc = norm(cwd);\n\tif (np === nc) return false;\n\treturn !np.startsWith(`${nc}/`);\n}\n\nfunction resolvePath(cwd: string, p: unknown): string {\n\tif (typeof p !== \"string\") return \"\";\n\tif (!p) return \"\";\n\treturn resolve(cwd, p);\n}\n\nexport const GLOBAL_AGENTS_FILE_WRITE_BLOCK_REASON =\n\t\"The agents instruction tree is user-managed. The agent cannot change ~/.lunr/agent/agents/.\";\nexport const MEMORY_FILE_DIRECT_WRITE_BLOCK_REASON =\n\t\"Memory is model-managed through the memory tools. Do not directly change ~/.lunr/simple-memory/memory.md.\";\nexport const SETTINGS_FILE_DIRECT_WRITE_BLOCK_REASON =\n\t\"lunR settings are user-managed through /settings. Do not directly change settings.json.\";\n\nfunction protectedFileWriteReason(toolName: string, input: Record<string, unknown>, cwd: string): string | undefined {\n\tif (toolName !== \"edit\" && toolName !== \"write\" && toolName !== \"code_rewrite\") return undefined;\n\tconst target = resolvePath(cwd, input.path);\n\tif (!target) return undefined;\n\tconst normalize = (path: string) => {\n\t\tconst normalized = resolve(path).replace(/\\\\/g, \"/\").replace(/\\/$/, \"\");\n\t\treturn process.platform === \"win32\" ? normalized.toLowerCase() : normalized;\n\t};\n\tif (isUserInstructionsPath(target, getAgentDir())) {\n\t\treturn GLOBAL_AGENTS_FILE_WRITE_BLOCK_REASON;\n\t}\n\tif (normalize(target) === normalize(join(dirname(getAgentDir()), \"simple-memory\", \"memory.md\"))) {\n\t\treturn MEMORY_FILE_DIRECT_WRITE_BLOCK_REASON;\n\t}\n\tconst globalSettings = normalize(join(getAgentDir(), \"settings.json\"));\n\tconst projectSettings = normalize(join(cwd, CONFIG_DIR_NAME, \"settings.json\"));\n\tconst normalizedTarget = normalize(target);\n\tif (normalizedTarget === globalSettings || normalizedTarget === projectSettings) {\n\t\treturn SETTINGS_FILE_DIRECT_WRITE_BLOCK_REASON;\n\t}\n\treturn undefined;\n}\n\nfunction isMutatingTool(toolName: string): boolean {\n\treturn MUTATING_TOOLS.has(toolName);\n}\n\ninterface RequestedChildLaunch {\n\tdescription: string;\n\tpermissions: \"full\" | \"read-only\";\n}\n\nfunction collectRequestedChildLaunches(value: unknown, launches: RequestedChildLaunch[]): void {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) return;\n\tconst input = value as Record<string, unknown>;\n\tif (typeof input.task === \"string\" && input.task.trim()) {\n\t\tlaunches.push({\n\t\t\tdescription:\n\t\t\t\ttypeof input.description === \"string\" && input.description.trim()\n\t\t\t\t\t? input.description.trim()\n\t\t\t\t\t: input.task.trim(),\n\t\t\tpermissions: input.permissions === \"read-only\" ? \"read-only\" : \"full\",\n\t\t});\n\t\treturn;\n\t}\n\tfor (const key of [\"tasks\", \"chain\", \"parallel\"] as const) {\n\t\tconst children = input[key];\n\t\tif (Array.isArray(children)) {\n\t\t\tfor (const child of children) collectRequestedChildLaunches(child, launches);\n\t\t} else if (key === \"parallel\") {\n\t\t\tcollectRequestedChildLaunches(children, launches);\n\t\t}\n\t}\n}\n\nfunction getRequestedChildLaunches(input: Record<string, unknown>): RequestedChildLaunch[] {\n\tconst launches: RequestedChildLaunch[] = [];\n\tcollectRequestedChildLaunches(input, launches);\n\treturn launches;\n}\n\nfunction requiresManualApproval(toolName: string, input: Record<string, unknown>): boolean {\n\tif (isMutatingTool(toolName)) return true;\n\tif (toolName === \"subagent\") {\n\t\treturn getRequestedChildLaunches(input).some((launch) => launch.permissions === \"full\");\n\t}\n\treturn toolName === \"code_rewrite\" && isCodeRewriteMutating(input);\n}\n\nexport interface GateOptions {\n\t/** Global preference for aggregate confirmation. Defaults to enabled. */\n\tconfirmLargeSubagentLaunches?: boolean;\n\t/** Assistant message that issued this tool call. Same-turn sibling SINGLE\n\t * `subagent` calls count toward the aggregate threshold. */\n\tassistantMessage?: {\n\t\tcontent?: ReadonlyArray<{ type?: string; name?: string; arguments?: unknown }>;\n\t};\n}\n\nfunction firstTaskText(value: unknown): string {\n\tif (typeof value === \"string\" && value.trim()) return sanitizeDetail(value);\n\treturn \"\";\n}\n\n/** First task text of a parallel fan-out or sibling SINGLE, used as the dialog summary. */\nfunction largeLaunchTaskSummary(\n\tinput: Record<string, unknown>,\n\tassistantMessage?: GateOptions[\"assistantMessage\"],\n): string {\n\tif (Array.isArray(input.tasks)) {\n\t\tfor (const task of input.tasks) {\n\t\t\tconst text = task && typeof task === \"object\" ? firstTaskText((task as { task?: unknown }).task) : \"\";\n\t\t\tif (text) return text;\n\t\t}\n\t}\n\tconst own = firstTaskText(input.task);\n\tif (own) return own;\n\tfor (const block of assistantMessage?.content ?? []) {\n\t\tif (block.type !== \"toolCall\" || block.name !== \"subagent\") continue;\n\t\tconst args =\n\t\t\tblock.arguments && typeof block.arguments === \"object\" && !Array.isArray(block.arguments)\n\t\t\t\t? (block.arguments as Record<string, unknown>)\n\t\t\t\t: undefined;\n\t\tconst text = firstTaskText(args?.task);\n\t\tif (text) return text;\n\t}\n\treturn \"\";\n}\n\n/**\n * Aggregate launch gate. A launch above LARGE_SUBAGENT_LAUNCH_THRESHOLD\n * parallel subagents in one `tasks`/`chain.parallel` call, or that many same-turn\n * SINGLE `subagent` calls) requires user approval in manual AND yolo modes; auto\n * mode runs it unconditionally.\n * Fail-closed without an approval handler, same as the mutating-tool gate.\n */\nasync function gateLargeSubagentLaunch(\n\tinput: Record<string, unknown>,\n\tctx: PermissionContext,\n\toptions?: GateOptions,\n): Promise<{ block: true; reason: string } | { fullChildrenApproved: boolean } | undefined> {\n\tif (ctx.mode === \"auto\") return undefined;\n\tif (options?.confirmLargeSubagentLaunches === false) return undefined;\n\tconst count = effectiveLargeSubagentLaunchCountForTurn(input, options?.assistantMessage);\n\tif (count <= LARGE_SUBAGENT_LAUNCH_THRESHOLD) return undefined;\n\tif (ctx.approvals.has(LARGE_SUBAGENT_LAUNCH_ACTION)) return { fullChildrenApproved: false };\n\n\tconst turnKey = options?.assistantMessage;\n\tconst cached = turnKey ? turnLargeLaunchDecisions.get(turnKey) : undefined;\n\tif (cached) {\n\t\tif (cached.decision === \"reject\") {\n\t\t\treturn {\n\t\t\t\tblock: true,\n\t\t\t\treason: cached.feedback\n\t\t\t\t\t? `${LARGE_SUBAGENT_LAUNCH_REJECT_REASON} ${cached.feedback}`\n\t\t\t\t\t: LARGE_SUBAGENT_LAUNCH_REJECT_REASON,\n\t\t\t};\n\t\t}\n\t\treturn { fullChildrenApproved: cached.fullChildrenApproved };\n\t}\n\n\tif (!approvalHandler) {\n\t\treturn { block: true, reason: NO_LARGE_SUBAGENT_LAUNCH_HANDLER_REASON };\n\t}\n\n\tconst summary = largeLaunchTaskSummary(input, options?.assistantMessage);\n\tconst siblingLaunches = (options?.assistantMessage?.content ?? []).flatMap((block) => {\n\t\tif (block.type !== \"toolCall\" || block.name !== \"subagent\") return [];\n\t\tconst args =\n\t\t\tblock.arguments && typeof block.arguments === \"object\" && !Array.isArray(block.arguments)\n\t\t\t\t? (block.arguments as Record<string, unknown>)\n\t\t\t\t: undefined;\n\t\treturn args ? getRequestedChildLaunches(args) : [];\n\t});\n\tconst launches = siblingLaunches.length > 0 ? siblingLaunches : getRequestedChildLaunches(input);\n\tconst fullChildrenApproved = launches.some((launch) => launch.permissions === \"full\");\n\tconst launchSummary = launches\n\t\t.map((launch) => `${launch.description}\\npermissions: ${launch.permissions}`)\n\t\t.join(\"\\n\");\n\tlet resp: ApprovalResponse;\n\ttry {\n\t\tresp = await approvalHandler({\n\t\t\ttoolName: \"subagent\",\n\t\t\taction: LARGE_SUBAGENT_LAUNCH_ACTION,\n\t\t\tdetail: `large subagent launch (${count} children)${launchSummary || summary ? `\\n${launchSummary || summary}` : \"\"}`,\n\t\t\tkind: \"large-subagent-launch\",\n\t\t});\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : NO_LARGE_SUBAGENT_LAUNCH_HANDLER_REASON;\n\t\treturn { block: true, reason: message };\n\t}\n\n\tconst rawDecision = typeof resp === \"string\" ? resp : resp.decision;\n\tconst decision: ApprovalDecision = rawDecision === \"approve\" ? \"once\" : rawDecision;\n\tconst feedback = typeof resp === \"string\" ? undefined : resp.feedback?.trim();\n\tif (turnKey) {\n\t\tturnLargeLaunchDecisions.set(turnKey, { decision, ...(feedback ? { feedback } : {}), fullChildrenApproved });\n\t}\n\tif (decision === \"session\") {\n\t\tctx.approvals.add(LARGE_SUBAGENT_LAUNCH_ACTION);\n\t\tif (fullChildrenApproved) ctx.approvals.add(FULL_CHILD_ACTION);\n\t\treturn { fullChildrenApproved };\n\t}\n\tif (decision === \"reject\") {\n\t\treturn {\n\t\t\tblock: true,\n\t\t\treason: feedback ? `${LARGE_SUBAGENT_LAUNCH_REJECT_REASON} ${feedback}` : LARGE_SUBAGENT_LAUNCH_REJECT_REASON,\n\t\t};\n\t}\n\treturn { fullChildrenApproved };\n}\n\nfunction sanitizeDetail(value: unknown): string {\n\tconst text = String(value ?? \"\").trim();\n\treturn text.length > 200 ? `${text.slice(0, 200)}…` : text;\n}\n\n/**\n * Returns a block result when the tool call should be blocked, else undefined.\n * Read-only tools always pass. YOLO and Auto always pass mutating tools. Plan\n * mode hard-blocks mutating tools (no prompt). Manual mode gates every mutating\n * tool; if an approval handler is registered it is asked, otherwise the call is\n * blocked (fail-closed — no silent allow).\n */\nexport async function gateToolCall(\n\ttoolName: string,\n\tinput: Record<string, unknown>,\n\tcwd: string,\n\tsessionId?: string,\n\toptions?: GateOptions,\n): Promise<{ block: true; reason: string } | undefined> {\n\tconst ctx = getContext(sessionId);\n\tconst protectedWriteReason = protectedFileWriteReason(toolName, input, cwd);\n\tif (protectedWriteReason) {\n\t\treturn { block: true, reason: protectedWriteReason };\n\t}\n\tif (READ_ONLY_TOOLS.has(toolName)) return undefined;\n\n\t// Aggregate launch confirmation runs before the mode early-return, including YOLO.\n\t// yolo mode too (only auto mode bypasses it).\n\tlet largeLaunchCoveredManualApproval = false;\n\tif (toolName === \"subagent\") {\n\t\tconst launchResult = await gateLargeSubagentLaunch(input, ctx, options);\n\t\tif (launchResult && \"block\" in launchResult) return launchResult;\n\t\tlargeLaunchCoveredManualApproval = ctx.mode === \"manual\" && launchResult?.fullChildrenApproved === true;\n\t}\n\n\tif (ctx.mode === \"plan\") {\n\t\tconst reason = planModeBlockReason(toolName, input);\n\t\treturn reason ? { block: true, reason } : undefined;\n\t}\n\n\tif (ctx.mode !== \"manual\") return undefined;\n\tif (!requiresManualApproval(toolName, input) || largeLaunchCoveredManualApproval) return undefined;\n\n\tlet action: string;\n\tlet detail: string;\n\n\tif (toolName === \"bash\") {\n\t\taction = \"bash\";\n\t\tdetail = sanitizeDetail(input.command);\n\t} else if (toolName === \"edit\" || toolName === \"write\") {\n\t\tconst path = resolvePath(cwd, input.path);\n\t\tconst outside = path ? isPathOutsideCwd(path, cwd) : false;\n\t\taction = outside ? `${toolName}-outside` : toolName;\n\t\tdetail = path || String(input.path ?? \"\");\n\t} else if (toolName === \"memory_add\") {\n\t\taction = toolName;\n\t\tdetail = sanitizeDetail(input.content);\n\t} else if (toolName === \"memory_remove\") {\n\t\taction = toolName;\n\t\tdetail = sanitizeDetail(input.line);\n\t} else if (toolName === \"cron\") {\n\t\taction = \"cron\";\n\t\tdetail = sanitizeDetail(input.action);\n\t} else if (toolName === \"subagent\") {\n\t\taction = FULL_CHILD_ACTION;\n\t\tconst launches = getRequestedChildLaunches(input).filter((launch) => launch.permissions === \"full\");\n\t\tdetail = sanitizeDetail(\n\t\t\tlaunches.map((launch) => `${launch.description}\\npermissions: ${launch.permissions}`).join(\"\\n\"),\n\t\t);\n\t} else if (toolName === \"code_rewrite\") {\n\t\taction = \"code_rewrite\";\n\t\tdetail = sanitizeDetail(input.path ?? input.pattern);\n\t} else {\n\t\t// All other mutating tools fall back to the tool name with no extra detail.\n\t\taction = toolName;\n\t\tdetail = \"\";\n\t}\n\n\tif (ctx.approvals.has(action)) return undefined;\n\n\tif (!approvalHandler) {\n\t\treturn { block: true, reason: NO_HANDLER_REASON };\n\t}\n\n\tlet resp: ApprovalResponse;\n\ttry {\n\t\tresp = await approvalHandler({ toolName, action, detail });\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : NO_HANDLER_REASON;\n\t\treturn { block: true, reason: message };\n\t}\n\n\tconst decision = typeof resp === \"string\" ? resp : resp.decision;\n\tif (decision === \"session\") {\n\t\tctx.approvals.add(action);\n\t\treturn undefined;\n\t}\n\tif (decision === \"reject\") {\n\t\tconst feedback = typeof resp === \"string\" ? undefined : resp.feedback?.trim();\n\t\treturn { block: true, reason: feedback ? `${REJECT_REASON} ${feedback}` : REJECT_REASON };\n\t}\n\t// \"once\" — allow this call only\n\treturn undefined;\n}\n"]}
1
+ {"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../../src/core/permissions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAQH,6BAA6B;AAC7B,eAAO,MAAM,gBAAgB,6CAA8C,CAAC;AAC5E,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE/D,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,cAAc,GAAG,cAAc,CAG1E;AAED,kEAAkE;AAClE,wBAAgB,gBAAgB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAE5D;AAED;;;GAGG;AACH,wBAAgB,8BAA8B,CAC7C,QAAQ,EAAE,cAAc,GAAG,SAAS,EACpC,WAAW,EAAE,cAAc,GACzB,cAAc,CAGhB;AAED,MAAM,WAAW,eAAe;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB;;2GAEuG;IACvG,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf;;uDAEmD;IACnD,IAAI,CAAC,EAAE,uBAAuB,GAAG,MAAM,CAAC;CACxC;AAED,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,SAAS,GAAG,QAAQ,CAAC;AAC7D;;8CAE8C;AAC9C,MAAM,MAAM,gBAAgB,GACzB,gBAAgB,GAChB;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACxC;IAAE,QAAQ,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAgC9C,eAAO,MAAM,iBAAiB,yEAAyE,CAAC;AACxG,eAAO,MAAM,mCAAmC,4CAA4C,CAAC;AAC7F,eAAO,MAAM,uCAAuC,kEAAkE,CAAC;AAwBvH,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,GAAE,cAAoC,GAAG,IAAI,CAE3G;AAED,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAE/D;AAED,wBAAgB,iBAAiB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,cAAc,CAEpE;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,cAAc,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAEhF;AAED,wBAAgB,gBAAgB,CAAC,WAAW,GAAE,cAAyB,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAMjG;AAED,wBAAgB,uBAAuB,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,eAAe,KAAK,OAAO,CAAC,gBAAgB,CAAC,CAAC,GAAG,SAAS,GAAG,IAAI,CAEnH;AAED,2DAA2D;AAC3D,eAAO,MAAM,kBAAkB,2CAAsC,CAAC;AACtE,eAAO,MAAM,kBAAkB,sEAAiE,CAAC;AACjG,eAAO,MAAM,sBAAsB,oDAAoD,CAAC;AAExF,mFAAmF;AACnF,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,gBAAgB,GAAG,MAAM,CASrE;AAED;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAW1E;AAED,wBAAgB,qBAAqB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAE9D;AAED,2EAA2E;AAC3E,wBAAgB,0BAA0B,IAAI,IAAI,CAIjD;AAED,+DAA+D;AAC/D,eAAO,MAAM,kBAAkB,4JAC2H,CAAC;AAgB3J,eAAO,MAAM,qCAAqC,gGAC4C,CAAC;AAC/F,eAAO,MAAM,qCAAqC,8GAC0D,CAAC;AAC7G,eAAO,MAAM,uCAAuC,4FACsC,CAAC;AA2E3F,MAAM,WAAW,WAAW;IAC3B,yEAAyE;IACzE,4BAA4B,CAAC,EAAE,OAAO,CAAC;IACvC;iEAC6D;IAC7D,gBAAgB,CAAC,EAAE;QAClB,OAAO,CAAC,EAAE,aAAa,CAAC;YAAE,IAAI,CAAC,EAAE,MAAM,CAAC;YAAC,IAAI,CAAC,EAAE,MAAM,CAAC;YAAC,SAAS,CAAC,EAAE,OAAO,CAAA;SAAE,CAAC,CAAC;KAC/E,CAAC;CACF;AAwHD;;;;;;GAMG;AACH,wBAAsB,YAAY,CACjC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,GAAG,EAAE,MAAM,EACX,SAAS,CAAC,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC;IAAE,KAAK,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAAC,CA0FtD","sourcesContent":["/**\n * lunR: permission modes (Manual / YOLO / Plan / Auto).\n *\n * Per-session only — never persisted per session, but the default mode new\n * sessions start with is configurable in /settings (`defaultPermissionMode`,\n * default \"manual\").\n *\n * - manual: every mutating tool call (bash, edit, write) requires approval.\n * - yolo: auto-approve tools; the agent may still ask questions.\n * - plan: read-only; mutating tools are hard-blocked (planModeBlockReason).\n * - auto: fully autonomous; a system-prompt addendum steers the model to\n * self-decide, and rollback is force-enabled for the session.\n *\n * The gate is wired into `agent-session.ts` `_installAgentToolHooks` before\n * the synchronous `_toolCallGates` loop. beforeToolCall is already async, so\n * awaiting the approval dialog is fine.\n *\n * State (mode + session-scoped approvals) is keyed by session id so\n * concurrent gateway chats do not share permission decisions.\n */\n\nimport { dirname, join, resolve } from \"node:path\";\nimport { CONFIG_DIR_NAME, getAgentDir } from \"../config.ts\";\nimport { effectiveLargeSubagentLaunchCountForTurn, LARGE_SUBAGENT_LAUNCH_THRESHOLD } from \"./large-subagent-launch.ts\";\nimport { isUserInstructionsPath } from \"./model-instructions.ts\";\nimport { isCodeRewriteMutating, planModeBlockReason } from \"./plan-mode.ts\";\n\n/** Shift+Tab cycle order. */\nexport const PERMISSION_MODES = [\"manual\", \"yolo\", \"plan\", \"auto\"] as const;\nexport type PermissionMode = (typeof PERMISSION_MODES)[number];\n\nexport function nextPermissionMode(current: PermissionMode): PermissionMode {\n\tconst i = PERMISSION_MODES.indexOf(current);\n\treturn PERMISSION_MODES[(i + 1) % PERMISSION_MODES.length];\n}\n\n/** True when the (default or session) permission mode is plan. */\nexport function isPlanModeActive(sessionId?: string): boolean {\n\treturn getPermissionMode(sessionId) === \"plan\";\n}\n\n/**\n * Destination mode when leaving plan via approve / `/plan off` / `/plan <text>`.\n * Explicit Shift+Tab or `/mode` picks do not use this — they already chose a mode.\n */\nexport function restorePermissionModeAfterPlan(\n\tprevious: PermissionMode | undefined,\n\tdefaultMode: PermissionMode,\n): PermissionMode {\n\tif (previous && previous !== \"plan\") return previous;\n\treturn defaultMode === \"plan\" ? \"yolo\" : defaultMode;\n}\n\nexport interface ApprovalRequest {\n\ttoolName: string;\n\t/** \"bash\" (detail = command), \"edit\"/\"write\" (detail = path),\n\t * \"edit-outside\"/\"write-outside\" when path escapes cwd,\n\t * \"subagent-full\" for full-access children, or \"large-subagent-launch\" for aggregate confirmation. */\n\taction: string;\n\tdetail: string;\n\t/** \"large-subagent-launch\" for aggregate child confirmation, \"plan\" for the\n\t * present_plan plan-approval prompt — the UI renders a dedicated dialog\n\t * for each instead of the generic tool dialog. */\n\tkind?: \"large-subagent-launch\" | \"plan\";\n}\n\nexport type ApprovalDecision = \"once\" | \"session\" | \"reject\";\n/** Handlers may return a bare decision string, a reject carrying user feedback\n * that becomes the block reason the model sees, or an approve carrying optional\n * feedback (plan approval with comments). */\nexport type ApprovalResponse =\n\t| ApprovalDecision\n\t| { decision: \"reject\"; feedback: string }\n\t| { decision: \"approve\"; feedback?: string };\n\n/** Read-only tools that never need approval. */\nconst READ_ONLY_TOOLS = new Set([\n\t\"read\",\n\t\"grep\",\n\t\"find\",\n\t\"ls\",\n\t\"web_search\",\n\t\"web_fetch\",\n\t\"fetch_content\",\n\t\"get_search_content\",\n\t\"sourcegraph\",\n\t\"repo_map\",\n\t\"symbol_outline\",\n\t\"read_block\",\n\t\"code_overview\",\n\t\"ast_search\",\n\t\"lsp_diagnostics\",\n\t\"lsp_hover\",\n\t\"lsp_definition\",\n\t\"lsp_references\",\n\t\"lsp_symbols\",\n\t\"lsp_code_actions\",\n\t\"lsp_completions\",\n\t\"memory_load\",\n]);\n\n/** Tools that mutate state and must be gated in manual mode. */\nconst MUTATING_TOOLS = new Set([\"bash\", \"edit\", \"write\", \"memory_add\", \"memory_remove\", \"cron\"]);\n\nconst REJECT_REASON = \"Rejected by user (permission mode: manual).\";\nexport const NO_HANDLER_REASON = \"Mutating tool blocked in manual mode: no approval channel available.\";\nexport const LARGE_SUBAGENT_LAUNCH_REJECT_REASON = \"Large subagent launch rejected by user.\";\nexport const NO_LARGE_SUBAGENT_LAUNCH_HANDLER_REASON = \"Large subagent launch blocked: no approval channel available.\";\n/** Session-approval keys for child launches. */\nconst LARGE_SUBAGENT_LAUNCH_ACTION = \"large-subagent-launch\";\nconst FULL_CHILD_ACTION = \"subagent-full\";\n\ninterface PermissionContext {\n\tmode: PermissionMode;\n\tapprovals: Set<string>;\n}\n\nconst contexts = new Map<string, PermissionContext>();\nlet defaultContext: PermissionContext = { mode: \"manual\", approvals: new Set() };\nlet approvalHandler: ((req: ApprovalRequest) => Promise<ApprovalResponse>) | undefined;\n/** One aggregate prompt covers every sibling SINGLE `subagent` on the same assistant message. */\nconst turnLargeLaunchDecisions = new WeakMap<\n\tobject,\n\t{ decision: ApprovalDecision; feedback?: string; fullChildrenApproved: boolean }\n>();\n\nfunction getContext(sessionId?: string): PermissionContext {\n\tif (!sessionId) return defaultContext;\n\treturn contexts.get(sessionId) ?? defaultContext;\n}\n\nexport function createPermissionContext(sessionId: string, mode: PermissionMode = defaultContext.mode): void {\n\tcontexts.set(sessionId, { mode, approvals: new Set() });\n}\n\nexport function deletePermissionContext(sessionId: string): void {\n\tcontexts.delete(sessionId);\n}\n\nexport function getPermissionMode(sessionId?: string): PermissionMode {\n\treturn getContext(sessionId).mode;\n}\n\nexport function setPermissionMode(mode: PermissionMode, sessionId?: string): void {\n\tgetContext(sessionId).mode = mode;\n}\n\nexport function resetPermissions(defaultMode: PermissionMode = \"manual\", sessionId?: string): void {\n\tif (sessionId) {\n\t\tcontexts.set(sessionId, { mode: defaultMode, approvals: new Set() });\n\t} else {\n\t\tdefaultContext = { mode: defaultMode, approvals: new Set() };\n\t}\n}\n\nexport function registerApprovalHandler(fn: ((req: ApprovalRequest) => Promise<ApprovalResponse>) | undefined): void {\n\tapprovalHandler = fn;\n}\n\n/** Model-facing result texts for the present_plan tool. */\nexport const PLAN_APPROVED_TEXT = \"Plan approved — implement it now.\";\nexport const PLAN_DECLINED_TEXT = \"Plan declined — revise the plan and call present_plan again.\";\nexport const PLAN_PASS_THROUGH_TEXT = \"Plan presented. The user will review and reply.\";\n\n/** lunr: map an approval response to the model-facing present_plan result text. */\nexport function planApprovalResultText(resp: ApprovalResponse): string {\n\tconst decision = typeof resp === \"string\" ? resp : resp.decision;\n\tconst feedback = typeof resp === \"string\" ? undefined : resp.feedback?.trim();\n\tif (decision === \"reject\") {\n\t\treturn feedback\n\t\t\t? `Plan declined: ${feedback} — revise the plan and call present_plan again.`\n\t\t\t: PLAN_DECLINED_TEXT;\n\t}\n\treturn feedback ? `Plan approved with feedback: ${feedback} — implement it now.` : PLAN_APPROVED_TEXT;\n}\n\n/**\n * lunr: present_plan approval request. Unlike mutating-tool and aggregate launch gates\n * this fails OPEN when no approval handler is registered (or none is reachable,\n * e.g. a gateway turn without a chat context): headless sessions have no one to\n * show the dialog to, so the plan is presented and the user replies in chat\n * instead of deadlocking the turn. Everything else keeps fail-closed.\n */\nexport async function requestPlanApproval(summary: string): Promise<string> {\n\tif (!approvalHandler) return PLAN_PASS_THROUGH_TEXT;\n\tlet resp: ApprovalResponse;\n\ttry {\n\t\tresp = await approvalHandler({ toolName: \"present_plan\", action: \"plan\", detail: summary, kind: \"plan\" });\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : \"approval request failed\";\n\t\tif (message === NO_HANDLER_REASON) return PLAN_PASS_THROUGH_TEXT;\n\t\treturn `Plan declined: ${message} — revise the plan and call present_plan again.`;\n\t}\n\treturn planApprovalResultText(resp);\n}\n\nexport function clearSessionApprovals(sessionId?: string): void {\n\tgetContext(sessionId).approvals.clear();\n}\n\n/** Test seam: remove every per-session context and restore the default. */\nexport function resetAllPermissionContexts(): void {\n\tcontexts.clear();\n\tdefaultContext = { mode: \"manual\", approvals: new Set() };\n\tapprovalHandler = undefined;\n}\n\n/** Appended to the system prompt while auto mode is active. */\nexport const AUTO_MODE_ADDENDUM =\n\t\"You are running fully autonomously. Do not ask the user questions or wait for confirmation; make reasonable decisions and complete the task end-to-end.\";\n\nfunction isPathOutsideCwd(absPath: string, cwd: string): boolean {\n\tconst norm = (p: string) => p.replace(/\\\\/g, \"/\").replace(/\\/$/, \"\");\n\tconst np = norm(absPath);\n\tconst nc = norm(cwd);\n\tif (np === nc) return false;\n\treturn !np.startsWith(`${nc}/`);\n}\n\nfunction resolvePath(cwd: string, p: unknown): string {\n\tif (typeof p !== \"string\") return \"\";\n\tif (!p) return \"\";\n\treturn resolve(cwd, p);\n}\n\nexport const GLOBAL_AGENTS_FILE_WRITE_BLOCK_REASON =\n\t\"The agents instruction tree is user-managed. The agent cannot change ~/.lunr/agent/agents/.\";\nexport const MEMORY_FILE_DIRECT_WRITE_BLOCK_REASON =\n\t\"Memory is model-managed through the memory tools. Do not directly change ~/.lunr/simple-memory/memory.md.\";\nexport const SETTINGS_FILE_DIRECT_WRITE_BLOCK_REASON =\n\t\"lunR settings are user-managed through /settings. Do not directly change settings.json.\";\n\nfunction protectedFileWriteReason(toolName: string, input: Record<string, unknown>, cwd: string): string | undefined {\n\tif (toolName !== \"edit\" && toolName !== \"write\" && toolName !== \"code_rewrite\") return undefined;\n\tconst target = resolvePath(cwd, input.path);\n\tif (!target) return undefined;\n\tconst normalize = (path: string) => {\n\t\tconst normalized = resolve(path).replace(/\\\\/g, \"/\").replace(/\\/$/, \"\");\n\t\treturn process.platform === \"win32\" ? normalized.toLowerCase() : normalized;\n\t};\n\tif (isUserInstructionsPath(target, getAgentDir())) {\n\t\treturn GLOBAL_AGENTS_FILE_WRITE_BLOCK_REASON;\n\t}\n\tif (normalize(target) === normalize(join(dirname(getAgentDir()), \"simple-memory\", \"memory.md\"))) {\n\t\treturn MEMORY_FILE_DIRECT_WRITE_BLOCK_REASON;\n\t}\n\tconst globalSettings = normalize(join(getAgentDir(), \"settings.json\"));\n\tconst projectSettings = normalize(join(cwd, CONFIG_DIR_NAME, \"settings.json\"));\n\tconst normalizedTarget = normalize(target);\n\tif (normalizedTarget === normalize(join(getAgentDir(), \"install-features.json\"))) {\n\t\treturn \"Optional features are user-managed through lunr features; Browser is managed in /settings. Do not change install-features.json directly.\";\n\t}\n\tif (normalizedTarget === globalSettings || normalizedTarget === projectSettings) {\n\t\treturn SETTINGS_FILE_DIRECT_WRITE_BLOCK_REASON;\n\t}\n\treturn undefined;\n}\n\nfunction isMutatingTool(toolName: string): boolean {\n\treturn MUTATING_TOOLS.has(toolName);\n}\n\ninterface RequestedChildLaunch {\n\tdescription: string;\n\tpermissions: \"full\" | \"read-only\";\n}\n\nfunction collectRequestedChildLaunches(value: unknown, launches: RequestedChildLaunch[]): void {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) return;\n\tconst input = value as Record<string, unknown>;\n\tif (typeof input.task === \"string\" && input.task.trim()) {\n\t\tlaunches.push({\n\t\t\tdescription:\n\t\t\t\ttypeof input.description === \"string\" && input.description.trim()\n\t\t\t\t\t? input.description.trim()\n\t\t\t\t\t: input.task.trim(),\n\t\t\tpermissions: input.permissions === \"read-only\" ? \"read-only\" : \"full\",\n\t\t});\n\t\treturn;\n\t}\n\tfor (const key of [\"tasks\", \"chain\", \"parallel\"] as const) {\n\t\tconst children = input[key];\n\t\tif (Array.isArray(children)) {\n\t\t\tfor (const child of children) collectRequestedChildLaunches(child, launches);\n\t\t} else if (key === \"parallel\") {\n\t\t\tcollectRequestedChildLaunches(children, launches);\n\t\t}\n\t}\n}\n\nfunction getRequestedChildLaunches(input: Record<string, unknown>): RequestedChildLaunch[] {\n\tconst launches: RequestedChildLaunch[] = [];\n\tcollectRequestedChildLaunches(input, launches);\n\treturn launches;\n}\n\nfunction requiresManualApproval(toolName: string, input: Record<string, unknown>): boolean {\n\tif (toolName === \"browser\") return input.action === \"act\";\n\tif (isMutatingTool(toolName)) return true;\n\tif (toolName === \"subagent\") {\n\t\treturn getRequestedChildLaunches(input).some((launch) => launch.permissions === \"full\");\n\t}\n\treturn toolName === \"code_rewrite\" && isCodeRewriteMutating(input);\n}\n\nexport interface GateOptions {\n\t/** Global preference for aggregate confirmation. Defaults to enabled. */\n\tconfirmLargeSubagentLaunches?: boolean;\n\t/** Assistant message that issued this tool call. Same-turn sibling SINGLE\n\t * `subagent` calls count toward the aggregate threshold. */\n\tassistantMessage?: {\n\t\tcontent?: ReadonlyArray<{ type?: string; name?: string; arguments?: unknown }>;\n\t};\n}\n\nfunction firstTaskText(value: unknown): string {\n\tif (typeof value === \"string\" && value.trim()) return sanitizeDetail(value);\n\treturn \"\";\n}\n\n/** First task text of a parallel fan-out or sibling SINGLE, used as the dialog summary. */\nfunction largeLaunchTaskSummary(\n\tinput: Record<string, unknown>,\n\tassistantMessage?: GateOptions[\"assistantMessage\"],\n): string {\n\tif (Array.isArray(input.tasks)) {\n\t\tfor (const task of input.tasks) {\n\t\t\tconst text = task && typeof task === \"object\" ? firstTaskText((task as { task?: unknown }).task) : \"\";\n\t\t\tif (text) return text;\n\t\t}\n\t}\n\tconst own = firstTaskText(input.task);\n\tif (own) return own;\n\tfor (const block of assistantMessage?.content ?? []) {\n\t\tif (block.type !== \"toolCall\" || block.name !== \"subagent\") continue;\n\t\tconst args =\n\t\t\tblock.arguments && typeof block.arguments === \"object\" && !Array.isArray(block.arguments)\n\t\t\t\t? (block.arguments as Record<string, unknown>)\n\t\t\t\t: undefined;\n\t\tconst text = firstTaskText(args?.task);\n\t\tif (text) return text;\n\t}\n\treturn \"\";\n}\n\n/**\n * Aggregate launch gate. A launch above LARGE_SUBAGENT_LAUNCH_THRESHOLD\n * parallel subagents in one `tasks`/`chain.parallel` call, or that many same-turn\n * SINGLE `subagent` calls) requires user approval in manual AND yolo modes; auto\n * mode runs it unconditionally.\n * Fail-closed without an approval handler, same as the mutating-tool gate.\n */\nasync function gateLargeSubagentLaunch(\n\tinput: Record<string, unknown>,\n\tctx: PermissionContext,\n\toptions?: GateOptions,\n): Promise<{ block: true; reason: string } | { fullChildrenApproved: boolean } | undefined> {\n\tif (ctx.mode === \"auto\") return undefined;\n\tif (options?.confirmLargeSubagentLaunches === false) return undefined;\n\tconst count = effectiveLargeSubagentLaunchCountForTurn(input, options?.assistantMessage);\n\tif (count <= LARGE_SUBAGENT_LAUNCH_THRESHOLD) return undefined;\n\tif (ctx.approvals.has(LARGE_SUBAGENT_LAUNCH_ACTION)) return { fullChildrenApproved: false };\n\n\tconst turnKey = options?.assistantMessage;\n\tconst cached = turnKey ? turnLargeLaunchDecisions.get(turnKey) : undefined;\n\tif (cached) {\n\t\tif (cached.decision === \"reject\") {\n\t\t\treturn {\n\t\t\t\tblock: true,\n\t\t\t\treason: cached.feedback\n\t\t\t\t\t? `${LARGE_SUBAGENT_LAUNCH_REJECT_REASON} ${cached.feedback}`\n\t\t\t\t\t: LARGE_SUBAGENT_LAUNCH_REJECT_REASON,\n\t\t\t};\n\t\t}\n\t\treturn { fullChildrenApproved: cached.fullChildrenApproved };\n\t}\n\n\tif (!approvalHandler) {\n\t\treturn { block: true, reason: NO_LARGE_SUBAGENT_LAUNCH_HANDLER_REASON };\n\t}\n\n\tconst summary = largeLaunchTaskSummary(input, options?.assistantMessage);\n\tconst siblingLaunches = (options?.assistantMessage?.content ?? []).flatMap((block) => {\n\t\tif (block.type !== \"toolCall\" || block.name !== \"subagent\") return [];\n\t\tconst args =\n\t\t\tblock.arguments && typeof block.arguments === \"object\" && !Array.isArray(block.arguments)\n\t\t\t\t? (block.arguments as Record<string, unknown>)\n\t\t\t\t: undefined;\n\t\treturn args ? getRequestedChildLaunches(args) : [];\n\t});\n\tconst launches = siblingLaunches.length > 0 ? siblingLaunches : getRequestedChildLaunches(input);\n\tconst fullChildrenApproved = launches.some((launch) => launch.permissions === \"full\");\n\tconst launchSummary = launches\n\t\t.map((launch) => `${launch.description}\\npermissions: ${launch.permissions}`)\n\t\t.join(\"\\n\");\n\tlet resp: ApprovalResponse;\n\ttry {\n\t\tresp = await approvalHandler({\n\t\t\ttoolName: \"subagent\",\n\t\t\taction: LARGE_SUBAGENT_LAUNCH_ACTION,\n\t\t\tdetail: `large subagent launch (${count} children)${launchSummary || summary ? `\\n${launchSummary || summary}` : \"\"}`,\n\t\t\tkind: \"large-subagent-launch\",\n\t\t});\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : NO_LARGE_SUBAGENT_LAUNCH_HANDLER_REASON;\n\t\treturn { block: true, reason: message };\n\t}\n\n\tconst rawDecision = typeof resp === \"string\" ? resp : resp.decision;\n\tconst decision: ApprovalDecision = rawDecision === \"approve\" ? \"once\" : rawDecision;\n\tconst feedback = typeof resp === \"string\" ? undefined : resp.feedback?.trim();\n\tif (turnKey) {\n\t\tturnLargeLaunchDecisions.set(turnKey, { decision, ...(feedback ? { feedback } : {}), fullChildrenApproved });\n\t}\n\tif (decision === \"session\") {\n\t\tctx.approvals.add(LARGE_SUBAGENT_LAUNCH_ACTION);\n\t\tif (fullChildrenApproved) ctx.approvals.add(FULL_CHILD_ACTION);\n\t\treturn { fullChildrenApproved };\n\t}\n\tif (decision === \"reject\") {\n\t\treturn {\n\t\t\tblock: true,\n\t\t\treason: feedback ? `${LARGE_SUBAGENT_LAUNCH_REJECT_REASON} ${feedback}` : LARGE_SUBAGENT_LAUNCH_REJECT_REASON,\n\t\t};\n\t}\n\treturn { fullChildrenApproved };\n}\n\nfunction sanitizeDetail(value: unknown): string {\n\tconst text = String(value ?? \"\").trim();\n\treturn text.length > 200 ? `${text.slice(0, 200)}…` : text;\n}\n\n/**\n * Returns a block result when the tool call should be blocked, else undefined.\n * Read-only tools always pass. YOLO and Auto always pass mutating tools. Plan\n * mode hard-blocks mutating tools (no prompt). Manual mode gates every mutating\n * tool; if an approval handler is registered it is asked, otherwise the call is\n * blocked (fail-closed — no silent allow).\n */\nexport async function gateToolCall(\n\ttoolName: string,\n\tinput: Record<string, unknown>,\n\tcwd: string,\n\tsessionId?: string,\n\toptions?: GateOptions,\n): Promise<{ block: true; reason: string } | undefined> {\n\tconst ctx = getContext(sessionId);\n\tconst protectedWriteReason = protectedFileWriteReason(toolName, input, cwd);\n\tif (protectedWriteReason) {\n\t\treturn { block: true, reason: protectedWriteReason };\n\t}\n\tif (READ_ONLY_TOOLS.has(toolName)) return undefined;\n\n\t// Aggregate launch confirmation runs before the mode early-return, including YOLO.\n\t// yolo mode too (only auto mode bypasses it).\n\tlet largeLaunchCoveredManualApproval = false;\n\tif (toolName === \"subagent\") {\n\t\tconst launchResult = await gateLargeSubagentLaunch(input, ctx, options);\n\t\tif (launchResult && \"block\" in launchResult) return launchResult;\n\t\tlargeLaunchCoveredManualApproval = ctx.mode === \"manual\" && launchResult?.fullChildrenApproved === true;\n\t}\n\n\tif (ctx.mode === \"plan\") {\n\t\tconst reason = planModeBlockReason(toolName, input);\n\t\treturn reason ? { block: true, reason } : undefined;\n\t}\n\n\tif (ctx.mode !== \"manual\") return undefined;\n\tif (!requiresManualApproval(toolName, input) || largeLaunchCoveredManualApproval) return undefined;\n\n\tlet action: string;\n\tlet detail: string;\n\n\tif (toolName === \"bash\") {\n\t\taction = \"bash\";\n\t\tdetail = sanitizeDetail(input.command);\n\t} else if (toolName === \"edit\" || toolName === \"write\") {\n\t\tconst path = resolvePath(cwd, input.path);\n\t\tconst outside = path ? isPathOutsideCwd(path, cwd) : false;\n\t\taction = outside ? `${toolName}-outside` : toolName;\n\t\tdetail = path || String(input.path ?? \"\");\n\t} else if (toolName === \"memory_add\") {\n\t\taction = toolName;\n\t\tdetail = sanitizeDetail(input.content);\n\t} else if (toolName === \"memory_remove\") {\n\t\taction = toolName;\n\t\tdetail = sanitizeDetail(input.line);\n\t} else if (toolName === \"cron\") {\n\t\taction = \"cron\";\n\t\tdetail = sanitizeDetail(input.action);\n\t} else if (toolName === \"subagent\") {\n\t\taction = FULL_CHILD_ACTION;\n\t\tconst launches = getRequestedChildLaunches(input).filter((launch) => launch.permissions === \"full\");\n\t\tdetail = sanitizeDetail(\n\t\t\tlaunches.map((launch) => `${launch.description}\\npermissions: ${launch.permissions}`).join(\"\\n\"),\n\t\t);\n\t} else if (toolName === \"browser\") {\n\t\taction = \"browser\";\n\t\tdetail = sanitizeDetail(\n\t\t\t`${input.interaction ?? \"\"} ${input.role ?? \"\"} ${input.name ?? input.label ?? \"\"}. Website effects cannot be undone.`,\n\t\t);\n\t} else if (toolName === \"code_rewrite\") {\n\t\taction = \"code_rewrite\";\n\t\tdetail = sanitizeDetail(input.path ?? input.pattern);\n\t} else {\n\t\t// All other mutating tools fall back to the tool name with no extra detail.\n\t\taction = toolName;\n\t\tdetail = \"\";\n\t}\n\n\tif (ctx.approvals.has(action)) return undefined;\n\n\tif (!approvalHandler) {\n\t\treturn { block: true, reason: NO_HANDLER_REASON };\n\t}\n\n\tlet resp: ApprovalResponse;\n\ttry {\n\t\tresp = await approvalHandler({ toolName, action, detail });\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : NO_HANDLER_REASON;\n\t\treturn { block: true, reason: message };\n\t}\n\n\tconst decision = typeof resp === \"string\" ? resp : resp.decision;\n\tif (decision === \"session\") {\n\t\tctx.approvals.add(action);\n\t\treturn undefined;\n\t}\n\tif (decision === \"reject\") {\n\t\tconst feedback = typeof resp === \"string\" ? undefined : resp.feedback?.trim();\n\t\treturn { block: true, reason: feedback ? `${REJECT_REASON} ${feedback}` : REJECT_REASON };\n\t}\n\t// \"once\" — allow this call only\n\treturn undefined;\n}\n"]}
@@ -194,6 +194,9 @@ function protectedFileWriteReason(toolName, input, cwd) {
194
194
  const globalSettings = normalize(join(getAgentDir(), "settings.json"));
195
195
  const projectSettings = normalize(join(cwd, CONFIG_DIR_NAME, "settings.json"));
196
196
  const normalizedTarget = normalize(target);
197
+ if (normalizedTarget === normalize(join(getAgentDir(), "install-features.json"))) {
198
+ return "Optional features are user-managed through lunr features; Browser is managed in /settings. Do not change install-features.json directly.";
199
+ }
197
200
  if (normalizedTarget === globalSettings || normalizedTarget === projectSettings) {
198
201
  return SETTINGS_FILE_DIRECT_WRITE_BLOCK_REASON;
199
202
  }
@@ -232,6 +235,8 @@ function getRequestedChildLaunches(input) {
232
235
  return launches;
233
236
  }
234
237
  function requiresManualApproval(toolName, input) {
238
+ if (toolName === "browser")
239
+ return input.action === "act";
235
240
  if (isMutatingTool(toolName))
236
241
  return true;
237
242
  if (toolName === "subagent") {
@@ -413,6 +418,10 @@ export async function gateToolCall(toolName, input, cwd, sessionId, options) {
413
418
  const launches = getRequestedChildLaunches(input).filter((launch) => launch.permissions === "full");
414
419
  detail = sanitizeDetail(launches.map((launch) => `${launch.description}\npermissions: ${launch.permissions}`).join("\n"));
415
420
  }
421
+ else if (toolName === "browser") {
422
+ action = "browser";
423
+ detail = sanitizeDetail(`${input.interaction ?? ""} ${input.role ?? ""} ${input.name ?? input.label ?? ""}. Website effects cannot be undone.`);
424
+ }
416
425
  else if (toolName === "code_rewrite") {
417
426
  action = "code_rewrite";
418
427
  detail = sanitizeDetail(input.path ?? input.pattern);