@ashx-j/lunr 0.2.13 → 0.2.15

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 (335) hide show
  1. package/CHANGELOG.md +27 -1
  2. package/README.md +10 -7
  3. package/dist/builtin-extensions/ashxj-tui.d.ts +16 -1
  4. package/dist/builtin-extensions/ashxj-tui.d.ts.map +1 -1
  5. package/dist/builtin-extensions/ashxj-tui.js +48 -24
  6. package/dist/builtin-extensions/ashxj-tui.js.map +1 -1
  7. package/dist/builtin-extensions/index.d.ts.map +1 -1
  8. package/dist/builtin-extensions/index.js +2 -0
  9. package/dist/builtin-extensions/index.js.map +1 -1
  10. package/dist/builtin-extensions/lunr-settings-tools.d.ts +4 -0
  11. package/dist/builtin-extensions/lunr-settings-tools.d.ts.map +1 -0
  12. package/dist/builtin-extensions/lunr-settings-tools.js +120 -0
  13. package/dist/builtin-extensions/lunr-settings-tools.js.map +1 -0
  14. package/dist/builtin-extensions/pi-prompt-template-model/subagent-runtime.d.ts +2 -2
  15. package/dist/builtin-extensions/pi-prompt-template-model/subagent-runtime.d.ts.map +1 -1
  16. package/dist/builtin-extensions/pi-prompt-template-model/subagent-runtime.js.map +1 -1
  17. package/dist/builtin-extensions/pi-prompt-template-model/subagent-step.d.ts.map +1 -1
  18. package/dist/builtin-extensions/pi-prompt-template-model/subagent-step.js +3 -3
  19. package/dist/builtin-extensions/pi-prompt-template-model/subagent-step.js.map +1 -1
  20. package/dist/builtin-extensions/pi-subagents/src/api/delegation.d.ts +2 -2
  21. package/dist/builtin-extensions/pi-subagents/src/api/delegation.d.ts.map +1 -1
  22. package/dist/builtin-extensions/pi-subagents/src/api/delegation.js +1 -1
  23. package/dist/builtin-extensions/pi-subagents/src/api/delegation.js.map +1 -1
  24. package/dist/builtin-extensions/pi-subagents/src/extension/index.d.ts +2 -0
  25. package/dist/builtin-extensions/pi-subagents/src/extension/index.d.ts.map +1 -1
  26. package/dist/builtin-extensions/pi-subagents/src/extension/index.js +29 -23
  27. package/dist/builtin-extensions/pi-subagents/src/extension/index.js.map +1 -1
  28. package/dist/builtin-extensions/pi-subagents/src/extension/schemas.d.ts +5 -11
  29. package/dist/builtin-extensions/pi-subagents/src/extension/schemas.d.ts.map +1 -1
  30. package/dist/builtin-extensions/pi-subagents/src/extension/schemas.js +12 -15
  31. package/dist/builtin-extensions/pi-subagents/src/extension/schemas.js.map +1 -1
  32. package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.d.ts +3 -3
  33. package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.d.ts.map +1 -1
  34. package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.js +14 -27
  35. package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.js.map +1 -1
  36. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-execution.d.ts.map +1 -1
  37. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-execution.js +9 -4
  38. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-execution.js.map +1 -1
  39. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-job-tracker.d.ts.map +1 -1
  40. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-job-tracker.js +2 -1
  41. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-job-tracker.js.map +1 -1
  42. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-resume.d.ts.map +1 -1
  43. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-resume.js +16 -3
  44. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-resume.js.map +1 -1
  45. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-status.d.ts +1 -0
  46. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-status.d.ts.map +1 -1
  47. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-status.js +7 -4
  48. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-status.js.map +1 -1
  49. package/dist/builtin-extensions/pi-subagents/src/runs/background/chain-append.d.ts.map +1 -1
  50. package/dist/builtin-extensions/pi-subagents/src/runs/background/chain-append.js +1 -0
  51. package/dist/builtin-extensions/pi-subagents/src/runs/background/chain-append.js.map +1 -1
  52. package/dist/builtin-extensions/pi-subagents/src/runs/background/chain-root-attachment.d.ts.map +1 -1
  53. package/dist/builtin-extensions/pi-subagents/src/runs/background/chain-root-attachment.js +3 -0
  54. package/dist/builtin-extensions/pi-subagents/src/runs/background/chain-root-attachment.js.map +1 -1
  55. package/dist/builtin-extensions/pi-subagents/src/runs/background/fleet-view.d.ts.map +1 -1
  56. package/dist/builtin-extensions/pi-subagents/src/runs/background/fleet-view.js +3 -3
  57. package/dist/builtin-extensions/pi-subagents/src/runs/background/fleet-view.js.map +1 -1
  58. package/dist/builtin-extensions/pi-subagents/src/runs/background/run-status.d.ts.map +1 -1
  59. package/dist/builtin-extensions/pi-subagents/src/runs/background/run-status.js +2 -2
  60. package/dist/builtin-extensions/pi-subagents/src/runs/background/run-status.js.map +1 -1
  61. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-runner.d.ts.map +1 -1
  62. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-runner.js +3 -0
  63. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-runner.js.map +1 -1
  64. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-clarify.d.ts.map +1 -1
  65. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-clarify.js +3 -35
  66. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-clarify.js.map +1 -1
  67. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-execution.d.ts.map +1 -1
  68. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-execution.js +7 -8
  69. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-execution.js.map +1 -1
  70. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/execution.d.ts.map +1 -1
  71. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/execution.js +2 -0
  72. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/execution.js.map +1 -1
  73. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.d.ts +1 -0
  74. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.d.ts.map +1 -1
  75. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.js +20 -21
  76. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.js.map +1 -1
  77. package/dist/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.d.ts +12 -1
  78. package/dist/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.d.ts.map +1 -1
  79. package/dist/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.js +42 -17
  80. package/dist/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.js.map +1 -1
  81. package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.d.ts +2 -0
  82. package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.d.ts.map +1 -1
  83. package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.js.map +1 -1
  84. package/dist/builtin-extensions/pi-subagents/src/shared/child-spec.d.ts +2 -1
  85. package/dist/builtin-extensions/pi-subagents/src/shared/child-spec.d.ts.map +1 -1
  86. package/dist/builtin-extensions/pi-subagents/src/shared/child-spec.js +23 -1
  87. package/dist/builtin-extensions/pi-subagents/src/shared/child-spec.js.map +1 -1
  88. package/dist/builtin-extensions/pi-subagents/src/shared/formatters.d.ts +3 -1
  89. package/dist/builtin-extensions/pi-subagents/src/shared/formatters.d.ts.map +1 -1
  90. package/dist/builtin-extensions/pi-subagents/src/shared/formatters.js +15 -4
  91. package/dist/builtin-extensions/pi-subagents/src/shared/formatters.js.map +1 -1
  92. package/dist/builtin-extensions/pi-subagents/src/shared/types.d.ts +14 -3
  93. package/dist/builtin-extensions/pi-subagents/src/shared/types.d.ts.map +1 -1
  94. package/dist/builtin-extensions/pi-subagents/src/shared/types.js +1 -1
  95. package/dist/builtin-extensions/pi-subagents/src/shared/types.js.map +1 -1
  96. package/dist/builtin-extensions/pi-subagents/src/slash/delegation-adapters.d.ts +3 -3
  97. package/dist/builtin-extensions/pi-subagents/src/slash/delegation-adapters.d.ts.map +1 -1
  98. package/dist/builtin-extensions/pi-subagents/src/slash/delegation-adapters.js +7 -6
  99. package/dist/builtin-extensions/pi-subagents/src/slash/delegation-adapters.js.map +1 -1
  100. package/dist/builtin-extensions/pi-subagents/src/slash/delegation-request.d.ts.map +1 -1
  101. package/dist/builtin-extensions/pi-subagents/src/slash/delegation-request.js +3 -3
  102. package/dist/builtin-extensions/pi-subagents/src/slash/delegation-request.js.map +1 -1
  103. package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.d.ts +1 -1
  104. package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.d.ts.map +1 -1
  105. package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.js +6 -4
  106. package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.js.map +1 -1
  107. package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.d.ts +1 -1
  108. package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.d.ts.map +1 -1
  109. package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.js +15 -10
  110. package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.js.map +1 -1
  111. package/dist/builtin-extensions/pi-subagents/src/tui/fleet.d.ts.map +1 -1
  112. package/dist/builtin-extensions/pi-subagents/src/tui/fleet.js +5 -4
  113. package/dist/builtin-extensions/pi-subagents/src/tui/fleet.js.map +1 -1
  114. package/dist/builtin-extensions/pi-subagents/src/tui/render.d.ts +2 -2
  115. package/dist/builtin-extensions/pi-subagents/src/tui/render.d.ts.map +1 -1
  116. package/dist/builtin-extensions/pi-subagents/src/tui/render.js +86 -52
  117. package/dist/builtin-extensions/pi-subagents/src/tui/render.js.map +1 -1
  118. package/dist/catalog/models.json +1 -1
  119. package/dist/catalog/providers/amazon-bedrock.json +1 -1
  120. package/dist/catalog/providers/anthropic.json +1 -1
  121. package/dist/catalog/providers/azure-openai-responses.json +1 -1
  122. package/dist/catalog/providers/cloudflare-ai-gateway.json +1 -1
  123. package/dist/catalog/providers/fireworks.json +1 -1
  124. package/dist/catalog/providers/github-copilot.json +1 -1
  125. package/dist/catalog/providers/google-vertex.json +1 -1
  126. package/dist/catalog/providers/google.json +1 -1
  127. package/dist/catalog/providers/groq.json +1 -1
  128. package/dist/catalog/providers/huggingface.json +1 -1
  129. package/dist/catalog/providers/nvidia.json +1 -1
  130. package/dist/catalog/providers/openai-codex.json +1 -1
  131. package/dist/catalog/providers/openai.json +1 -1
  132. package/dist/catalog/providers/opencode-go.json +1 -1
  133. package/dist/catalog/providers/opencode.json +1 -1
  134. package/dist/catalog/providers/openrouter.json +1 -1
  135. package/dist/catalog/providers/vercel-ai-gateway.json +1 -1
  136. package/dist/catalog/publication.json +131 -3
  137. package/dist/cli/list-models.d.ts.map +1 -1
  138. package/dist/cli/list-models.js +1 -0
  139. package/dist/cli/list-models.js.map +1 -1
  140. package/dist/cli.d.ts.map +1 -1
  141. package/dist/cli.js +52 -27
  142. package/dist/cli.js.map +1 -1
  143. package/dist/core/agent-session-runtime.d.ts +5 -1
  144. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  145. package/dist/core/agent-session-runtime.js +7 -2
  146. package/dist/core/agent-session-runtime.js.map +1 -1
  147. package/dist/core/agent-session.d.ts +2 -0
  148. package/dist/core/agent-session.d.ts.map +1 -1
  149. package/dist/core/agent-session.js +18 -6
  150. package/dist/core/agent-session.js.map +1 -1
  151. package/dist/core/catalog-cache-scope.d.ts +3 -0
  152. package/dist/core/catalog-cache-scope.d.ts.map +1 -0
  153. package/dist/core/catalog-cache-scope.js +12 -0
  154. package/dist/core/catalog-cache-scope.js.map +1 -0
  155. package/dist/core/catalog-merge.d.ts +2 -0
  156. package/dist/core/catalog-merge.d.ts.map +1 -1
  157. package/dist/core/catalog-merge.js +29 -2
  158. package/dist/core/catalog-merge.js.map +1 -1
  159. package/dist/core/catalog-refresh-polling.d.ts +8 -0
  160. package/dist/core/catalog-refresh-polling.d.ts.map +1 -0
  161. package/dist/core/catalog-refresh-polling.js +30 -0
  162. package/dist/core/catalog-refresh-polling.js.map +1 -0
  163. package/dist/core/codex-catalog.d.ts +3 -0
  164. package/dist/core/codex-catalog.d.ts.map +1 -0
  165. package/dist/core/codex-catalog.js +15 -0
  166. package/dist/core/codex-catalog.js.map +1 -0
  167. package/dist/core/context-breakdown.d.ts +2 -0
  168. package/dist/core/context-breakdown.d.ts.map +1 -1
  169. package/dist/core/context-breakdown.js +6 -2
  170. package/dist/core/context-breakdown.js.map +1 -1
  171. package/dist/core/customize.d.ts +2 -4
  172. package/dist/core/customize.d.ts.map +1 -1
  173. package/dist/core/customize.js +2 -8
  174. package/dist/core/customize.js.map +1 -1
  175. package/dist/core/footer-data-provider.d.ts +3 -4
  176. package/dist/core/footer-data-provider.d.ts.map +1 -1
  177. package/dist/core/footer-data-provider.js +54 -82
  178. package/dist/core/footer-data-provider.js.map +1 -1
  179. package/dist/core/injected-prompt.d.ts +3 -3
  180. package/dist/core/injected-prompt.d.ts.map +1 -1
  181. package/dist/core/injected-prompt.js +2 -7
  182. package/dist/core/injected-prompt.js.map +1 -1
  183. package/dist/core/large-subagent-launch.d.ts +13 -0
  184. package/dist/core/large-subagent-launch.d.ts.map +1 -0
  185. package/dist/core/large-subagent-launch.js +54 -0
  186. package/dist/core/large-subagent-launch.js.map +1 -0
  187. package/dist/core/live-catalog.d.ts +5 -2
  188. package/dist/core/live-catalog.d.ts.map +1 -1
  189. package/dist/core/live-catalog.js +108 -27
  190. package/dist/core/live-catalog.js.map +1 -1
  191. package/dist/core/model-instructions.d.ts +24 -0
  192. package/dist/core/model-instructions.d.ts.map +1 -0
  193. package/dist/core/model-instructions.js +123 -0
  194. package/dist/core/model-instructions.js.map +1 -0
  195. package/dist/core/model-runtime.d.ts +8 -0
  196. package/dist/core/model-runtime.d.ts.map +1 -1
  197. package/dist/core/model-runtime.js +64 -12
  198. package/dist/core/model-runtime.js.map +1 -1
  199. package/dist/core/official-catalog.d.ts +4 -0
  200. package/dist/core/official-catalog.d.ts.map +1 -1
  201. package/dist/core/official-catalog.js +86 -21
  202. package/dist/core/official-catalog.js.map +1 -1
  203. package/dist/core/permissions.d.ts +10 -11
  204. package/dist/core/permissions.d.ts.map +1 -1
  205. package/dist/core/permissions.js +107 -40
  206. package/dist/core/permissions.js.map +1 -1
  207. package/dist/core/plan-mode.d.ts.map +1 -1
  208. package/dist/core/plan-mode.js +10 -1
  209. package/dist/core/plan-mode.js.map +1 -1
  210. package/dist/core/resource-loader.d.ts +3 -0
  211. package/dist/core/resource-loader.d.ts.map +1 -1
  212. package/dist/core/resource-loader.js +13 -4
  213. package/dist/core/resource-loader.js.map +1 -1
  214. package/dist/core/runtime-bridges.d.ts +4 -0
  215. package/dist/core/runtime-bridges.d.ts.map +1 -0
  216. package/dist/core/runtime-bridges.js +16 -0
  217. package/dist/core/runtime-bridges.js.map +1 -0
  218. package/dist/core/sdk.d.ts.map +1 -1
  219. package/dist/core/sdk.js +1 -0
  220. package/dist/core/sdk.js.map +1 -1
  221. package/dist/core/settings-manager.d.ts +13 -6
  222. package/dist/core/settings-manager.d.ts.map +1 -1
  223. package/dist/core/settings-manager.js +32 -17
  224. package/dist/core/settings-manager.js.map +1 -1
  225. package/dist/core/settings-tools-bridge.d.ts +35 -0
  226. package/dist/core/settings-tools-bridge.d.ts.map +1 -0
  227. package/dist/core/settings-tools-bridge.js +56 -0
  228. package/dist/core/settings-tools-bridge.js.map +1 -0
  229. package/dist/core/slash-commands.d.ts.map +1 -1
  230. package/dist/core/slash-commands.js +1 -1
  231. package/dist/core/slash-commands.js.map +1 -1
  232. package/dist/core/system-prompt.d.ts.map +1 -1
  233. package/dist/core/system-prompt.js +1 -1
  234. package/dist/core/system-prompt.js.map +1 -1
  235. package/dist/gateway/agent-bridge.d.ts.map +1 -1
  236. package/dist/gateway/agent-bridge.js +3 -2
  237. package/dist/gateway/agent-bridge.js.map +1 -1
  238. package/dist/gateway/approval.d.ts.map +1 -1
  239. package/dist/gateway/approval.js +4 -3
  240. package/dist/gateway/approval.js.map +1 -1
  241. package/dist/gateway/commands.d.ts +1 -1
  242. package/dist/gateway/commands.d.ts.map +1 -1
  243. package/dist/gateway/commands.js +1 -18
  244. package/dist/gateway/commands.js.map +1 -1
  245. package/dist/gateway/cron.d.ts.map +1 -1
  246. package/dist/gateway/cron.js +3 -2
  247. package/dist/gateway/cron.js.map +1 -1
  248. package/dist/gateway/router.d.ts +1 -1
  249. package/dist/gateway/router.d.ts.map +1 -1
  250. package/dist/gateway/router.js +1 -1
  251. package/dist/gateway/router.js.map +1 -1
  252. package/dist/main.d.ts +2 -0
  253. package/dist/main.d.ts.map +1 -1
  254. package/dist/main.js +108 -58
  255. package/dist/main.js.map +1 -1
  256. package/dist/migrations.d.ts +2 -0
  257. package/dist/migrations.d.ts.map +1 -1
  258. package/dist/migrations.js +18 -4
  259. package/dist/migrations.js.map +1 -1
  260. package/dist/modes/interactive/components/assistant-message.d.ts +1 -3
  261. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  262. package/dist/modes/interactive/components/assistant-message.js +4 -32
  263. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  264. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
  265. package/dist/modes/interactive/components/custom-editor.js +2 -1
  266. package/dist/modes/interactive/components/custom-editor.js.map +1 -1
  267. package/dist/modes/interactive/components/injected-prompt-message.d.ts +1 -1
  268. package/dist/modes/interactive/components/injected-prompt-message.d.ts.map +1 -1
  269. package/dist/modes/interactive/components/injected-prompt-message.js +1 -1
  270. package/dist/modes/interactive/components/injected-prompt-message.js.map +1 -1
  271. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  272. package/dist/modes/interactive/components/model-selector.js +4 -1
  273. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  274. package/dist/modes/interactive/components/plan-message.d.ts +1 -3
  275. package/dist/modes/interactive/components/plan-message.d.ts.map +1 -1
  276. package/dist/modes/interactive/components/plan-message.js +1 -16
  277. package/dist/modes/interactive/components/plan-message.js.map +1 -1
  278. package/dist/modes/interactive/components/settings-selector.d.ts +8 -5
  279. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  280. package/dist/modes/interactive/components/settings-selector.js +71 -31
  281. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  282. package/dist/modes/interactive/components/user-message.d.ts +1 -3
  283. package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  284. package/dist/modes/interactive/components/user-message.js +2 -19
  285. package/dist/modes/interactive/components/user-message.js.map +1 -1
  286. package/dist/modes/interactive/interactive-mode.d.ts +13 -4
  287. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  288. package/dist/modes/interactive/interactive-mode.js +163 -177
  289. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  290. package/dist/modes/interactive/theme/moon.json +0 -1
  291. package/dist/modes/interactive/theme/theme-schema.json +3 -3
  292. package/dist/modes/interactive/theme/theme.d.ts +1 -1
  293. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  294. package/dist/modes/interactive/theme/theme.js +95 -90
  295. package/dist/modes/interactive/theme/theme.js.map +1 -1
  296. package/dist/startup/interactive-view.d.ts +55 -0
  297. package/dist/startup/interactive-view.d.ts.map +1 -0
  298. package/dist/startup/interactive-view.js +332 -0
  299. package/dist/startup/interactive-view.js.map +1 -0
  300. package/dist/startup/launch-routing.d.ts +8 -0
  301. package/dist/startup/launch-routing.d.ts.map +1 -0
  302. package/dist/startup/launch-routing.js +29 -0
  303. package/dist/startup/launch-routing.js.map +1 -0
  304. package/dist/startup/startup-milestones.d.ts +4 -0
  305. package/dist/startup/startup-milestones.d.ts.map +1 -0
  306. package/dist/startup/startup-milestones.js +14 -0
  307. package/dist/startup/startup-milestones.js.map +1 -0
  308. package/dist/utils/syntax-highlight.d.ts.map +1 -1
  309. package/dist/utils/syntax-highlight.js +10 -4
  310. package/dist/utils/syntax-highlight.js.map +1 -1
  311. package/docs/features.md +9 -9
  312. package/docs/interactive-startup.md +58 -0
  313. package/docs/keybindings.md +1 -1
  314. package/docs/model-catalog.md +29 -0
  315. package/docs/quickstart.md +3 -2
  316. package/docs/settings.md +4 -4
  317. package/docs/terminal-setup.md +2 -2
  318. package/docs/termux.md +1 -1
  319. package/docs/usage.md +4 -3
  320. package/docs/windows.md +1 -1
  321. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  322. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  323. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  324. package/examples/extensions/gondolin/package-lock.json +2 -2
  325. package/examples/extensions/gondolin/package.json +1 -1
  326. package/examples/extensions/sandbox/package-lock.json +2 -2
  327. package/examples/extensions/sandbox/package.json +1 -1
  328. package/examples/extensions/subagent/README.md +1 -1
  329. package/examples/extensions/with-deps/package-lock.json +2 -2
  330. package/examples/extensions/with-deps/package.json +1 -1
  331. package/package.json +16 -16
  332. package/dist/core/swarm.d.ts +0 -54
  333. package/dist/core/swarm.d.ts.map +0 -1
  334. package/dist/core/swarm.js +0 -119
  335. package/dist/core/swarm.js.map +0 -1
@@ -1,10 +1,12 @@
1
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
1
+ import { createHash, randomUUID } from "node:crypto";
2
+ import { existsSync, mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
2
3
  import { dirname, join } from "node:path";
3
4
  import { fileURLToPath } from "node:url";
4
5
  import { getAgentDir, getPackageDir, VERSION } from "../config.js";
5
6
  import { getPiUserAgent } from "../utils/pi-user-agent.js";
6
7
  /** Directory on GitHub raw (`providers.json` + `providers/{id}.json`). Override with `LUNR_OFFICIAL_CATALOG_URL`. */
7
8
  export const OFFICIAL_CATALOG_DEFAULT_URL = "https://raw.githubusercontent.com/ashx-j/lunR/master/catalog";
9
+ export const VERSIONED_CATALOG_URL = "https://raw.githubusercontent.com/ashx-j/lunR/model-catalog/catalog";
8
10
  export const OFFICIAL_CATALOG_TIMEOUT_MS = 4000;
9
11
  export const OFFICIAL_CATALOG_CACHE_FILENAME = "official-catalog-cache.json";
10
12
  const THINKING_LEVEL_KEYS = ["off", "minimal", "low", "medium", "high", "xhigh", "max"];
@@ -72,6 +74,21 @@ function parseCost(value) {
72
74
  output,
73
75
  cacheRead: asFiniteNumber(value.cacheRead) ?? 0,
74
76
  cacheWrite: asFiniteNumber(value.cacheWrite) ?? 0,
77
+ ...(Array.isArray(value.tiers)
78
+ ? {
79
+ tiers: value.tiers.flatMap((tier) => {
80
+ if (!isRecord(tier) || !(typeof tier.inputTokensAbove === "number" && tier.inputTokensAbove >= 0))
81
+ return [];
82
+ const rates = parseCost({
83
+ input: tier.input,
84
+ output: tier.output,
85
+ cacheRead: tier.cacheRead,
86
+ cacheWrite: tier.cacheWrite,
87
+ });
88
+ return rates ? [{ ...rates, inputTokensAbove: tier.inputTokensAbove }] : [];
89
+ }),
90
+ }
91
+ : {}),
75
92
  };
76
93
  }
77
94
  function parseInput(value) {
@@ -125,6 +142,9 @@ function parseOfficialEntry(value) {
125
142
  const headers = parseHeaders(value.headers);
126
143
  return {
127
144
  id,
145
+ ...(isRecord(value.catalog) && value.catalog.source === "provider" && Array.isArray(value.catalog.supplied)
146
+ ? { catalog: value.catalog }
147
+ : {}),
128
148
  name,
129
149
  api: api,
130
150
  provider,
@@ -232,13 +252,23 @@ export function loadCachedOfficialCatalog(cachePath) {
232
252
  return readCatalogFile(cachePath);
233
253
  }
234
254
  export function writeOfficialCatalogCache(catalog, cachePath) {
255
+ const temporary = `${cachePath}.${randomUUID()}.tmp`;
235
256
  try {
236
257
  mkdirSync(dirname(cachePath), { recursive: true, mode: 0o700 });
237
- writeFileSync(cachePath, `${JSON.stringify(catalog, null, 2)}\n`, "utf-8");
258
+ writeFileSync(temporary, `${JSON.stringify(catalog, null, 2)}\n`, { encoding: "utf-8", mode: 0o600 });
259
+ renameSync(temporary, cachePath);
238
260
  }
239
261
  catch {
240
262
  // Cache is best-effort.
241
263
  }
264
+ finally {
265
+ try {
266
+ unlinkSync(temporary);
267
+ }
268
+ catch {
269
+ /* Renamed or never created. */
270
+ }
271
+ }
242
272
  }
243
273
  export function officialModelsByProvider(catalog) {
244
274
  const byProvider = new Map();
@@ -273,7 +303,7 @@ export function preferOfficialCatalog(previous, next) {
273
303
  if (next.source === "github")
274
304
  return next;
275
305
  if (previous?.source === "github")
276
- return previous;
306
+ return { ...previous, errors: next.errors };
277
307
  return next;
278
308
  }
279
309
  export function officialModelKeys(catalog) {
@@ -282,6 +312,7 @@ export function officialModelKeys(catalog) {
282
312
  const ZERO_COST = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
283
313
  export function officialEntryToModel(entry, template) {
284
314
  return {
315
+ catalog: entry.catalog,
285
316
  id: entry.id,
286
317
  name: entry.name,
287
318
  api: entry.api || template?.api || "openai-completions",
@@ -324,20 +355,22 @@ async function fetchJson(url, options) {
324
355
  error.name = "AbortError";
325
356
  return error;
326
357
  };
327
- const response = await Promise.race([
328
- options.fetchImpl(url, {
329
- headers: options.headers,
330
- signal: controller.signal,
331
- }),
358
+ return await Promise.race([
359
+ (async () => {
360
+ const response = await options.fetchImpl(url, {
361
+ headers: options.headers,
362
+ signal: controller.signal,
363
+ });
364
+ if (!response.ok)
365
+ return { ok: false, status: response.status };
366
+ return { ok: true, value: await response.json() };
367
+ })(),
332
368
  new Promise((_, reject) => {
333
369
  controller.signal.addEventListener("abort", () => reject(abortError()), { once: true });
334
370
  if (controller.signal.aborted)
335
371
  reject(abortError());
336
372
  }),
337
373
  ]);
338
- if (!response.ok)
339
- return { ok: false, status: response.status };
340
- return { ok: true, value: await response.json() };
341
374
  }
342
375
  catch {
343
376
  return { ok: false };
@@ -367,38 +400,70 @@ export async function loadOfficialCatalog(options = {}) {
367
400
  "User-Agent": getPiUserAgent(VERSION),
368
401
  };
369
402
  const fetchOptions = { timeoutMs, signal: options.signal, fetchImpl, headers };
370
- const base = options.url ?? officialCatalogBaseUrl();
403
+ const unavailable = () => ({
404
+ ...fallbackCatalog(bundled, cachePath),
405
+ errors: Object.fromEntries((options.providerIds ?? []).map((id) => [id, "Published catalog unavailable; using cached metadata"])),
406
+ });
407
+ let base = options.url ?? officialCatalogBaseUrl();
408
+ let manifest;
409
+ // Existing custom mirrors remain compatible with the v1 index/shard format.
410
+ if (!options.url && !process.env.LUNR_OFFICIAL_CATALOG_URL) {
411
+ const result = await fetchJson(`${VERSIONED_CATALOG_URL}/publication.json`, fetchOptions);
412
+ if (result.ok &&
413
+ isRecord(result.value) &&
414
+ result.value.version === 2 &&
415
+ typeof result.value.revision === "string" &&
416
+ /^sha256-[a-f0-9]{64}$/.test(result.value.revision) &&
417
+ isRecord(result.value.shards) &&
418
+ parseProviderIndex(result.value.providers)) {
419
+ manifest = result.value;
420
+ base = `${VERSIONED_CATALOG_URL}/snapshots/${result.value.revision}`;
421
+ }
422
+ }
371
423
  try {
372
- const indexResult = await fetchJson(officialCatalogUrlFor("providers.json", base), fetchOptions);
424
+ const indexResult = manifest
425
+ ? { ok: true, value: manifest.providers }
426
+ : await fetchJson(officialCatalogUrlFor("providers.json", base), fetchOptions);
373
427
  if (!indexResult.ok)
374
- return fallbackCatalog(bundled, cachePath);
428
+ return unavailable();
375
429
  const index = parseProviderIndex(indexResult.value);
376
430
  if (!index)
377
- return fallbackCatalog(bundled, cachePath);
431
+ return unavailable();
378
432
  const wanted = new Set(index);
379
433
  const requested = options.providerIds ?? [];
380
434
  const shardIds = requested.filter((providerId) => wanted.has(providerId));
381
435
  if (shardIds.length === 0)
382
436
  return fallbackCatalog(bundled, cachePath);
383
437
  const replacements = new Map();
438
+ const errors = {};
384
439
  await Promise.all(shardIds.map(async (providerId) => {
385
440
  const result = await fetchJson(officialCatalogUrlFor(`providers/${encodeURIComponent(providerId)}.json`, base), fetchOptions);
386
- if (!result.ok)
441
+ if (!result.ok) {
442
+ errors[providerId] = "Catalog shard unavailable; using cached metadata";
387
443
  return;
444
+ }
445
+ if (manifest &&
446
+ manifest.shards[providerId] !==
447
+ createHash("sha256").update(JSON.stringify(result.value)).digest("hex")) {
448
+ errors[providerId] = "Catalog shard checksum mismatch; using cached metadata";
449
+ return;
450
+ }
388
451
  const parsed = parseOfficialCatalog(result.value);
389
- if (!parsed || parsed.models.length === 0)
452
+ if (!parsed || parsed.models.length === 0 || parsed.models.some((model) => model.provider !== providerId)) {
453
+ errors[providerId] = "Invalid catalog shard; using cached metadata";
390
454
  return;
455
+ }
391
456
  replacements.set(providerId, parsed.models);
392
457
  }));
393
458
  if (replacements.size === 0)
394
- return fallbackCatalog(bundled, cachePath);
395
- const catalog = mergeOfficialCatalogByProvider(officialCatalogBase(bundled, cachePath), replacements);
459
+ return { ...fallbackCatalog(bundled, cachePath), errors };
460
+ const catalog = mergeOfficialCatalogByProvider(officialCatalogBase(bundled, cachePath), replacements, typeof manifest?.generatedAt === "string" ? manifest.generatedAt : undefined);
396
461
  if (cachePath)
397
462
  writeOfficialCatalogCache(catalog, cachePath);
398
- return { catalog, source: "github" };
463
+ return { catalog, source: "github", ...(Object.keys(errors).length ? { errors } : {}) };
399
464
  }
400
465
  catch {
401
- return fallbackCatalog(bundled, cachePath);
466
+ return unavailable();
402
467
  }
403
468
  }
404
469
  //# sourceMappingURL=official-catalog.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"official-catalog.js","sourceRoot":"","sources":["../../src/core/official-catalog.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport type { Api, Model, ThinkingLevelMap } from \"@ashx-j/lunr-ai\";\nimport { getAgentDir, getPackageDir, VERSION } from \"../config.ts\";\nimport { getPiUserAgent } from \"../utils/pi-user-agent.ts\";\n\n/** Directory on GitHub raw (`providers.json` + `providers/{id}.json`). Override with `LUNR_OFFICIAL_CATALOG_URL`. */\nexport const OFFICIAL_CATALOG_DEFAULT_URL = \"https://raw.githubusercontent.com/ashx-j/lunR/master/catalog\";\nexport const OFFICIAL_CATALOG_TIMEOUT_MS = 4000;\nexport const OFFICIAL_CATALOG_CACHE_FILENAME = \"official-catalog-cache.json\";\n\nconst THINKING_LEVEL_KEYS = [\"off\", \"minimal\", \"low\", \"medium\", \"high\", \"xhigh\", \"max\"] as const;\nconst META_KEYS = new Set([\"version\", \"updatedAt\", \"generatedAt\", \"sourceCommit\", \"providerCount\", \"modelCount\"]);\n\nexport interface OfficialModelCost {\n\tinput: number;\n\toutput: number;\n\tcacheRead: number;\n\tcacheWrite: number;\n}\n\nexport interface OfficialModelEntry {\n\tid: string;\n\tname: string;\n\tapi: Api;\n\tprovider: string;\n\tbaseUrl: string;\n\treasoning: boolean;\n\tinput: (\"text\" | \"image\")[];\n\tcost: OfficialModelCost;\n\tcontextWindow: number;\n\tmaxTokens: number;\n\tcompat?: Model<Api>[\"compat\"];\n\tthinkingLevelMap?: ThinkingLevelMap;\n\theaders?: Record<string, string>;\n}\n\nexport interface OfficialCatalogFile {\n\tversion: number;\n\tupdatedAt: string;\n\tmodels: OfficialModelEntry[];\n}\n\nexport type OfficialCatalogSource = \"github\" | \"cache\" | \"bundled\";\n\nexport interface OfficialCatalogLoadResult {\n\tcatalog: OfficialCatalogFile;\n\tsource: OfficialCatalogSource;\n}\n\n/** Seed shipped in-repo; used when the JSON file cannot be read. */\nexport const BUNDLED_OFFICIAL_CATALOG: OfficialCatalogFile = {\n\tversion: 1,\n\tupdatedAt: \"2026-08-15T00:00:00Z\",\n\tmodels: [\n\t\t{\n\t\t\tid: \"grok-4.6\",\n\t\t\tname: \"Grok 4.6\",\n\t\t\tapi: \"openai-completions\",\n\t\t\tprovider: \"xai\",\n\t\t\tbaseUrl: \"https://api.x.ai/v1\",\n\t\t\treasoning: true,\n\t\t\tinput: [\"text\", \"image\"],\n\t\t\tcost: { input: 2, output: 6, cacheRead: 0.5, cacheWrite: 0 },\n\t\t\tcontextWindow: 500000,\n\t\t\tmaxTokens: 500000,\n\t\t},\n\t],\n};\n\nexport function officialCatalogCachePath(agentDir: string = getAgentDir()): string {\n\treturn join(agentDir, OFFICIAL_CATALOG_CACHE_FILENAME);\n}\n\n/** Base URL (no trailing slash). `LUNR_OFFICIAL_CATALOG_URL` overrides the directory, not a single file. */\nexport function officialCatalogBaseUrl(override?: string): string {\n\tconst raw = (override ?? process.env.LUNR_OFFICIAL_CATALOG_URL)?.trim() || OFFICIAL_CATALOG_DEFAULT_URL;\n\treturn raw.replace(/\\/+$/, \"\");\n}\n\n/** @deprecated Use officialCatalogBaseUrl. Kept as an alias for the directory base. */\nexport function officialCatalogUrl(): string {\n\treturn officialCatalogBaseUrl();\n}\n\nexport function officialCatalogUrlFor(path: string, base?: string): string {\n\tconst normalized = path.replace(/^\\/+/, \"\");\n\treturn `${officialCatalogBaseUrl(base)}/${normalized}`;\n}\n\nexport function modelKey(provider: string, id: string): string {\n\treturn `${provider}/${id}`;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction asFiniteNumber(value: unknown): number | undefined {\n\tif (typeof value === \"number\" && Number.isFinite(value)) return value;\n\tif (typeof value === \"string\" && value.trim()) {\n\t\tconst parsed = Number(value);\n\t\tif (Number.isFinite(parsed)) return parsed;\n\t}\n\treturn undefined;\n}\n\nfunction parseCost(value: unknown): OfficialModelCost | undefined {\n\tif (!isRecord(value)) return undefined;\n\tconst input = asFiniteNumber(value.input);\n\tconst output = asFiniteNumber(value.output);\n\tif (input === undefined || output === undefined) return undefined;\n\treturn {\n\t\tinput,\n\t\toutput,\n\t\tcacheRead: asFiniteNumber(value.cacheRead) ?? 0,\n\t\tcacheWrite: asFiniteNumber(value.cacheWrite) ?? 0,\n\t};\n}\n\nfunction parseInput(value: unknown): (\"text\" | \"image\")[] | undefined {\n\tif (!Array.isArray(value)) return undefined;\n\tconst input: (\"text\" | \"image\")[] = [];\n\tfor (const entry of value) {\n\t\tif (entry === \"text\" || entry === \"image\") input.push(entry);\n\t}\n\treturn input.length > 0 ? input : undefined;\n}\n\nfunction parseThinkingLevelMap(value: unknown): ThinkingLevelMap | undefined {\n\tif (!isRecord(value)) return undefined;\n\tconst map: ThinkingLevelMap = {};\n\tlet any = false;\n\tfor (const level of THINKING_LEVEL_KEYS) {\n\t\tconst mapped = value[level];\n\t\tif (mapped === null || typeof mapped === \"string\") {\n\t\t\tmap[level] = mapped;\n\t\t\tany = true;\n\t\t}\n\t}\n\treturn any ? map : undefined;\n}\n\nfunction parseHeaders(value: unknown): Record<string, string> | undefined {\n\tif (!isRecord(value)) return undefined;\n\tconst headers: Record<string, string> = {};\n\tfor (const [name, headerValue] of Object.entries(value)) {\n\t\tif (typeof headerValue === \"string\") headers[name] = headerValue;\n\t}\n\treturn Object.keys(headers).length > 0 ? headers : undefined;\n}\n\nfunction parseOfficialEntry(value: unknown): OfficialModelEntry | undefined {\n\tif (!isRecord(value)) return undefined;\n\tconst id = typeof value.id === \"string\" ? value.id.trim() : \"\";\n\tconst provider = typeof value.provider === \"string\" ? value.provider.trim() : \"\";\n\tif (!id || !provider) return undefined;\n\tconst api = typeof value.api === \"string\" && value.api.trim() ? value.api.trim() : \"openai-completions\";\n\tconst name = typeof value.name === \"string\" && value.name.trim() ? value.name.trim() : id;\n\tconst baseUrl = typeof value.baseUrl === \"string\" ? value.baseUrl.trim() : \"\";\n\tconst cost = parseCost(value.cost) ?? { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };\n\tconst input = parseInput(value.input) ?? [\"text\"];\n\tconst compat = isRecord(value.compat) ? (value.compat as Model<Api>[\"compat\"]) : undefined;\n\tconst thinkingLevelMap = parseThinkingLevelMap(value.thinkingLevelMap);\n\tconst headers = parseHeaders(value.headers);\n\treturn {\n\t\tid,\n\t\tname,\n\t\tapi: api as Api,\n\t\tprovider,\n\t\tbaseUrl,\n\t\treasoning: value.reasoning === true,\n\t\tinput,\n\t\tcost,\n\t\tcontextWindow: asFiniteNumber(value.contextWindow) ?? 128000,\n\t\tmaxTokens: asFiniteNumber(value.maxTokens) ?? 8192,\n\t\t...(compat ? { compat } : {}),\n\t\t...(thinkingLevelMap ? { thinkingLevelMap } : {}),\n\t\t...(headers ? { headers } : {}),\n\t};\n}\n\nfunction catalogFile(models: OfficialModelEntry[], value?: Record<string, unknown>): OfficialCatalogFile {\n\tconst version = value ? (asFiniteNumber(value.version) ?? 1) : 1;\n\tconst updatedAt = value && typeof value.updatedAt === \"string\" && value.updatedAt.trim() ? value.updatedAt : \"\";\n\treturn { version, updatedAt, models };\n}\n\nfunction parseKeyedCatalog(value: Record<string, unknown>): OfficialCatalogFile | undefined {\n\tconst models: OfficialModelEntry[] = [];\n\tfor (const [key, entry] of Object.entries(value)) {\n\t\tif (META_KEYS.has(key) || !isRecord(entry)) continue;\n\t\tif (typeof entry.id === \"string\") {\n\t\t\tconst parsed = parseOfficialEntry(entry);\n\t\t\tif (parsed) models.push(parsed);\n\t\t\tcontinue;\n\t\t}\n\t\tfor (const [modelId, model] of Object.entries(entry)) {\n\t\t\tif (!isRecord(model)) continue;\n\t\t\tconst parsed = parseOfficialEntry({\n\t\t\t\t...model,\n\t\t\t\tid: typeof model.id === \"string\" && model.id.trim() ? model.id : modelId,\n\t\t\t\tprovider: typeof model.provider === \"string\" && model.provider.trim() ? model.provider : key,\n\t\t\t});\n\t\t\tif (parsed) models.push(parsed);\n\t\t}\n\t}\n\treturn models.length > 0 ? catalogFile(models, value) : undefined;\n}\n\n/** Parse an official catalog document. Returns undefined on a bad shape (never throws). */\nexport function parseOfficialCatalog(value: unknown): OfficialCatalogFile | undefined {\n\tif (!isRecord(value)) return undefined;\n\tif (Array.isArray(value.models)) {\n\t\tconst models: OfficialModelEntry[] = [];\n\t\tfor (const entry of value.models) {\n\t\t\tconst parsed = parseOfficialEntry(entry);\n\t\t\tif (parsed) models.push(parsed);\n\t\t}\n\t\treturn catalogFile(models, value);\n\t}\n\tif (\"models\" in value) return undefined;\n\treturn parseKeyedCatalog(value);\n}\n\nfunction parseProviderIndex(value: unknown): string[] | undefined {\n\tif (!Array.isArray(value) || !value.every((entry) => typeof entry === \"string\")) return undefined;\n\treturn value;\n}\n\nfunction readCatalogFile(path: string): OfficialCatalogFile | undefined {\n\ttry {\n\t\tif (!existsSync(path)) return undefined;\n\t\treturn parseOfficialCatalog(JSON.parse(readFileSync(path, \"utf-8\")));\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction bundledCatalogCandidates(): string[] {\n\tconst here = dirname(fileURLToPath(import.meta.url));\n\tconst packageDir = getPackageDir();\n\treturn [\n\t\tjoin(packageDir, \"dist\", \"catalog\", \"models.json\"),\n\t\tjoin(packageDir, \"..\", \"..\", \"catalog\", \"models.json\"),\n\t\tjoin(here, \"../../../../catalog/models.json\"),\n\t\tjoin(packageDir, \"catalog\", \"models.json\"),\n\t\tjoin(here, \"../catalog/models.json\"),\n\t\tjoin(here, \"models.json\"),\n\t\tjoin(packageDir, \"dist\", \"catalog\", \"official-models.json\"),\n\t\tjoin(packageDir, \"..\", \"..\", \"catalog\", \"official-models.json\"),\n\t\tjoin(here, \"../../../../catalog/official-models.json\"),\n\t\tjoin(here, \"official-models.json\"),\n\t\tjoin(here, \"../catalog/official-models.json\"),\n\t];\n}\n\nexport function loadBundledOfficialCatalog(): OfficialCatalogFile {\n\tfor (const path of bundledCatalogCandidates()) {\n\t\tconst parsed = readCatalogFile(path);\n\t\tif (parsed) return parsed;\n\t}\n\treturn BUNDLED_OFFICIAL_CATALOG;\n}\n\nexport function loadCachedOfficialCatalog(cachePath?: string): OfficialCatalogFile | undefined {\n\tif (!cachePath) return undefined;\n\treturn readCatalogFile(cachePath);\n}\n\nexport function writeOfficialCatalogCache(catalog: OfficialCatalogFile, cachePath: string): void {\n\ttry {\n\t\tmkdirSync(dirname(cachePath), { recursive: true, mode: 0o700 });\n\t\twriteFileSync(cachePath, `${JSON.stringify(catalog, null, 2)}\\n`, \"utf-8\");\n\t} catch {\n\t\t// Cache is best-effort.\n\t}\n}\n\nexport function officialModelsByProvider(catalog: OfficialCatalogFile): Map<string, OfficialModelEntry[]> {\n\tconst byProvider = new Map<string, OfficialModelEntry[]>();\n\tfor (const model of catalog.models) {\n\t\tconst list = byProvider.get(model.provider) ?? [];\n\t\tlist.push(model);\n\t\tbyProvider.set(model.provider, list);\n\t}\n\treturn byProvider;\n}\n\n/** Replace or add per-provider rows. Existing providers not in `replacements` are kept. */\nexport function mergeOfficialCatalogByProvider(\n\tbase: OfficialCatalogFile,\n\treplacements: ReadonlyMap<string, OfficialModelEntry[]>,\n\tupdatedAt?: string,\n): OfficialCatalogFile {\n\tconst byProvider = officialModelsByProvider(base);\n\tfor (const [providerId, models] of replacements) {\n\t\tbyProvider.set(providerId, models);\n\t}\n\treturn {\n\t\tversion: base.version || 1,\n\t\tupdatedAt: updatedAt ?? new Date().toISOString(),\n\t\tmodels: [...byProvider.values()].flat(),\n\t};\n}\n\n/** Bundled as the floor; cache rows win per provider. */\nexport function officialCatalogBase(bundled: OfficialCatalogFile, cachePath?: string): OfficialCatalogFile {\n\tconst cached = loadCachedOfficialCatalog(cachePath);\n\tif (!cached) return bundled;\n\treturn mergeOfficialCatalogByProvider(bundled, officialModelsByProvider(cached), cached.updatedAt);\n}\n\n/** A completed GitHub overlay must not be replaced by cache/bundled. */\nexport function preferOfficialCatalog(\n\tprevious: OfficialCatalogLoadResult | undefined,\n\tnext: OfficialCatalogLoadResult,\n): OfficialCatalogLoadResult {\n\tif (next.source === \"github\") return next;\n\tif (previous?.source === \"github\") return previous;\n\treturn next;\n}\n\nexport function officialModelKeys(catalog: OfficialCatalogFile): Set<string> {\n\treturn new Set(catalog.models.map((model) => modelKey(model.provider, model.id)));\n}\n\nconst ZERO_COST = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };\n\nexport function officialEntryToModel(entry: OfficialModelEntry, template?: Model<Api>): Model<Api> {\n\treturn {\n\t\tid: entry.id,\n\t\tname: entry.name,\n\t\tapi: entry.api || template?.api || \"openai-completions\",\n\t\tprovider: entry.provider,\n\t\tbaseUrl: entry.baseUrl || template?.baseUrl || \"\",\n\t\treasoning: entry.reasoning,\n\t\tinput: entry.input.length > 0 ? entry.input : (template?.input ?? [\"text\"]),\n\t\tcost: entry.cost ?? template?.cost ?? ZERO_COST,\n\t\tcontextWindow: entry.contextWindow,\n\t\tmaxTokens: entry.maxTokens,\n\t\tcompat: entry.compat ?? template?.compat,\n\t\tthinkingLevelMap: entry.thinkingLevelMap ?? template?.thinkingLevelMap,\n\t\theaders: entry.headers ?? template?.headers,\n\t};\n}\n\nexport interface LoadOfficialCatalogOptions {\n\tallowNetwork?: boolean;\n\tcachePath?: string;\n\tbundled?: OfficialCatalogFile;\n\t/** Catalog directory base (not a single-file URL). */\n\turl?: string;\n\ttimeoutMs?: number;\n\tsignal?: AbortSignal;\n\tfetchImpl?: typeof fetch;\n\t/** Stored-credential provider ids. Only these shards are fetched. */\n\tproviderIds?: readonly string[];\n}\n\nfunction resolveBundledCatalog(bundled?: OfficialCatalogFile): OfficialCatalogFile {\n\tif (bundled) return bundled;\n\treturn loadBundledOfficialCatalog();\n}\n\nfunction fallbackCatalog(bundled: OfficialCatalogFile | undefined, cachePath?: string): OfficialCatalogLoadResult {\n\tconst cached = loadCachedOfficialCatalog(cachePath);\n\tif (cached) return { catalog: cached, source: \"cache\" };\n\tconst resolved = resolveBundledCatalog(bundled);\n\tif (resolved.models.length > 0) return { catalog: resolved, source: \"bundled\" };\n\treturn { catalog: BUNDLED_OFFICIAL_CATALOG, source: \"bundled\" };\n}\n\nasync function fetchJson(\n\turl: string,\n\toptions: {\n\t\ttimeoutMs: number;\n\t\tsignal?: AbortSignal;\n\t\tfetchImpl: typeof fetch;\n\t\theaders: Record<string, string>;\n\t},\n): Promise<{ ok: true; value: unknown } | { ok: false; status?: number }> {\n\tconst controller = new AbortController();\n\tconst timer = setTimeout(() => controller.abort(), options.timeoutMs);\n\tconst onParentAbort = () => controller.abort();\n\toptions.signal?.addEventListener(\"abort\", onParentAbort, { once: true });\n\tif (options.signal?.aborted) controller.abort();\n\ttry {\n\t\tconst abortError = () => {\n\t\t\tconst error = new Error(\"The operation was aborted\");\n\t\t\terror.name = \"AbortError\";\n\t\t\treturn error;\n\t\t};\n\t\tconst response = await Promise.race([\n\t\t\toptions.fetchImpl(url, {\n\t\t\t\theaders: options.headers,\n\t\t\t\tsignal: controller.signal,\n\t\t\t}),\n\t\t\tnew Promise<never>((_, reject) => {\n\t\t\t\tcontroller.signal.addEventListener(\"abort\", () => reject(abortError()), { once: true });\n\t\t\t\tif (controller.signal.aborted) reject(abortError());\n\t\t\t}),\n\t\t]);\n\t\tif (!response.ok) return { ok: false, status: response.status };\n\t\treturn { ok: true, value: await response.json() };\n\t} catch {\n\t\treturn { ok: false };\n\t} finally {\n\t\tclearTimeout(timer);\n\t\toptions.signal?.removeEventListener(\"abort\", onParentAbort);\n\t}\n}\n\n/**\n * Load the official overlay. Network only when allowNetwork is true.\n * Fetches providers.json, then providers/{id}.json for stored-credential providers.\n * Successful shards replace that provider only; failed shards keep cache/bundled rows.\n * All requested shards failed → cache, then bundled. Never writes a worse cache. Never throws.\n */\nexport async function loadOfficialCatalog(\n\toptions: LoadOfficialCatalogOptions = {},\n): Promise<OfficialCatalogLoadResult> {\n\tconst cachePath = options.cachePath;\n\t// Cache-only: prefer the on-disk cache and skip parsing bundled models.json.\n\tif (!options.allowNetwork) {\n\t\treturn fallbackCatalog(options.bundled, cachePath);\n\t}\n\n\tconst bundled = resolveBundledCatalog(options.bundled);\n\tconst timeoutMs = options.timeoutMs ?? OFFICIAL_CATALOG_TIMEOUT_MS;\n\tconst fetchImpl = options.fetchImpl ?? fetch;\n\tconst headers = {\n\t\taccept: \"application/json\",\n\t\t\"User-Agent\": getPiUserAgent(VERSION),\n\t};\n\tconst fetchOptions = { timeoutMs, signal: options.signal, fetchImpl, headers };\n\tconst base = options.url ?? officialCatalogBaseUrl();\n\n\ttry {\n\t\tconst indexResult = await fetchJson(officialCatalogUrlFor(\"providers.json\", base), fetchOptions);\n\t\tif (!indexResult.ok) return fallbackCatalog(bundled, cachePath);\n\t\tconst index = parseProviderIndex(indexResult.value);\n\t\tif (!index) return fallbackCatalog(bundled, cachePath);\n\n\t\tconst wanted = new Set(index);\n\t\tconst requested = options.providerIds ?? [];\n\t\tconst shardIds = requested.filter((providerId) => wanted.has(providerId));\n\t\tif (shardIds.length === 0) return fallbackCatalog(bundled, cachePath);\n\n\t\tconst replacements = new Map<string, OfficialModelEntry[]>();\n\t\tawait Promise.all(\n\t\t\tshardIds.map(async (providerId) => {\n\t\t\t\tconst result = await fetchJson(\n\t\t\t\t\tofficialCatalogUrlFor(`providers/${encodeURIComponent(providerId)}.json`, base),\n\t\t\t\t\tfetchOptions,\n\t\t\t\t);\n\t\t\t\tif (!result.ok) return;\n\t\t\t\tconst parsed = parseOfficialCatalog(result.value);\n\t\t\t\tif (!parsed || parsed.models.length === 0) return;\n\t\t\t\treplacements.set(providerId, parsed.models);\n\t\t\t}),\n\t\t);\n\t\tif (replacements.size === 0) return fallbackCatalog(bundled, cachePath);\n\n\t\tconst catalog = mergeOfficialCatalogByProvider(officialCatalogBase(bundled, cachePath), replacements);\n\t\tif (cachePath) writeOfficialCatalogCache(catalog, cachePath);\n\t\treturn { catalog, source: \"github\" };\n\t} catch {\n\t\treturn fallbackCatalog(bundled, cachePath);\n\t}\n}\n"]}
1
+ {"version":3,"file":"official-catalog.js","sourceRoot":"","sources":["../../src/core/official-catalog.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash, randomUUID } from \"node:crypto\";\nimport { existsSync, mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport type { Api, Model, ThinkingLevelMap } from \"@ashx-j/lunr-ai\";\nimport { getAgentDir, getPackageDir, VERSION } from \"../config.ts\";\nimport { getPiUserAgent } from \"../utils/pi-user-agent.ts\";\n\n/** Directory on GitHub raw (`providers.json` + `providers/{id}.json`). Override with `LUNR_OFFICIAL_CATALOG_URL`. */\nexport const OFFICIAL_CATALOG_DEFAULT_URL = \"https://raw.githubusercontent.com/ashx-j/lunR/master/catalog\";\nexport const VERSIONED_CATALOG_URL = \"https://raw.githubusercontent.com/ashx-j/lunR/model-catalog/catalog\";\nexport const OFFICIAL_CATALOG_TIMEOUT_MS = 4000;\nexport const OFFICIAL_CATALOG_CACHE_FILENAME = \"official-catalog-cache.json\";\n\nconst THINKING_LEVEL_KEYS = [\"off\", \"minimal\", \"low\", \"medium\", \"high\", \"xhigh\", \"max\"] as const;\nconst META_KEYS = new Set([\"version\", \"updatedAt\", \"generatedAt\", \"sourceCommit\", \"providerCount\", \"modelCount\"]);\n\nexport interface OfficialModelCost {\n\ttiers?: Model<Api>[\"cost\"][\"tiers\"];\n\tinput: number;\n\toutput: number;\n\tcacheRead: number;\n\tcacheWrite: number;\n}\n\nexport interface OfficialModelEntry {\n\tcatalog?: Model<Api>[\"catalog\"];\n\tid: string;\n\tname: string;\n\tapi: Api;\n\tprovider: string;\n\tbaseUrl: string;\n\treasoning: boolean;\n\tinput: (\"text\" | \"image\")[];\n\tcost: OfficialModelCost;\n\tcontextWindow: number;\n\tmaxTokens: number;\n\tcompat?: Model<Api>[\"compat\"];\n\tthinkingLevelMap?: ThinkingLevelMap;\n\theaders?: Record<string, string>;\n}\n\nexport interface OfficialCatalogFile {\n\tversion: number;\n\tupdatedAt: string;\n\tmodels: OfficialModelEntry[];\n}\n\nexport type OfficialCatalogSource = \"github\" | \"cache\" | \"bundled\";\n\nexport interface OfficialCatalogLoadResult {\n\terrors?: Record<string, string>;\n\tcatalog: OfficialCatalogFile;\n\tsource: OfficialCatalogSource;\n}\n\n/** Seed shipped in-repo; used when the JSON file cannot be read. */\nexport const BUNDLED_OFFICIAL_CATALOG: OfficialCatalogFile = {\n\tversion: 1,\n\tupdatedAt: \"2026-08-15T00:00:00Z\",\n\tmodels: [\n\t\t{\n\t\t\tid: \"grok-4.6\",\n\t\t\tname: \"Grok 4.6\",\n\t\t\tapi: \"openai-completions\",\n\t\t\tprovider: \"xai\",\n\t\t\tbaseUrl: \"https://api.x.ai/v1\",\n\t\t\treasoning: true,\n\t\t\tinput: [\"text\", \"image\"],\n\t\t\tcost: { input: 2, output: 6, cacheRead: 0.5, cacheWrite: 0 },\n\t\t\tcontextWindow: 500000,\n\t\t\tmaxTokens: 500000,\n\t\t},\n\t],\n};\n\nexport function officialCatalogCachePath(agentDir: string = getAgentDir()): string {\n\treturn join(agentDir, OFFICIAL_CATALOG_CACHE_FILENAME);\n}\n\n/** Base URL (no trailing slash). `LUNR_OFFICIAL_CATALOG_URL` overrides the directory, not a single file. */\nexport function officialCatalogBaseUrl(override?: string): string {\n\tconst raw = (override ?? process.env.LUNR_OFFICIAL_CATALOG_URL)?.trim() || OFFICIAL_CATALOG_DEFAULT_URL;\n\treturn raw.replace(/\\/+$/, \"\");\n}\n\n/** @deprecated Use officialCatalogBaseUrl. Kept as an alias for the directory base. */\nexport function officialCatalogUrl(): string {\n\treturn officialCatalogBaseUrl();\n}\n\nexport function officialCatalogUrlFor(path: string, base?: string): string {\n\tconst normalized = path.replace(/^\\/+/, \"\");\n\treturn `${officialCatalogBaseUrl(base)}/${normalized}`;\n}\n\nexport function modelKey(provider: string, id: string): string {\n\treturn `${provider}/${id}`;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction asFiniteNumber(value: unknown): number | undefined {\n\tif (typeof value === \"number\" && Number.isFinite(value)) return value;\n\tif (typeof value === \"string\" && value.trim()) {\n\t\tconst parsed = Number(value);\n\t\tif (Number.isFinite(parsed)) return parsed;\n\t}\n\treturn undefined;\n}\n\nfunction parseCost(value: unknown): OfficialModelCost | undefined {\n\tif (!isRecord(value)) return undefined;\n\tconst input = asFiniteNumber(value.input);\n\tconst output = asFiniteNumber(value.output);\n\tif (input === undefined || output === undefined) return undefined;\n\treturn {\n\t\tinput,\n\t\toutput,\n\t\tcacheRead: asFiniteNumber(value.cacheRead) ?? 0,\n\t\tcacheWrite: asFiniteNumber(value.cacheWrite) ?? 0,\n\t\t...(Array.isArray(value.tiers)\n\t\t\t? {\n\t\t\t\t\ttiers: value.tiers.flatMap((tier) => {\n\t\t\t\t\t\tif (!isRecord(tier) || !(typeof tier.inputTokensAbove === \"number\" && tier.inputTokensAbove >= 0))\n\t\t\t\t\t\t\treturn [];\n\t\t\t\t\t\tconst rates = parseCost({\n\t\t\t\t\t\t\tinput: tier.input,\n\t\t\t\t\t\t\toutput: tier.output,\n\t\t\t\t\t\t\tcacheRead: tier.cacheRead,\n\t\t\t\t\t\t\tcacheWrite: tier.cacheWrite,\n\t\t\t\t\t\t});\n\t\t\t\t\t\treturn rates ? [{ ...rates, inputTokensAbove: tier.inputTokensAbove }] : [];\n\t\t\t\t\t}),\n\t\t\t\t}\n\t\t\t: {}),\n\t};\n}\n\nfunction parseInput(value: unknown): (\"text\" | \"image\")[] | undefined {\n\tif (!Array.isArray(value)) return undefined;\n\tconst input: (\"text\" | \"image\")[] = [];\n\tfor (const entry of value) {\n\t\tif (entry === \"text\" || entry === \"image\") input.push(entry);\n\t}\n\treturn input.length > 0 ? input : undefined;\n}\n\nfunction parseThinkingLevelMap(value: unknown): ThinkingLevelMap | undefined {\n\tif (!isRecord(value)) return undefined;\n\tconst map: ThinkingLevelMap = {};\n\tlet any = false;\n\tfor (const level of THINKING_LEVEL_KEYS) {\n\t\tconst mapped = value[level];\n\t\tif (mapped === null || typeof mapped === \"string\") {\n\t\t\tmap[level] = mapped;\n\t\t\tany = true;\n\t\t}\n\t}\n\treturn any ? map : undefined;\n}\n\nfunction parseHeaders(value: unknown): Record<string, string> | undefined {\n\tif (!isRecord(value)) return undefined;\n\tconst headers: Record<string, string> = {};\n\tfor (const [name, headerValue] of Object.entries(value)) {\n\t\tif (typeof headerValue === \"string\") headers[name] = headerValue;\n\t}\n\treturn Object.keys(headers).length > 0 ? headers : undefined;\n}\n\nfunction parseOfficialEntry(value: unknown): OfficialModelEntry | undefined {\n\tif (!isRecord(value)) return undefined;\n\tconst id = typeof value.id === \"string\" ? value.id.trim() : \"\";\n\tconst provider = typeof value.provider === \"string\" ? value.provider.trim() : \"\";\n\tif (!id || !provider) return undefined;\n\tconst api = typeof value.api === \"string\" && value.api.trim() ? value.api.trim() : \"openai-completions\";\n\tconst name = typeof value.name === \"string\" && value.name.trim() ? value.name.trim() : id;\n\tconst baseUrl = typeof value.baseUrl === \"string\" ? value.baseUrl.trim() : \"\";\n\tconst cost = parseCost(value.cost) ?? { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };\n\tconst input = parseInput(value.input) ?? [\"text\"];\n\tconst compat = isRecord(value.compat) ? (value.compat as Model<Api>[\"compat\"]) : undefined;\n\tconst thinkingLevelMap = parseThinkingLevelMap(value.thinkingLevelMap);\n\tconst headers = parseHeaders(value.headers);\n\treturn {\n\t\tid,\n\t\t...(isRecord(value.catalog) && value.catalog.source === \"provider\" && Array.isArray(value.catalog.supplied)\n\t\t\t? { catalog: value.catalog as Model<Api>[\"catalog\"] }\n\t\t\t: {}),\n\t\tname,\n\t\tapi: api as Api,\n\t\tprovider,\n\t\tbaseUrl,\n\t\treasoning: value.reasoning === true,\n\t\tinput,\n\t\tcost,\n\t\tcontextWindow: asFiniteNumber(value.contextWindow) ?? 128000,\n\t\tmaxTokens: asFiniteNumber(value.maxTokens) ?? 8192,\n\t\t...(compat ? { compat } : {}),\n\t\t...(thinkingLevelMap ? { thinkingLevelMap } : {}),\n\t\t...(headers ? { headers } : {}),\n\t};\n}\n\nfunction catalogFile(models: OfficialModelEntry[], value?: Record<string, unknown>): OfficialCatalogFile {\n\tconst version = value ? (asFiniteNumber(value.version) ?? 1) : 1;\n\tconst updatedAt = value && typeof value.updatedAt === \"string\" && value.updatedAt.trim() ? value.updatedAt : \"\";\n\treturn { version, updatedAt, models };\n}\n\nfunction parseKeyedCatalog(value: Record<string, unknown>): OfficialCatalogFile | undefined {\n\tconst models: OfficialModelEntry[] = [];\n\tfor (const [key, entry] of Object.entries(value)) {\n\t\tif (META_KEYS.has(key) || !isRecord(entry)) continue;\n\t\tif (typeof entry.id === \"string\") {\n\t\t\tconst parsed = parseOfficialEntry(entry);\n\t\t\tif (parsed) models.push(parsed);\n\t\t\tcontinue;\n\t\t}\n\t\tfor (const [modelId, model] of Object.entries(entry)) {\n\t\t\tif (!isRecord(model)) continue;\n\t\t\tconst parsed = parseOfficialEntry({\n\t\t\t\t...model,\n\t\t\t\tid: typeof model.id === \"string\" && model.id.trim() ? model.id : modelId,\n\t\t\t\tprovider: typeof model.provider === \"string\" && model.provider.trim() ? model.provider : key,\n\t\t\t});\n\t\t\tif (parsed) models.push(parsed);\n\t\t}\n\t}\n\treturn models.length > 0 ? catalogFile(models, value) : undefined;\n}\n\n/** Parse an official catalog document. Returns undefined on a bad shape (never throws). */\nexport function parseOfficialCatalog(value: unknown): OfficialCatalogFile | undefined {\n\tif (!isRecord(value)) return undefined;\n\tif (Array.isArray(value.models)) {\n\t\tconst models: OfficialModelEntry[] = [];\n\t\tfor (const entry of value.models) {\n\t\t\tconst parsed = parseOfficialEntry(entry);\n\t\t\tif (parsed) models.push(parsed);\n\t\t}\n\t\treturn catalogFile(models, value);\n\t}\n\tif (\"models\" in value) return undefined;\n\treturn parseKeyedCatalog(value);\n}\n\nfunction parseProviderIndex(value: unknown): string[] | undefined {\n\tif (!Array.isArray(value) || !value.every((entry) => typeof entry === \"string\")) return undefined;\n\treturn value;\n}\n\nfunction readCatalogFile(path: string): OfficialCatalogFile | undefined {\n\ttry {\n\t\tif (!existsSync(path)) return undefined;\n\t\treturn parseOfficialCatalog(JSON.parse(readFileSync(path, \"utf-8\")));\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction bundledCatalogCandidates(): string[] {\n\tconst here = dirname(fileURLToPath(import.meta.url));\n\tconst packageDir = getPackageDir();\n\treturn [\n\t\tjoin(packageDir, \"dist\", \"catalog\", \"models.json\"),\n\t\tjoin(packageDir, \"..\", \"..\", \"catalog\", \"models.json\"),\n\t\tjoin(here, \"../../../../catalog/models.json\"),\n\t\tjoin(packageDir, \"catalog\", \"models.json\"),\n\t\tjoin(here, \"../catalog/models.json\"),\n\t\tjoin(here, \"models.json\"),\n\t\tjoin(packageDir, \"dist\", \"catalog\", \"official-models.json\"),\n\t\tjoin(packageDir, \"..\", \"..\", \"catalog\", \"official-models.json\"),\n\t\tjoin(here, \"../../../../catalog/official-models.json\"),\n\t\tjoin(here, \"official-models.json\"),\n\t\tjoin(here, \"../catalog/official-models.json\"),\n\t];\n}\n\nexport function loadBundledOfficialCatalog(): OfficialCatalogFile {\n\tfor (const path of bundledCatalogCandidates()) {\n\t\tconst parsed = readCatalogFile(path);\n\t\tif (parsed) return parsed;\n\t}\n\treturn BUNDLED_OFFICIAL_CATALOG;\n}\n\nexport function loadCachedOfficialCatalog(cachePath?: string): OfficialCatalogFile | undefined {\n\tif (!cachePath) return undefined;\n\treturn readCatalogFile(cachePath);\n}\n\nexport function writeOfficialCatalogCache(catalog: OfficialCatalogFile, cachePath: string): void {\n\tconst temporary = `${cachePath}.${randomUUID()}.tmp`;\n\ttry {\n\t\tmkdirSync(dirname(cachePath), { recursive: true, mode: 0o700 });\n\t\twriteFileSync(temporary, `${JSON.stringify(catalog, null, 2)}\\n`, { encoding: \"utf-8\", mode: 0o600 });\n\t\trenameSync(temporary, cachePath);\n\t} catch {\n\t\t// Cache is best-effort.\n\t} finally {\n\t\ttry {\n\t\t\tunlinkSync(temporary);\n\t\t} catch {\n\t\t\t/* Renamed or never created. */\n\t\t}\n\t}\n}\n\nexport function officialModelsByProvider(catalog: OfficialCatalogFile): Map<string, OfficialModelEntry[]> {\n\tconst byProvider = new Map<string, OfficialModelEntry[]>();\n\tfor (const model of catalog.models) {\n\t\tconst list = byProvider.get(model.provider) ?? [];\n\t\tlist.push(model);\n\t\tbyProvider.set(model.provider, list);\n\t}\n\treturn byProvider;\n}\n\n/** Replace or add per-provider rows. Existing providers not in `replacements` are kept. */\nexport function mergeOfficialCatalogByProvider(\n\tbase: OfficialCatalogFile,\n\treplacements: ReadonlyMap<string, OfficialModelEntry[]>,\n\tupdatedAt?: string,\n): OfficialCatalogFile {\n\tconst byProvider = officialModelsByProvider(base);\n\tfor (const [providerId, models] of replacements) {\n\t\tbyProvider.set(providerId, models);\n\t}\n\treturn {\n\t\tversion: base.version || 1,\n\t\tupdatedAt: updatedAt ?? new Date().toISOString(),\n\t\tmodels: [...byProvider.values()].flat(),\n\t};\n}\n\n/** Bundled as the floor; cache rows win per provider. */\nexport function officialCatalogBase(bundled: OfficialCatalogFile, cachePath?: string): OfficialCatalogFile {\n\tconst cached = loadCachedOfficialCatalog(cachePath);\n\tif (!cached) return bundled;\n\treturn mergeOfficialCatalogByProvider(bundled, officialModelsByProvider(cached), cached.updatedAt);\n}\n\n/** A completed GitHub overlay must not be replaced by cache/bundled. */\nexport function preferOfficialCatalog(\n\tprevious: OfficialCatalogLoadResult | undefined,\n\tnext: OfficialCatalogLoadResult,\n): OfficialCatalogLoadResult {\n\tif (next.source === \"github\") return next;\n\tif (previous?.source === \"github\") return { ...previous, errors: next.errors };\n\treturn next;\n}\n\nexport function officialModelKeys(catalog: OfficialCatalogFile): Set<string> {\n\treturn new Set(catalog.models.map((model) => modelKey(model.provider, model.id)));\n}\n\nconst ZERO_COST = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };\n\nexport function officialEntryToModel(entry: OfficialModelEntry, template?: Model<Api>): Model<Api> {\n\treturn {\n\t\tcatalog: entry.catalog,\n\t\tid: entry.id,\n\t\tname: entry.name,\n\t\tapi: entry.api || template?.api || \"openai-completions\",\n\t\tprovider: entry.provider,\n\t\tbaseUrl: entry.baseUrl || template?.baseUrl || \"\",\n\t\treasoning: entry.reasoning,\n\t\tinput: entry.input.length > 0 ? entry.input : (template?.input ?? [\"text\"]),\n\t\tcost: entry.cost ?? template?.cost ?? ZERO_COST,\n\t\tcontextWindow: entry.contextWindow,\n\t\tmaxTokens: entry.maxTokens,\n\t\tcompat: entry.compat ?? template?.compat,\n\t\tthinkingLevelMap: entry.thinkingLevelMap ?? template?.thinkingLevelMap,\n\t\theaders: entry.headers ?? template?.headers,\n\t};\n}\n\nexport interface LoadOfficialCatalogOptions {\n\tallowNetwork?: boolean;\n\tcachePath?: string;\n\tbundled?: OfficialCatalogFile;\n\t/** Catalog directory base (not a single-file URL). */\n\turl?: string;\n\ttimeoutMs?: number;\n\tsignal?: AbortSignal;\n\tfetchImpl?: typeof fetch;\n\t/** Stored-credential provider ids. Only these shards are fetched. */\n\tproviderIds?: readonly string[];\n}\n\nfunction resolveBundledCatalog(bundled?: OfficialCatalogFile): OfficialCatalogFile {\n\tif (bundled) return bundled;\n\treturn loadBundledOfficialCatalog();\n}\n\nfunction fallbackCatalog(bundled: OfficialCatalogFile | undefined, cachePath?: string): OfficialCatalogLoadResult {\n\tconst cached = loadCachedOfficialCatalog(cachePath);\n\tif (cached) return { catalog: cached, source: \"cache\" };\n\tconst resolved = resolveBundledCatalog(bundled);\n\tif (resolved.models.length > 0) return { catalog: resolved, source: \"bundled\" };\n\treturn { catalog: BUNDLED_OFFICIAL_CATALOG, source: \"bundled\" };\n}\n\nasync function fetchJson(\n\turl: string,\n\toptions: {\n\t\ttimeoutMs: number;\n\t\tsignal?: AbortSignal;\n\t\tfetchImpl: typeof fetch;\n\t\theaders: Record<string, string>;\n\t},\n): Promise<{ ok: true; value: unknown } | { ok: false; status?: number }> {\n\tconst controller = new AbortController();\n\tconst timer = setTimeout(() => controller.abort(), options.timeoutMs);\n\tconst onParentAbort = () => controller.abort();\n\toptions.signal?.addEventListener(\"abort\", onParentAbort, { once: true });\n\tif (options.signal?.aborted) controller.abort();\n\ttry {\n\t\tconst abortError = () => {\n\t\t\tconst error = new Error(\"The operation was aborted\");\n\t\t\terror.name = \"AbortError\";\n\t\t\treturn error;\n\t\t};\n\t\treturn await Promise.race([\n\t\t\t(async () => {\n\t\t\t\tconst response = await options.fetchImpl(url, {\n\t\t\t\t\theaders: options.headers,\n\t\t\t\t\tsignal: controller.signal,\n\t\t\t\t});\n\t\t\t\tif (!response.ok) return { ok: false as const, status: response.status };\n\t\t\t\treturn { ok: true as const, value: await response.json() };\n\t\t\t})(),\n\t\t\tnew Promise<never>((_, reject) => {\n\t\t\t\tcontroller.signal.addEventListener(\"abort\", () => reject(abortError()), { once: true });\n\t\t\t\tif (controller.signal.aborted) reject(abortError());\n\t\t\t}),\n\t\t]);\n\t} catch {\n\t\treturn { ok: false };\n\t} finally {\n\t\tclearTimeout(timer);\n\t\toptions.signal?.removeEventListener(\"abort\", onParentAbort);\n\t}\n}\n\n/**\n * Load the official overlay. Network only when allowNetwork is true.\n * Fetches providers.json, then providers/{id}.json for stored-credential providers.\n * Successful shards replace that provider only; failed shards keep cache/bundled rows.\n * All requested shards failed → cache, then bundled. Never writes a worse cache. Never throws.\n */\nexport async function loadOfficialCatalog(\n\toptions: LoadOfficialCatalogOptions = {},\n): Promise<OfficialCatalogLoadResult> {\n\tconst cachePath = options.cachePath;\n\t// Cache-only: prefer the on-disk cache and skip parsing bundled models.json.\n\tif (!options.allowNetwork) {\n\t\treturn fallbackCatalog(options.bundled, cachePath);\n\t}\n\n\tconst bundled = resolveBundledCatalog(options.bundled);\n\tconst timeoutMs = options.timeoutMs ?? OFFICIAL_CATALOG_TIMEOUT_MS;\n\tconst fetchImpl = options.fetchImpl ?? fetch;\n\tconst headers = {\n\t\taccept: \"application/json\",\n\t\t\"User-Agent\": getPiUserAgent(VERSION),\n\t};\n\tconst fetchOptions = { timeoutMs, signal: options.signal, fetchImpl, headers };\n\tconst unavailable = (): OfficialCatalogLoadResult => ({\n\t\t...fallbackCatalog(bundled, cachePath),\n\t\terrors: Object.fromEntries(\n\t\t\t(options.providerIds ?? []).map((id) => [id, \"Published catalog unavailable; using cached metadata\"]),\n\t\t),\n\t});\n\tlet base = options.url ?? officialCatalogBaseUrl();\n\tlet manifest: Record<string, unknown> | undefined;\n\t// Existing custom mirrors remain compatible with the v1 index/shard format.\n\tif (!options.url && !process.env.LUNR_OFFICIAL_CATALOG_URL) {\n\t\tconst result = await fetchJson(`${VERSIONED_CATALOG_URL}/publication.json`, fetchOptions);\n\t\tif (\n\t\t\tresult.ok &&\n\t\t\tisRecord(result.value) &&\n\t\t\tresult.value.version === 2 &&\n\t\t\ttypeof result.value.revision === \"string\" &&\n\t\t\t/^sha256-[a-f0-9]{64}$/.test(result.value.revision) &&\n\t\t\tisRecord(result.value.shards) &&\n\t\t\tparseProviderIndex(result.value.providers)\n\t\t) {\n\t\t\tmanifest = result.value;\n\t\t\tbase = `${VERSIONED_CATALOG_URL}/snapshots/${result.value.revision}`;\n\t\t}\n\t}\n\n\ttry {\n\t\tconst indexResult = manifest\n\t\t\t? { ok: true as const, value: manifest.providers }\n\t\t\t: await fetchJson(officialCatalogUrlFor(\"providers.json\", base), fetchOptions);\n\t\tif (!indexResult.ok) return unavailable();\n\t\tconst index = parseProviderIndex(indexResult.value);\n\t\tif (!index) return unavailable();\n\n\t\tconst wanted = new Set(index);\n\t\tconst requested = options.providerIds ?? [];\n\t\tconst shardIds = requested.filter((providerId) => wanted.has(providerId));\n\t\tif (shardIds.length === 0) return fallbackCatalog(bundled, cachePath);\n\n\t\tconst replacements = new Map<string, OfficialModelEntry[]>();\n\t\tconst errors: Record<string, string> = {};\n\t\tawait Promise.all(\n\t\t\tshardIds.map(async (providerId) => {\n\t\t\t\tconst result = await fetchJson(\n\t\t\t\t\tofficialCatalogUrlFor(`providers/${encodeURIComponent(providerId)}.json`, base),\n\t\t\t\t\tfetchOptions,\n\t\t\t\t);\n\t\t\t\tif (!result.ok) {\n\t\t\t\t\terrors[providerId] = \"Catalog shard unavailable; using cached metadata\";\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (\n\t\t\t\t\tmanifest &&\n\t\t\t\t\t(manifest.shards as Record<string, unknown>)[providerId] !==\n\t\t\t\t\t\tcreateHash(\"sha256\").update(JSON.stringify(result.value)).digest(\"hex\")\n\t\t\t\t) {\n\t\t\t\t\terrors[providerId] = \"Catalog shard checksum mismatch; using cached metadata\";\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst parsed = parseOfficialCatalog(result.value);\n\t\t\t\tif (!parsed || parsed.models.length === 0 || parsed.models.some((model) => model.provider !== providerId)) {\n\t\t\t\t\terrors[providerId] = \"Invalid catalog shard; using cached metadata\";\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\treplacements.set(providerId, parsed.models);\n\t\t\t}),\n\t\t);\n\t\tif (replacements.size === 0) return { ...fallbackCatalog(bundled, cachePath), errors };\n\n\t\tconst catalog = mergeOfficialCatalogByProvider(\n\t\t\tofficialCatalogBase(bundled, cachePath),\n\t\t\treplacements,\n\t\t\ttypeof manifest?.generatedAt === \"string\" ? manifest.generatedAt : undefined,\n\t\t);\n\t\tif (cachePath) writeOfficialCatalogCache(catalog, cachePath);\n\t\treturn { catalog, source: \"github\", ...(Object.keys(errors).length ? { errors } : {}) };\n\t} catch {\n\t\treturn unavailable();\n\t}\n}\n"]}
@@ -33,13 +33,13 @@ export interface ApprovalRequest {
33
33
  toolName: string;
34
34
  /** "bash" (detail = command), "edit"/"write" (detail = path),
35
35
  * "edit-outside"/"write-outside" when path escapes cwd,
36
- * "swarm" for auto-activated agent swarms (detail = summary lines). */
36
+ * "subagent-full" for full-access children, or "large-subagent-launch" for aggregate confirmation. */
37
37
  action: string;
38
38
  detail: string;
39
- /** "swarm" when this is the agent-swarm approval prompt, "plan" for the
39
+ /** "large-subagent-launch" for aggregate child confirmation, "plan" for the
40
40
  * present_plan plan-approval prompt — the UI renders a dedicated dialog
41
41
  * for each instead of the generic tool dialog. */
42
- kind?: "swarm" | "plan";
42
+ kind?: "large-subagent-launch" | "plan";
43
43
  }
44
44
  export type ApprovalDecision = "once" | "session" | "reject";
45
45
  /** Handlers may return a bare decision string, a reject carrying user feedback
@@ -53,8 +53,8 @@ export type ApprovalResponse = ApprovalDecision | {
53
53
  feedback?: string;
54
54
  };
55
55
  export declare const NO_HANDLER_REASON = "Mutating tool blocked in manual mode: no approval channel available.";
56
- export declare const SWARM_REJECT_REASON = "Agent swarm rejected by user.";
57
- export declare const NO_SWARM_HANDLER_REASON = "Agent swarm blocked: no approval channel available.";
56
+ export declare const LARGE_SUBAGENT_LAUNCH_REJECT_REASON = "Large subagent launch rejected by user.";
57
+ export declare const NO_LARGE_SUBAGENT_LAUNCH_HANDLER_REASON = "Large subagent launch blocked: no approval channel available.";
58
58
  export declare function createPermissionContext(sessionId: string, mode?: PermissionMode): void;
59
59
  export declare function deletePermissionContext(sessionId: string): void;
60
60
  export declare function getPermissionMode(sessionId?: string): PermissionMode;
@@ -68,7 +68,7 @@ export declare const PLAN_PASS_THROUGH_TEXT = "Plan presented. The user will rev
68
68
  /** lunr: map an approval response to the model-facing present_plan result text. */
69
69
  export declare function planApprovalResultText(resp: ApprovalResponse): string;
70
70
  /**
71
- * lunr: present_plan approval request. Unlike the mutating-tool and swarm gates
71
+ * lunr: present_plan approval request. Unlike mutating-tool and aggregate launch gates
72
72
  * this fails OPEN when no approval handler is registered (or none is reachable,
73
73
  * e.g. a gateway turn without a chat context): headless sessions have no one to
74
74
  * show the dialog to, so the plan is presented and the user replies in chat
@@ -80,14 +80,13 @@ export declare function clearSessionApprovals(sessionId?: string): void;
80
80
  export declare function resetAllPermissionContexts(): void;
81
81
  /** Appended to the system prompt while auto mode is active. */
82
82
  export declare const AUTO_MODE_ADDENDUM = "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.";
83
- export declare const GLOBAL_AGENTS_FILE_WRITE_BLOCK_REASON = "The global AGENTS.md file is user-managed. The agent cannot change ~/.lunr/agent/AGENTS.md.";
83
+ export declare const GLOBAL_AGENTS_FILE_WRITE_BLOCK_REASON = "The agents instruction tree is user-managed. The agent cannot change ~/.lunr/agent/agents/.";
84
84
  export declare const MEMORY_FILE_DIRECT_WRITE_BLOCK_REASON = "Memory is model-managed through the memory tools. Do not directly change ~/.lunr/simple-memory/memory.md.";
85
85
  export interface GateOptions {
86
- /** True when the current turn started from an explicit /swarm prompt — the
87
- * user already asked for the swarm, so the swarm approval gate is skipped. */
88
- explicitSwarmTurn?: boolean;
86
+ /** Global preference for aggregate confirmation. Defaults to enabled. */
87
+ confirmLargeSubagentLaunches?: boolean;
89
88
  /** Assistant message that issued this tool call. Same-turn sibling SINGLE
90
- * `subagent` calls count toward the swarm threshold. */
89
+ * `subagent` calls count toward the aggregate threshold. */
91
90
  assistantMessage?: {
92
91
  content?: ReadonlyArray<{
93
92
  type?: string;
@@ -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 { getAgentDir } from \"../config.ts\";\nimport { isCodeRewriteMutating, planModeBlockReason } from \"./plan-mode.ts\";\nimport { effectiveSwarmCountForTurn, SWARM_APPROVAL_THRESHOLD } from \"./swarm.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 * \"swarm\" for auto-activated agent swarms (detail = summary lines). */\n\taction: string;\n\tdetail: string;\n\t/** \"swarm\" when this is the agent-swarm approval prompt, \"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?: \"swarm\" | \"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 SWARM_REJECT_REASON = \"Agent swarm rejected by user.\";\nexport const NO_SWARM_HANDLER_REASON = \"Agent swarm blocked: no approval channel available.\";\n/** Session-approval key for auto-activated agent swarms. */\nconst SWARM_ACTION = \"swarm\";\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 swarm prompt covers every sibling SINGLE `subagent` on the same assistant message. */\nconst turnSwarmDecisions = new WeakMap<object, { decision: ApprovalDecision; feedback?: string }>();\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 the mutating-tool and swarm 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 global AGENTS.md file is user-managed. The agent cannot change ~/.lunr/agent/AGENTS.md.\";\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.\";\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\tconst agentsPaths = [join(getAgentDir(), \"AGENTS.md\"), join(getAgentDir(), \"AGENTS.MD\")];\n\tif (agentsPaths.some((candidate) => normalize(target) === normalize(candidate))) {\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\treturn undefined;\n}\n\nfunction isMutatingTool(toolName: string): boolean {\n\treturn MUTATING_TOOLS.has(toolName);\n}\n\nfunction requiresManualApproval(toolName: string, input: Record<string, unknown>): boolean {\n\tif (isMutatingTool(toolName)) return true;\n\treturn toolName === \"code_rewrite\" && isCodeRewriteMutating(input);\n}\n\nexport interface GateOptions {\n\t/** True when the current turn started from an explicit /swarm prompt — the\n\t * user already asked for the swarm, so the swarm approval gate is skipped. */\n\texplicitSwarmTurn?: boolean;\n\t/** Assistant message that issued this tool call. Same-turn sibling SINGLE\n\t * `subagent` calls count toward the swarm 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 swarmTaskSummary(input: Record<string, unknown>, assistantMessage?: GateOptions[\"assistantMessage\"]): 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 * Agent-swarm gate. An auto-activated swarm (more than SWARM_APPROVAL_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 and explicit /swarm turns are pre-approved.\n * Fail-closed without an approval handler, same as the mutating-tool gate.\n */\nasync function gateSwarmCall(\n\tinput: Record<string, unknown>,\n\tctx: PermissionContext,\n\toptions?: GateOptions,\n): Promise<{ block: true; reason: string } | undefined> {\n\tif (ctx.mode === \"auto\") return undefined;\n\tif (options?.explicitSwarmTurn) return undefined;\n\tconst count = effectiveSwarmCountForTurn(input, options?.assistantMessage);\n\tif (count <= SWARM_APPROVAL_THRESHOLD) return undefined;\n\tif (ctx.approvals.has(SWARM_ACTION)) return undefined;\n\n\tconst turnKey = options?.assistantMessage;\n\tconst cached = turnKey ? turnSwarmDecisions.get(turnKey) : undefined;\n\tif (cached) {\n\t\tif (cached.decision === \"reject\") {\n\t\t\treturn { block: true, reason: cached.feedback ? `${SWARM_REJECT_REASON} ${cached.feedback}` : SWARM_REJECT_REASON };\n\t\t}\n\t\treturn undefined;\n\t}\n\n\tif (!approvalHandler) {\n\t\treturn { block: true, reason: NO_SWARM_HANDLER_REASON };\n\t}\n\n\tconst summary = swarmTaskSummary(input, options?.assistantMessage);\n\tlet resp: ApprovalResponse;\n\ttry {\n\t\tresp = await approvalHandler({\n\t\t\ttoolName: \"subagent\",\n\t\t\taction: SWARM_ACTION,\n\t\t\tdetail: summary ? `agent swarm (${count} subagents)\\n${summary}` : `agent swarm (${count} subagents)`,\n\t\t\tkind: \"swarm\",\n\t\t});\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : NO_SWARM_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) turnSwarmDecisions.set(turnKey, { decision, ...(feedback ? { feedback } : {}) });\n\tif (decision === \"session\") {\n\t\tctx.approvals.add(SWARM_ACTION);\n\t\treturn undefined;\n\t}\n\tif (decision === \"reject\") {\n\t\treturn { block: true, reason: feedback ? `${SWARM_REJECT_REASON} ${feedback}` : SWARM_REJECT_REASON };\n\t}\n\treturn undefined;\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// lunr: agent-swarm gate runs before the mode early-return — it applies in\n\t// yolo mode too (only auto mode bypasses it).\n\tif (toolName === \"subagent\") {\n\t\tconst swarmBlock = await gateSwarmCall(input, ctx, options);\n\t\tif (swarmBlock) return swarmBlock;\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)) 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 === \"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;AAiC9C,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;AAkE7G,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,CAqFtD","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 { 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\t\"settings_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.\";\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\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.startsWith(\"settings_\") && toolName !== \"settings_load\") return Object.keys(input).length > 0;\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"]}