@ashx-j/lunr 0.2.21 → 0.2.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (438) hide show
  1. package/CHANGELOG.md +1 -1
  2. package/README.md +20 -4
  3. package/dist/builtin-extensions/index.d.ts.map +1 -1
  4. package/dist/builtin-extensions/index.js +1 -0
  5. package/dist/builtin-extensions/index.js.map +1 -1
  6. package/dist/builtin-extensions/lunr-browser.d.ts +3 -0
  7. package/dist/builtin-extensions/lunr-browser.d.ts.map +1 -0
  8. package/dist/builtin-extensions/lunr-browser.js +56 -0
  9. package/dist/builtin-extensions/lunr-browser.js.map +1 -0
  10. package/dist/builtin-extensions/lunr-todos.d.ts.map +1 -1
  11. package/dist/builtin-extensions/lunr-todos.js +15 -0
  12. package/dist/builtin-extensions/lunr-todos.js.map +1 -1
  13. package/dist/builtin-extensions/pi-intercom/index.d.ts.map +1 -1
  14. package/dist/builtin-extensions/pi-intercom/index.js +3 -0
  15. package/dist/builtin-extensions/pi-intercom/index.js.map +1 -1
  16. package/dist/builtin-extensions/pi-subagents/src/extension/control-notices.d.ts +1 -1
  17. package/dist/builtin-extensions/pi-subagents/src/extension/control-notices.d.ts.map +1 -1
  18. package/dist/builtin-extensions/pi-subagents/src/extension/control-notices.js +5 -1
  19. package/dist/builtin-extensions/pi-subagents/src/extension/control-notices.js.map +1 -1
  20. package/dist/builtin-extensions/pi-subagents/src/extension/index.d.ts +2 -2
  21. package/dist/builtin-extensions/pi-subagents/src/extension/index.d.ts.map +1 -1
  22. package/dist/builtin-extensions/pi-subagents/src/extension/index.js +18 -5
  23. package/dist/builtin-extensions/pi-subagents/src/extension/index.js.map +1 -1
  24. package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.d.ts +4 -3
  25. package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.d.ts.map +1 -1
  26. package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.js +3 -0
  27. package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.js.map +1 -1
  28. package/dist/builtin-extensions/pi-subagents/src/intercom/communication.d.ts +17 -0
  29. package/dist/builtin-extensions/pi-subagents/src/intercom/communication.d.ts.map +1 -0
  30. package/dist/builtin-extensions/pi-subagents/src/intercom/communication.js +45 -0
  31. package/dist/builtin-extensions/pi-subagents/src/intercom/communication.js.map +1 -0
  32. package/dist/builtin-extensions/pi-subagents/src/intercom/intercom-bridge.d.ts.map +1 -1
  33. package/dist/builtin-extensions/pi-subagents/src/intercom/intercom-bridge.js +4 -11
  34. package/dist/builtin-extensions/pi-subagents/src/intercom/intercom-bridge.js.map +1 -1
  35. package/dist/builtin-extensions/pi-subagents/src/intercom/native-supervisor-channel.d.ts +4 -1
  36. package/dist/builtin-extensions/pi-subagents/src/intercom/native-supervisor-channel.d.ts.map +1 -1
  37. package/dist/builtin-extensions/pi-subagents/src/intercom/native-supervisor-channel.js +160 -51
  38. package/dist/builtin-extensions/pi-subagents/src/intercom/native-supervisor-channel.js.map +1 -1
  39. package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-ask.d.ts.map +1 -1
  40. package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-ask.js +5 -0
  41. package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-ask.js.map +1 -1
  42. package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-questions.d.ts +2 -0
  43. package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-questions.d.ts.map +1 -1
  44. package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-questions.js +3 -2
  45. package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-questions.js.map +1 -1
  46. package/dist/builtin-extensions/pi-subagents/src/runs/background/auto-drain.d.ts +1 -0
  47. package/dist/builtin-extensions/pi-subagents/src/runs/background/auto-drain.d.ts.map +1 -1
  48. package/dist/builtin-extensions/pi-subagents/src/runs/background/auto-drain.js +2 -1
  49. package/dist/builtin-extensions/pi-subagents/src/runs/background/auto-drain.js.map +1 -1
  50. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-wait.d.ts +1 -0
  51. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-wait.d.ts.map +1 -1
  52. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-wait.js +2 -0
  53. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-wait.js.map +1 -1
  54. package/dist/builtin-extensions/pi-subagents/src/runs/shared/pi-args.d.ts.map +1 -1
  55. package/dist/builtin-extensions/pi-subagents/src/runs/shared/pi-args.js +3 -0
  56. package/dist/builtin-extensions/pi-subagents/src/runs/shared/pi-args.js.map +1 -1
  57. package/dist/builtin-extensions/pi-subagents/src/runs/shared/subagent-control.d.ts +1 -0
  58. package/dist/builtin-extensions/pi-subagents/src/runs/shared/subagent-control.d.ts.map +1 -1
  59. package/dist/builtin-extensions/pi-subagents/src/runs/shared/subagent-control.js +3 -0
  60. package/dist/builtin-extensions/pi-subagents/src/runs/shared/subagent-control.js.map +1 -1
  61. package/dist/builtin-extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.d.ts.map +1 -1
  62. package/dist/builtin-extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.js +1 -1
  63. package/dist/builtin-extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.js.map +1 -1
  64. package/dist/builtin-extensions/pi-subagents/src/shared/types.d.ts +1 -0
  65. package/dist/builtin-extensions/pi-subagents/src/shared/types.d.ts.map +1 -1
  66. package/dist/builtin-extensions/pi-subagents/src/shared/types.js.map +1 -1
  67. package/dist/builtin-extensions/pi-subagents/src/tui/communication.d.ts +18 -0
  68. package/dist/builtin-extensions/pi-subagents/src/tui/communication.d.ts.map +1 -0
  69. package/dist/builtin-extensions/pi-subagents/src/tui/communication.js +47 -0
  70. package/dist/builtin-extensions/pi-subagents/src/tui/communication.js.map +1 -0
  71. package/dist/builtin-extensions/pi-web-access/index.d.ts.map +1 -1
  72. package/dist/builtin-extensions/pi-web-access/index.js +11 -7
  73. package/dist/builtin-extensions/pi-web-access/index.js.map +1 -1
  74. package/dist/cli/args.d.ts.map +1 -1
  75. package/dist/cli/args.js +2 -1
  76. package/dist/cli/args.js.map +1 -1
  77. package/dist/cli/install-cli.d.ts.map +1 -1
  78. package/dist/cli/install-cli.js +15 -45
  79. package/dist/cli/install-cli.js.map +1 -1
  80. package/dist/core/agent-session-runtime.d.ts +9 -0
  81. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  82. package/dist/core/agent-session-runtime.js +126 -29
  83. package/dist/core/agent-session-runtime.js.map +1 -1
  84. package/dist/core/agent-session.d.ts +3 -0
  85. package/dist/core/agent-session.d.ts.map +1 -1
  86. package/dist/core/agent-session.js +20 -2
  87. package/dist/core/agent-session.js.map +1 -1
  88. package/dist/core/browser/network.d.ts +9 -0
  89. package/dist/core/browser/network.d.ts.map +1 -0
  90. package/dist/core/browser/network.js +146 -0
  91. package/dist/core/browser/network.js.map +1 -0
  92. package/dist/core/browser/runtime.d.ts +24 -0
  93. package/dist/core/browser/runtime.d.ts.map +1 -0
  94. package/dist/core/browser/runtime.js +289 -0
  95. package/dist/core/browser/runtime.js.map +1 -0
  96. package/dist/core/browser/schema.d.ts +16 -0
  97. package/dist/core/browser/schema.d.ts.map +1 -0
  98. package/dist/core/browser/schema.js +36 -0
  99. package/dist/core/browser/schema.js.map +1 -0
  100. package/dist/core/browser/settings.d.ts +8 -0
  101. package/dist/core/browser/settings.d.ts.map +1 -0
  102. package/dist/core/browser/settings.js +30 -0
  103. package/dist/core/browser/settings.js.map +1 -0
  104. package/dist/core/browser/setup.d.ts +2 -0
  105. package/dist/core/browser/setup.d.ts.map +1 -0
  106. package/dist/core/browser/setup.js +16 -0
  107. package/dist/core/browser/setup.js.map +1 -0
  108. package/dist/core/customize.d.ts.map +1 -1
  109. package/dist/core/customize.js +15 -14
  110. package/dist/core/customize.js.map +1 -1
  111. package/dist/core/export-html/index.d.ts.map +1 -1
  112. package/dist/core/export-html/index.js +1 -1
  113. package/dist/core/export-html/index.js.map +1 -1
  114. package/dist/core/extensions/runner.d.ts +1 -0
  115. package/dist/core/extensions/runner.d.ts.map +1 -1
  116. package/dist/core/extensions/runner.js +1 -1
  117. package/dist/core/extensions/runner.js.map +1 -1
  118. package/dist/core/extensions/types.d.ts +1 -1
  119. package/dist/core/extensions/types.d.ts.map +1 -1
  120. package/dist/core/extensions/types.js.map +1 -1
  121. package/dist/core/install-features.d.ts.map +1 -1
  122. package/dist/core/install-features.js +10 -8
  123. package/dist/core/install-features.js.map +1 -1
  124. package/dist/core/memory-cap.d.ts.map +1 -1
  125. package/dist/core/memory-cap.js +5 -3
  126. package/dist/core/memory-cap.js.map +1 -1
  127. package/dist/core/model-tiers.d.ts.map +1 -1
  128. package/dist/core/model-tiers.js +9 -6
  129. package/dist/core/model-tiers.js.map +1 -1
  130. package/dist/core/permissions.d.ts.map +1 -1
  131. package/dist/core/permissions.js +9 -0
  132. package/dist/core/permissions.js.map +1 -1
  133. package/dist/core/plan-mode.d.ts.map +1 -1
  134. package/dist/core/plan-mode.js +3 -0
  135. package/dist/core/plan-mode.js.map +1 -1
  136. package/dist/core/process-registry.d.ts.map +1 -1
  137. package/dist/core/process-registry.js +6 -4
  138. package/dist/core/process-registry.js.map +1 -1
  139. package/dist/core/runtime-scope.d.ts +11 -0
  140. package/dist/core/runtime-scope.d.ts.map +1 -0
  141. package/dist/core/runtime-scope.js +3 -0
  142. package/dist/core/runtime-scope.js.map +1 -0
  143. package/dist/core/sdk.d.ts.map +1 -1
  144. package/dist/core/sdk.js +13 -0
  145. package/dist/core/sdk.js.map +1 -1
  146. package/dist/core/session-handoff.d.ts +35 -0
  147. package/dist/core/session-handoff.d.ts.map +1 -0
  148. package/dist/core/session-handoff.js +214 -0
  149. package/dist/core/session-handoff.js.map +1 -0
  150. package/dist/core/session-manager.d.ts +20 -0
  151. package/dist/core/session-manager.d.ts.map +1 -1
  152. package/dist/core/session-manager.js +184 -22
  153. package/dist/core/session-manager.js.map +1 -1
  154. package/dist/core/session-ownership.d.ts +28 -0
  155. package/dist/core/session-ownership.d.ts.map +1 -0
  156. package/dist/core/session-ownership.js +138 -0
  157. package/dist/core/session-ownership.js.map +1 -0
  158. package/dist/core/session-retention.d.ts.map +1 -1
  159. package/dist/core/session-retention.js +11 -2
  160. package/dist/core/session-retention.js.map +1 -1
  161. package/dist/core/settings-manager.d.ts +7 -0
  162. package/dist/core/settings-manager.d.ts.map +1 -1
  163. package/dist/core/settings-manager.js +18 -0
  164. package/dist/core/settings-manager.js.map +1 -1
  165. package/dist/core/slash-commands.d.ts.map +1 -1
  166. package/dist/core/slash-commands.js +2 -0
  167. package/dist/core/slash-commands.js.map +1 -1
  168. package/dist/core/system-prompt.d.ts.map +1 -1
  169. package/dist/core/system-prompt.js +5 -2
  170. package/dist/core/system-prompt.js.map +1 -1
  171. package/dist/core/todo-settings.d.ts +5 -0
  172. package/dist/core/todo-settings.d.ts.map +1 -0
  173. package/dist/core/todo-settings.js +7 -0
  174. package/dist/core/todo-settings.js.map +1 -0
  175. package/dist/core/tools/bash.d.ts.map +1 -1
  176. package/dist/core/tools/bash.js +4 -4
  177. package/dist/core/tools/bash.js.map +1 -1
  178. package/dist/core/tools/edit.d.ts.map +1 -1
  179. package/dist/core/tools/edit.js +5 -3
  180. package/dist/core/tools/edit.js.map +1 -1
  181. package/dist/core/tools/find.d.ts.map +1 -1
  182. package/dist/core/tools/find.js +4 -4
  183. package/dist/core/tools/find.js.map +1 -1
  184. package/dist/core/tools/grep.d.ts.map +1 -1
  185. package/dist/core/tools/grep.js +4 -4
  186. package/dist/core/tools/grep.js.map +1 -1
  187. package/dist/core/tools/ls.d.ts.map +1 -1
  188. package/dist/core/tools/ls.js +4 -4
  189. package/dist/core/tools/ls.js.map +1 -1
  190. package/dist/core/tools/read.d.ts.map +1 -1
  191. package/dist/core/tools/read.js +4 -4
  192. package/dist/core/tools/read.js.map +1 -1
  193. package/dist/core/tools/render-utils.d.ts +11 -2
  194. package/dist/core/tools/render-utils.d.ts.map +1 -1
  195. package/dist/core/tools/render-utils.js +31 -4
  196. package/dist/core/tools/render-utils.js.map +1 -1
  197. package/dist/core/tools/write.d.ts.map +1 -1
  198. package/dist/core/tools/write.js +4 -4
  199. package/dist/core/tools/write.js.map +1 -1
  200. package/dist/core/usage-service.d.ts.map +1 -1
  201. package/dist/core/usage-service.js +5 -3
  202. package/dist/core/usage-service.js.map +1 -1
  203. package/dist/gateway/adapters/discord.d.ts +12 -1
  204. package/dist/gateway/adapters/discord.d.ts.map +1 -1
  205. package/dist/gateway/adapters/discord.js +112 -17
  206. package/dist/gateway/adapters/discord.js.map +1 -1
  207. package/dist/gateway/adapters/telegram.d.ts +4 -2
  208. package/dist/gateway/adapters/telegram.d.ts.map +1 -1
  209. package/dist/gateway/adapters/telegram.js +34 -11
  210. package/dist/gateway/adapters/telegram.js.map +1 -1
  211. package/dist/gateway/agent-bridge.d.ts +14 -3
  212. package/dist/gateway/agent-bridge.d.ts.map +1 -1
  213. package/dist/gateway/agent-bridge.js +252 -60
  214. package/dist/gateway/agent-bridge.js.map +1 -1
  215. package/dist/gateway/approval.d.ts +1 -0
  216. package/dist/gateway/approval.d.ts.map +1 -1
  217. package/dist/gateway/approval.js +60 -18
  218. package/dist/gateway/approval.js.map +1 -1
  219. package/dist/gateway/authz.d.ts +2 -0
  220. package/dist/gateway/authz.d.ts.map +1 -1
  221. package/dist/gateway/authz.js +13 -0
  222. package/dist/gateway/authz.js.map +1 -1
  223. package/dist/gateway/buttons.d.ts +3 -1
  224. package/dist/gateway/buttons.d.ts.map +1 -1
  225. package/dist/gateway/buttons.js +18 -3
  226. package/dist/gateway/buttons.js.map +1 -1
  227. package/dist/gateway/command.d.ts.map +1 -1
  228. package/dist/gateway/command.js +49 -4
  229. package/dist/gateway/command.js.map +1 -1
  230. package/dist/gateway/commands.d.ts.map +1 -1
  231. package/dist/gateway/commands.js +18 -3
  232. package/dist/gateway/commands.js.map +1 -1
  233. package/dist/gateway/config.d.ts +5 -0
  234. package/dist/gateway/config.d.ts.map +1 -1
  235. package/dist/gateway/config.js +5 -0
  236. package/dist/gateway/config.js.map +1 -1
  237. package/dist/gateway/conversations.d.ts +14 -0
  238. package/dist/gateway/conversations.d.ts.map +1 -0
  239. package/dist/gateway/conversations.js +30 -0
  240. package/dist/gateway/conversations.js.map +1 -0
  241. package/dist/gateway/download.d.ts +2 -0
  242. package/dist/gateway/download.d.ts.map +1 -0
  243. package/dist/gateway/download.js +36 -0
  244. package/dist/gateway/download.js.map +1 -0
  245. package/dist/gateway/index.d.ts.map +1 -1
  246. package/dist/gateway/index.js +85 -26
  247. package/dist/gateway/index.js.map +1 -1
  248. package/dist/gateway/mobile-commands.d.ts +24 -0
  249. package/dist/gateway/mobile-commands.d.ts.map +1 -0
  250. package/dist/gateway/mobile-commands.js +422 -0
  251. package/dist/gateway/mobile-commands.js.map +1 -0
  252. package/dist/gateway/presenter.d.ts +16 -0
  253. package/dist/gateway/presenter.d.ts.map +1 -0
  254. package/dist/gateway/presenter.js +210 -0
  255. package/dist/gateway/presenter.js.map +1 -0
  256. package/dist/gateway/router.d.ts +1 -0
  257. package/dist/gateway/router.d.ts.map +1 -1
  258. package/dist/gateway/router.js +32 -3
  259. package/dist/gateway/router.js.map +1 -1
  260. package/dist/gateway/service.d.ts +46 -0
  261. package/dist/gateway/service.d.ts.map +1 -0
  262. package/dist/gateway/service.js +395 -0
  263. package/dist/gateway/service.js.map +1 -0
  264. package/dist/gateway/setup.d.ts +4 -0
  265. package/dist/gateway/setup.d.ts.map +1 -0
  266. package/dist/gateway/setup.js +146 -0
  267. package/dist/gateway/setup.js.map +1 -0
  268. package/dist/gateway/types.d.ts +4 -2
  269. package/dist/gateway/types.d.ts.map +1 -1
  270. package/dist/gateway/types.js.map +1 -1
  271. package/dist/index.d.ts +2 -0
  272. package/dist/index.d.ts.map +1 -1
  273. package/dist/index.js +2 -0
  274. package/dist/index.js.map +1 -1
  275. package/dist/main.d.ts.map +1 -1
  276. package/dist/main.js +2 -1
  277. package/dist/main.js.map +1 -1
  278. package/dist/modes/interactive/components/assistant-message.d.ts +11 -2
  279. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  280. package/dist/modes/interactive/components/assistant-message.js +53 -16
  281. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  282. package/dist/modes/interactive/components/copyable-text.d.ts +31 -0
  283. package/dist/modes/interactive/components/copyable-text.d.ts.map +1 -0
  284. package/dist/modes/interactive/components/copyable-text.js +165 -0
  285. package/dist/modes/interactive/components/copyable-text.js.map +1 -0
  286. package/dist/modes/interactive/components/custom-entry.d.ts +1 -0
  287. package/dist/modes/interactive/components/custom-entry.d.ts.map +1 -1
  288. package/dist/modes/interactive/components/custom-entry.js +8 -0
  289. package/dist/modes/interactive/components/custom-entry.js.map +1 -1
  290. package/dist/modes/interactive/components/custom-message.d.ts +1 -0
  291. package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
  292. package/dist/modes/interactive/components/custom-message.js +8 -0
  293. package/dist/modes/interactive/components/custom-message.js.map +1 -1
  294. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  295. package/dist/modes/interactive/components/session-selector.js +16 -0
  296. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  297. package/dist/modes/interactive/components/settings-selector.d.ts +5 -0
  298. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  299. package/dist/modes/interactive/components/settings-selector.js +38 -0
  300. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  301. package/dist/modes/interactive/interactive-mode.d.ts +3 -0
  302. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  303. package/dist/modes/interactive/interactive-mode.js +151 -7
  304. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  305. package/dist/node-runtime/agent-session-services-NQ6GKOIK.js +49 -0
  306. package/dist/node-runtime/{builtin-extensions-JCOPAAB5.js → builtin-extensions-GVC6IFDU.js} +6 -5
  307. package/dist/node-runtime/{chunk-LTYWTR3V.js → chunk-2MI5OPMN.js} +17 -2
  308. package/dist/node-runtime/{chunk-W3CVH5RX.js → chunk-2TKODGBZ.js} +11 -6
  309. package/dist/node-runtime/chunk-4EULYYR4.js +62 -0
  310. package/dist/node-runtime/chunk-5BNJ4JUH.js +672 -0
  311. package/dist/node-runtime/{chunk-6N22HULO.js → chunk-5D7LC2ZQ.js} +7 -2
  312. package/dist/node-runtime/{chunk-KBKMCJDU.js → chunk-5ZQXRPMC.js} +19 -4
  313. package/dist/node-runtime/{chunk-6KDIOJL3.js → chunk-6427XAWG.js} +3 -3
  314. package/dist/node-runtime/{chunk-BOHIDQT4.js → chunk-6B2POMK7.js} +1 -1
  315. package/dist/node-runtime/{chunk-RNBHABBA.js → chunk-7QWNYZDI.js} +7 -0
  316. package/dist/node-runtime/chunk-AZJHNQKQ.js +205 -0
  317. package/dist/node-runtime/{chunk-A3KMVBZV.js → chunk-BBUVIEZB.js} +1 -10
  318. package/dist/node-runtime/chunk-BFNXONG3.js +521 -0
  319. package/dist/node-runtime/{chunk-IRPJXI6U.js → chunk-BX2RB477.js} +1 -1
  320. package/dist/node-runtime/chunk-CCCN2UCX.js +14 -0
  321. package/dist/node-runtime/{chunk-25I2BHAA.js → chunk-CSUZVNYE.js} +1 -1
  322. package/dist/node-runtime/{chunk-QZMODZQ2.js → chunk-E24EO34J.js} +2 -1
  323. package/dist/node-runtime/{chunk-2BUAYZ7K.js → chunk-EQ63ANHL.js} +422 -123
  324. package/dist/node-runtime/{chunk-GB2MGFLI.js → chunk-GJSAD4AB.js} +216 -201
  325. package/dist/node-runtime/{chunk-W3SILANP.js → chunk-GMHJCCEN.js} +8 -8
  326. package/dist/node-runtime/{chunk-DDWHZ633.js → chunk-GNN7H3B7.js} +1 -1
  327. package/dist/node-runtime/chunk-GS66LV4M.js +2830 -0
  328. package/dist/node-runtime/{chunk-6BEIBLQ3.js → chunk-H3XF4UVQ.js} +1 -1
  329. package/dist/node-runtime/chunk-H4K3JDRB.js +47 -0
  330. package/dist/node-runtime/{chunk-YMEAYRBE.js → chunk-HTFRRDSF.js} +2 -7
  331. package/dist/node-runtime/chunk-IMLCWLPI.js +9 -0
  332. package/dist/node-runtime/{chunk-Y5KOEMBH.js → chunk-IQIEU7SB.js} +9 -674
  333. package/dist/node-runtime/{chunk-OPEK5RRY.js → chunk-IVXYUAJE.js} +1 -1
  334. package/dist/node-runtime/{chunk-PDNXVXMD.js → chunk-IWOWXRWU.js} +58 -48
  335. package/dist/node-runtime/chunk-KKUTQQV7.js +144 -0
  336. package/dist/node-runtime/{chunk-AWVD5IEY.js → chunk-LMBNLFXQ.js} +23 -12
  337. package/dist/node-runtime/{chunk-7NBZ5P7I.js → chunk-NAY6UUQZ.js} +1 -1
  338. package/dist/node-runtime/chunk-OAR4TYZE.js +146 -0
  339. package/dist/node-runtime/{chunk-STERBGUB.js → chunk-OFKSVRV7.js} +2 -2
  340. package/dist/node-runtime/{chunk-JZQ7F36T.js → chunk-ORH324EP.js} +19 -3
  341. package/dist/node-runtime/{chunk-2SJB2AWP.js → chunk-PC2Z5TKZ.js} +3 -3
  342. package/dist/node-runtime/{chunk-SY2TFMLO.js → chunk-QDGKKKUM.js} +46 -151
  343. package/dist/node-runtime/chunk-R3K2F5GI.js +122 -0
  344. package/dist/node-runtime/chunk-RMQZU2YU.js +117 -0
  345. package/dist/node-runtime/{chunk-XI77KVKA.js → chunk-TDL7UWJ7.js} +283 -2999
  346. package/dist/node-runtime/{chunk-G6LRAP36.js → chunk-TQGPP4SC.js} +1 -1
  347. package/dist/node-runtime/chunk-UAEOTO52.js +119 -0
  348. package/dist/node-runtime/{chunk-VZR3NCM7.js → chunk-UAFLNHSH.js} +18 -14
  349. package/dist/node-runtime/{chunk-AY6CAJSL.js → chunk-UJOCPOMX.js} +6 -3
  350. package/dist/node-runtime/chunk-UP2XBVH5.js +40 -0
  351. package/dist/node-runtime/{chunk-WJVFOIB5.js → chunk-UQUCFAJ3.js} +1 -1
  352. package/dist/node-runtime/chunk-URD2SLIT.js +1019 -0
  353. package/dist/node-runtime/chunk-US544NN6.js +13 -0
  354. package/dist/node-runtime/chunk-UWPJL22I.js +341 -0
  355. package/dist/node-runtime/chunk-V2A7CEXK.js +355 -0
  356. package/dist/node-runtime/chunk-VJPTNWAP.js +708 -0
  357. package/dist/node-runtime/{chunk-WKDK4C5P.js → chunk-VSSXXL36.js} +38 -164
  358. package/dist/node-runtime/{chunk-4I23VTC4.js → chunk-VWCE2HSZ.js} +21 -124
  359. package/dist/node-runtime/{chunk-WLLDXJRT.js → chunk-WADV2VDS.js} +22 -1014
  360. package/dist/node-runtime/{chunk-GKLEQ3I4.js → chunk-XLTL257W.js} +126 -27
  361. package/dist/node-runtime/chunk-YPHAIRZT.js +10 -0
  362. package/dist/node-runtime/cli-runtime.js +2 -2
  363. package/dist/node-runtime/command-3JHHXOPX.js +45 -0
  364. package/dist/node-runtime/commands-2JVNFGMQ.js +36 -0
  365. package/dist/node-runtime/{commands-MV5KOZ64.js → commands-KAMO2T6P.js} +10 -10
  366. package/dist/node-runtime/config-RORQUQFG.js +20 -0
  367. package/dist/node-runtime/{customize-LF5VST47.js → customize-VFJV3U6A.js} +2 -1
  368. package/dist/node-runtime/{direct-tool-executor-BK7CLEBX.js → direct-tool-executor-YAVOLDFY.js} +8 -8
  369. package/dist/node-runtime/{export-html-TEXVV5RP.js → export-html-KBFVV63J.js} +4 -3
  370. package/dist/node-runtime/{extension-input-O4HSAEM4.js → extension-input-K24TVKVW.js} +4 -4
  371. package/dist/node-runtime/{extension-selector-X5FCX43D.js → extension-selector-SPNF7EDR.js} +4 -4
  372. package/dist/node-runtime/{extract-XLQSJN4V.js → extract-EQJE7FZZ.js} +2 -2
  373. package/dist/node-runtime/{gateway-BM6NLOH4.js → gateway-VFO6SFKK.js} +275 -994
  374. package/dist/node-runtime/{gemini-search-U7SUMPQA.js → gemini-search-35OCRFLN.js} +1 -1
  375. package/dist/node-runtime/{gemini-url-context-PXWCBQHK.js → gemini-url-context-UQY3PHHW.js} +2 -2
  376. package/dist/node-runtime/index.js +104 -65
  377. package/dist/node-runtime/{init-3C7Z24OI.js → init-X2LIUB2H.js} +3 -3
  378. package/dist/node-runtime/{install-cli-EXMJQESX.js → install-cli-C3CF7O7N.js} +21 -82
  379. package/dist/node-runtime/interactive-mode-LOM6AIF6.js +72 -0
  380. package/dist/node-runtime/{interactive-view-ILS6TAN5.js → interactive-view-IDSCPPK7.js} +8 -8
  381. package/dist/node-runtime/lunr-browser-YNW7FTYX.js +87 -0
  382. package/dist/node-runtime/{lunr-cron-4VHP4E4B.js → lunr-cron-BKHGNBKT.js} +19 -5
  383. package/dist/node-runtime/main.js +44 -31
  384. package/dist/node-runtime/{memory-cap-3S4XRLNP.js → memory-cap-EL3KL4JJ.js} +2 -1
  385. package/dist/node-runtime/mobile-commands-HMP25WBC.js +32 -0
  386. package/dist/node-runtime/model-runtime-PLQKAG4B.js +16 -0
  387. package/dist/node-runtime/{model-tiers-NJLHUEGK.js → model-tiers-OU3U5CZG.js} +2 -1
  388. package/dist/node-runtime/{package-manager-cli-N37546V5.js → package-manager-cli-VCK4E2RC.js} +22 -15
  389. package/dist/node-runtime/{pi-intercom-NV2LW6X7.js → pi-intercom-HBPK5HSJ.js} +4 -1
  390. package/dist/node-runtime/{pi-mcp-adapter-GUFZWW54.js → pi-mcp-adapter-E6WULBKF.js} +4 -4
  391. package/dist/node-runtime/{pi-subagents-6MUIFNDM.js → pi-subagents-FEUDLJOE.js} +201 -78
  392. package/dist/node-runtime/{pi-web-access-2CQGFLT2.js → pi-web-access-WTGMNZ32.js} +15 -15
  393. package/dist/node-runtime/process-registry-4FAKZQOL.js +31 -0
  394. package/dist/node-runtime/{proxy-modes-V6YVFH3C.js → proxy-modes-OSQCWRBI.js} +9 -9
  395. package/dist/node-runtime/rpc-entry.js +44 -31
  396. package/dist/node-runtime/{rpc-mode-W5ZTLTMZ.js → rpc-mode-P5ODXPEG.js} +2 -2
  397. package/dist/node-runtime/runtime-4VA6JKNF.js +373 -0
  398. package/dist/node-runtime/{runtime-bridges-2VQTLPOZ.js → runtime-bridges-3XUQ46XW.js} +6 -5
  399. package/dist/node-runtime/service-ISSP6VHE.js +36 -0
  400. package/dist/node-runtime/session-handoff-HC7R5E24.js +33 -0
  401. package/dist/node-runtime/{session-manager-E7AREDTV.js → session-manager-CFN4UFM2.js} +2 -1
  402. package/dist/node-runtime/{session-selector-FJ7M2AIX.js → session-selector-LHRMJOKT.js} +5 -4
  403. package/dist/node-runtime/{settings-manager-CUGAZWAB.js → settings-manager-UUZ6NUXI.js} +7 -2
  404. package/dist/node-runtime/setup-JBKOLJ6F.js +18 -0
  405. package/dist/node-runtime/setup-NRXVZBLJ.js +155 -0
  406. package/dist/node-runtime/{subagent-executor-MH4A7CCF.js → subagent-executor-MLUMBWCP.js} +22 -18
  407. package/dist/node-runtime/theme-U7IGOA7O.js +68 -0
  408. package/dist/node-runtime/trust-manager-MMISNCYO.js +17 -0
  409. package/dist/node-runtime/{update-cli-XTZMZGOL.js → update-cli-4TP25CNW.js} +7 -2
  410. package/dist/node-runtime/usage-service-LFB2SWYV.js +37 -0
  411. package/dist/node-runtime/{video-extract-OYT5WKS5.js → video-extract-OOZHR7SU.js} +2 -2
  412. package/dist/node-runtime/{youtube-extract-TQYKGFGS.js → youtube-extract-FNPAUNHU.js} +6 -6
  413. package/docs/browser.md +86 -0
  414. package/docs/extensions.md +2 -0
  415. package/docs/features.md +94 -16
  416. package/docs/interactive-startup.md +2 -1
  417. package/docs/sessions.md +10 -0
  418. package/docs/settings.md +1 -0
  419. package/docs/tui.md +2 -0
  420. package/docs/usage.md +16 -0
  421. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  422. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  423. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  424. package/examples/extensions/gondolin/package-lock.json +2 -2
  425. package/examples/extensions/gondolin/package.json +1 -1
  426. package/examples/extensions/sandbox/package-lock.json +2 -2
  427. package/examples/extensions/sandbox/package.json +1 -1
  428. package/examples/extensions/with-deps/package-lock.json +2 -2
  429. package/examples/extensions/with-deps/package.json +1 -1
  430. package/package.json +7 -4
  431. package/scripts/install-browser.mjs +20 -0
  432. package/dist/node-runtime/agent-session-services-C743TYQE.js +0 -37
  433. package/dist/node-runtime/chunk-VGYZ3APQ.js +0 -59
  434. package/dist/node-runtime/command-P4NYCJ2M.js +0 -13
  435. package/dist/node-runtime/interactive-mode-EVVBA64D.js +0 -59
  436. package/dist/node-runtime/{chunk-UWQYRSYQ.js → chunk-YJMMG7C6.js} +25 -25
  437. package/dist/node-runtime/{mcp-panel-IIGMXQGP.js → mcp-panel-KTTFXJZ4.js} +3 -3
  438. package/dist/node-runtime/{src-BPQFJR76.js → src-IVPNZ2BX.js} +9 -9
@@ -1,2913 +1,126 @@
1
1
  import { createRequire as __lunrRequire } from "node:module"; const require = __lunrRequire(import.meta.url);
2
2
  import {
3
- DEFAULT_THINKING_LEVEL,
4
- calculateContextTokens,
5
- collectEntriesForBranchSummary,
6
- compact,
7
- estimateContextTokens,
8
- estimateTokens,
9
- findInitialModel,
10
- generateBranchSummary,
11
- prepareCompaction,
12
- shouldCompact
13
- } from "./chunk-STERBGUB.js";
14
- import {
15
- DefaultResourceLoader,
16
- ExtensionRunner,
17
- createSyntheticSourceInfo,
18
- emitSessionShutdownEvent,
19
- expandPromptTemplate,
20
- formatSkillsForPrompt
21
- } from "./chunk-Y5KOEMBH.js";
22
- import {
23
- stripFrontmatter
24
- } from "./chunk-QFWG2RVL.js";
25
- import {
26
- createAllToolDefinitions,
27
- createLocalBashOperations,
28
- createToolDefinitionFromAgentTool,
29
- wrapToolDefinition
30
- } from "./chunk-WKDK4C5P.js";
31
- import {
32
- DEFAULT_MAX_BYTES,
33
- truncateTail
34
- } from "./chunk-53YJI7JU.js";
35
- import {
36
- stripAnsi
37
- } from "./chunk-KBKMCJDU.js";
38
- import {
39
- getShellConfig,
40
- sanitizeBinaryOutput
41
- } from "./chunk-CSFI6YXL.js";
42
- import {
43
- SettingsManager,
44
- require_proper_lockfile
45
- } from "./chunk-WLLDXJRT.js";
46
- import {
47
- CURRENT_SESSION_VERSION,
48
- SessionManager,
49
- getDefaultSessionDir,
50
- getLatestCompactionEntry
51
- } from "./chunk-GKLEQ3I4.js";
52
- import {
53
- convertToLlm
54
- } from "./chunk-FVDOXRUD.js";
55
- import {
56
- clearPlanUsageCache
57
- } from "./chunk-LTYWTR3V.js";
58
- import {
59
- gateToolCall
60
- } from "./chunk-6N22HULO.js";
61
- import {
62
- isUserInstructionsPath,
63
- loadSelectedUserInstructions
64
- } from "./chunk-M3LZLQW2.js";
65
- import {
66
- measureStartup,
67
- time
68
- } from "./chunk-PVCDKGR6.js";
69
- import {
70
- MEMORY_TOOL_NAMES
71
- } from "./chunk-AY6CAJSL.js";
72
- import {
73
- getThemeByName,
74
- theme
75
- } from "./chunk-RNBHABBA.js";
76
- import {
77
- CONFIG_DIR_NAME,
78
- VERSION,
79
- getAgentDir,
80
- getDocsPath,
81
- getExamplesPath,
82
- getPackageDir,
83
- getReadmePath,
84
- normalizePath,
85
- resolvePath
86
- } from "./chunk-FQMM2EZ2.js";
87
- import {
88
- __toESM
89
- } from "./chunk-BRJX2PRC.js";
90
-
91
- // packages/coding-agent/dist/core/agent-session-services.js
92
- import { join as join14 } from "node:path";
93
-
94
- // packages/coding-agent/dist/core/model-runtime.js
95
- import { dirname as dirname5, join as join7 } from "node:path";
96
- import { createModels, lazyStream as lazyStream2, ModelsError } from "@ashx-j/lunr-ai";
97
- import * as builtinProviderCatalog from "@ashx-j/lunr-ai/providers/all";
98
-
99
- // packages/coding-agent/dist/core/auth-storage.js
100
- var import_proper_lockfile = __toESM(require_proper_lockfile(), 1);
101
- import { chmodSync, existsSync, mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync } from "fs";
102
- import { dirname, join } from "path";
103
-
104
- // packages/coding-agent/dist/core/resolve-config-value.js
105
- import { execSync, spawnSync } from "child_process";
106
- var commandResultCache = /* @__PURE__ */ new Map(), ENV_VAR_NAME_RE = /^[A-Za-z_][A-Za-z0-9_]*$/, ENV_VAR_NAME_PREFIX_RE = /^[A-Za-z_][A-Za-z0-9_]*/;
107
- function appendLiteral(parts, value) {
108
- if (!value)
109
- return;
110
- let previousPart = parts[parts.length - 1];
111
- if (previousPart?.type === "literal") {
112
- previousPart.value += value;
113
- return;
114
- }
115
- parts.push({ type: "literal", value });
116
- }
117
- function parseConfigValueTemplate(config) {
118
- let parts = [], index = 0;
119
- for (; index < config.length; ) {
120
- let dollarIndex = config.indexOf("$", index);
121
- if (dollarIndex < 0) {
122
- appendLiteral(parts, config.slice(index));
123
- break;
124
- }
125
- appendLiteral(parts, config.slice(index, dollarIndex));
126
- let nextChar = config[dollarIndex + 1];
127
- if (nextChar === "$" || nextChar === "!") {
128
- appendLiteral(parts, nextChar), index = dollarIndex + 2;
129
- continue;
130
- }
131
- if (nextChar === "{") {
132
- let endIndex = config.indexOf("}", dollarIndex + 2);
133
- if (endIndex < 0) {
134
- appendLiteral(parts, "$"), index = dollarIndex + 1;
135
- continue;
136
- }
137
- let name = config.slice(dollarIndex + 2, endIndex);
138
- ENV_VAR_NAME_RE.test(name) ? parts.push({ type: "env", name }) : appendLiteral(parts, config.slice(dollarIndex, endIndex + 1)), index = endIndex + 1;
139
- continue;
140
- }
141
- let match = config.slice(dollarIndex + 1).match(ENV_VAR_NAME_PREFIX_RE);
142
- if (match) {
143
- parts.push({ type: "env", name: match[0] }), index = dollarIndex + 1 + match[0].length;
144
- continue;
145
- }
146
- appendLiteral(parts, "$"), index = dollarIndex + 1;
147
- }
148
- return parts;
149
- }
150
- function parseConfigValueReference(config) {
151
- return config.startsWith("!") ? { type: "command", config } : { type: "template", parts: parseConfigValueTemplate(config) };
152
- }
153
- function resolveEnvConfigValue(name, env) {
154
- return env?.[name] || process.env[name] || void 0;
155
- }
156
- function getTemplateEnvVarNames(parts) {
157
- let names = [];
158
- for (let part of parts)
159
- part.type !== "env" || names.includes(part.name) || names.push(part.name);
160
- return names;
161
- }
162
- function resolveTemplate(parts, env) {
163
- let resolved = "";
164
- for (let part of parts) {
165
- if (part.type === "literal") {
166
- resolved += part.value;
167
- continue;
168
- }
169
- let envValue = resolveEnvConfigValue(part.name, env);
170
- if (envValue === void 0)
171
- return;
172
- resolved += envValue;
173
- }
174
- return resolved;
175
- }
176
- function getConfigValueEnvVarNames(config) {
177
- let reference = parseConfigValueReference(config);
178
- return reference.type === "template" ? getTemplateEnvVarNames(reference.parts) : [];
179
- }
180
- function getMissingConfigValueEnvVarNames(config, env) {
181
- return getConfigValueEnvVarNames(config).filter((name) => resolveEnvConfigValue(name, env) === void 0);
182
- }
183
- function isCommandConfigValue(config) {
184
- return parseConfigValueReference(config).type === "command";
185
- }
186
- function isConfigValueConfigured(config, env) {
187
- return getMissingConfigValueEnvVarNames(config, env).length === 0;
188
- }
189
- function resolveConfigValue(config, env) {
190
- let reference = parseConfigValueReference(config);
191
- return reference.type === "command" ? executeCommand(reference.config) : resolveTemplate(reference.parts, env);
192
- }
193
- function executeWithConfiguredShell(command) {
194
- try {
195
- let { shell, args, commandTransport } = getShellConfig(), commandFromStdin = commandTransport === "stdin", result = spawnSync(shell, commandFromStdin ? args : [...args, command], {
196
- encoding: "utf-8",
197
- input: commandFromStdin ? command : void 0,
198
- timeout: 1e4,
199
- stdio: [commandFromStdin ? "pipe" : "ignore", "pipe", "ignore"],
200
- shell: !1,
201
- windowsHide: !0
202
- });
203
- return result.error ? result.error.code === "ENOENT" ? { executed: !1, value: void 0 } : { executed: !0, value: void 0 } : result.status !== 0 ? { executed: !0, value: void 0 } : { executed: !0, value: (result.stdout ?? "").trim() || void 0 };
204
- } catch {
205
- return { executed: !1, value: void 0 };
206
- }
207
- }
208
- function executeWithDefaultShell(command) {
209
- try {
210
- return execSync(command, {
211
- encoding: "utf-8",
212
- timeout: 1e4,
213
- stdio: ["ignore", "pipe", "ignore"]
214
- }).trim() || void 0;
215
- } catch {
216
- return;
217
- }
218
- }
219
- function executeCommandUncached(commandConfig) {
220
- let command = commandConfig.slice(1);
221
- return process.platform === "win32" ? (() => {
222
- let configuredResult = executeWithConfiguredShell(command);
223
- return configuredResult.executed ? configuredResult.value : executeWithDefaultShell(command);
224
- })() : executeWithDefaultShell(command);
225
- }
226
- function executeCommand(commandConfig) {
227
- if (commandResultCache.has(commandConfig))
228
- return commandResultCache.get(commandConfig);
229
- let result = executeCommandUncached(commandConfig);
230
- return commandResultCache.set(commandConfig, result), result;
231
- }
232
- function resolveConfigValueUncached(config, env) {
233
- let reference = parseConfigValueReference(config);
234
- return reference.type === "command" ? executeCommandUncached(reference.config) : resolveTemplate(reference.parts, env);
235
- }
236
- function resolveConfigValueOrThrow(config, description, env) {
237
- let resolvedValue = resolveConfigValueUncached(config, env);
238
- if (resolvedValue !== void 0)
239
- return resolvedValue;
240
- let reference = parseConfigValueReference(config);
241
- if (reference.type === "command")
242
- throw new Error(`Failed to resolve ${description} from shell command: ${reference.config.slice(1)}`);
243
- if (reference.type === "template") {
244
- let missingEnvVars = getMissingConfigValueEnvVarNames(config, env);
245
- if (missingEnvVars.length === 1)
246
- throw new Error(`Failed to resolve ${description} from environment variable: ${missingEnvVars[0]}`);
247
- if (missingEnvVars.length > 1)
248
- throw new Error(`Failed to resolve ${description} from environment variables: ${missingEnvVars.join(", ")}`);
249
- }
250
- throw new Error(`Failed to resolve ${description}`);
251
- }
252
- function resolveHeadersOrThrow(headers, description, env) {
253
- if (!headers)
254
- return;
255
- let resolved = {};
256
- for (let [key, value] of Object.entries(headers))
257
- resolved[key] = resolveConfigValueOrThrow(value, `${description} header "${key}"`, env);
258
- return Object.keys(resolved).length > 0 ? resolved : void 0;
259
- }
260
-
261
- // packages/coding-agent/dist/core/auth-storage.js
262
- var AUTH_FILE_WRITE_OPTIONS = { encoding: "utf-8", mode: 384 }, AUTH_LOCK_STALE_MS = 12e4;
263
- function writeAuthFileAtomic(authPath, contents) {
264
- let tmp = `${authPath}.${process.pid}.${Date.now()}.tmp`;
265
- writeFileSync(tmp, contents, AUTH_FILE_WRITE_OPTIONS);
266
- try {
267
- chmodSync(tmp, 384);
268
- } catch {
269
- }
270
- try {
271
- if (process.platform === "win32" && existsSync(authPath)) {
272
- writeFileSync(authPath, contents, AUTH_FILE_WRITE_OPTIONS), chmodSync(authPath, 384);
273
- return;
274
- }
275
- renameSync(tmp, authPath);
276
- try {
277
- chmodSync(authPath, 384);
278
- } catch {
279
- }
280
- } finally {
281
- try {
282
- unlinkSync(tmp);
283
- } catch {
284
- }
285
- }
286
- }
287
- var FileAuthStorageBackend = class {
288
- authPath;
289
- constructor(authPath = join(getAgentDir(), "auth.json")) {
290
- this.authPath = normalizePath(authPath);
291
- }
292
- ensureParentDir() {
293
- let dir = dirname(this.authPath);
294
- existsSync(dir) || mkdirSync(dir, { recursive: !0, mode: 448 });
295
- }
296
- ensureFileExists() {
297
- existsSync(this.authPath) || (writeFileSync(this.authPath, "{}", AUTH_FILE_WRITE_OPTIONS), chmodSync(this.authPath, 384));
298
- }
299
- acquireLockSyncWithRetry(path) {
300
- let lastError;
301
- for (let attempt = 1; attempt <= 10; attempt++)
302
- try {
303
- return import_proper_lockfile.default.lockSync(path, { realpath: !1, stale: AUTH_LOCK_STALE_MS });
304
- } catch (error) {
305
- if ((typeof error == "object" && error !== null && "code" in error ? String(error.code) : void 0) !== "ELOCKED" || attempt === 10)
306
- throw error;
307
- lastError = error;
308
- let start = Date.now();
309
- for (; Date.now() - start < 20; )
310
- ;
311
- }
312
- throw lastError ?? new Error("Failed to acquire auth storage lock");
313
- }
314
- withLock(fn) {
315
- this.ensureParentDir(), this.ensureFileExists();
316
- let release;
317
- try {
318
- release = this.acquireLockSyncWithRetry(this.authPath);
319
- let current = existsSync(this.authPath) ? readFileSync(this.authPath, "utf-8") : void 0, { result, next } = fn(current);
320
- return next !== void 0 && writeAuthFileAtomic(this.authPath, next), result;
321
- } finally {
322
- release && release();
323
- }
324
- }
325
- async withLockAsync(fn) {
326
- this.ensureParentDir(), this.ensureFileExists();
327
- let release, lockCompromised = !1, lockCompromisedError, throwIfCompromised = () => {
328
- if (lockCompromised)
329
- throw lockCompromisedError ?? new Error("Auth storage lock was compromised");
330
- };
331
- try {
332
- release = await import_proper_lockfile.default.lock(this.authPath, {
333
- retries: {
334
- retries: 10,
335
- factor: 2,
336
- minTimeout: 100,
337
- maxTimeout: 1e4,
338
- randomize: !0
339
- },
340
- stale: AUTH_LOCK_STALE_MS,
341
- onCompromised: (err) => {
342
- lockCompromised = !0, lockCompromisedError = err;
343
- }
344
- }), throwIfCompromised();
345
- let current = existsSync(this.authPath) ? readFileSync(this.authPath, "utf-8") : void 0, { result, next } = await fn(current);
346
- return throwIfCompromised(), next !== void 0 && writeAuthFileAtomic(this.authPath, next), throwIfCompromised(), result;
347
- } finally {
348
- if (release)
349
- try {
350
- await release();
351
- } catch {
352
- }
353
- }
354
- }
355
- }, InMemoryAuthStorageBackend = class {
356
- value;
357
- withLock(fn) {
358
- let { result, next } = fn(this.value);
359
- return next !== void 0 && (this.value = next), result;
360
- }
361
- async withLockAsync(fn) {
362
- let { result, next } = await fn(this.value);
363
- return next !== void 0 && (this.value = next), result;
364
- }
365
- }, AuthStorage = class _AuthStorage {
366
- data = {};
367
- storage;
368
- constructor(storage) {
369
- this.storage = storage, this.reload();
370
- }
371
- static create(authPath) {
372
- return new _AuthStorage(new FileAuthStorageBackend(authPath ?? join(getAgentDir(), "auth.json")));
373
- }
374
- static fromStorage(storage) {
375
- return new _AuthStorage(storage);
376
- }
377
- static inMemory(data = {}) {
378
- let storage = new InMemoryAuthStorageBackend();
379
- return storage.withLock(() => ({ result: void 0, next: JSON.stringify(data, null, 2) })), _AuthStorage.fromStorage(storage);
380
- }
381
- parseStorageData(content) {
382
- return content ? JSON.parse(content) : {};
383
- }
384
- /**
385
- * Reload credentials from storage.
386
- */
387
- reload() {
388
- let content;
389
- try {
390
- this.storage.withLock((current) => (content = current, { result: void 0 })), this.data = this.parseStorageData(content);
391
- } catch {
392
- }
393
- }
394
- async read(provider) {
395
- let credential = this.data[provider];
396
- return credential?.type !== "api_key" || credential.key === void 0 ? credential : { ...credential, key: resolveConfigValue(credential.key, credential.env) };
397
- }
398
- async modify(provider, fn) {
399
- return this.storage.withLockAsync(async (content) => {
400
- let currentData = this.parseStorageData(content), next = await fn(currentData[provider]);
401
- if (next === void 0)
402
- return this.data = currentData, { result: currentData[provider] };
403
- let merged = { ...currentData, [provider]: next };
404
- return this.data = merged, { result: next, next: JSON.stringify(merged, null, 2) };
405
- });
406
- }
407
- async delete(provider) {
408
- await this.storage.withLockAsync(async (content) => {
409
- let currentData = this.parseStorageData(content);
410
- return delete currentData[provider], this.data = currentData, { result: void 0, next: JSON.stringify(currentData, null, 2) };
411
- });
412
- }
413
- /** List credential metadata without resolving configured key values. */
414
- async list() {
415
- return Object.entries(this.data).map(([providerId, credential]) => ({ providerId, type: credential.type }));
416
- }
417
- };
418
- function readStoredCredential(providerId, authPath = join(getAgentDir(), "auth.json")) {
419
- try {
420
- return JSON.parse(readFileSync(normalizePath(authPath), "utf-8"))[providerId];
421
- } catch {
422
- return;
423
- }
424
- }
425
-
426
- // packages/coding-agent/dist/core/catalog-cache-scope.js
427
- import { createHash } from "node:crypto";
428
- function catalogCacheScope(provider, baseUrl, credential) {
429
- let identity = credential?.type === "oauth" ? typeof credential.accountId == "string" ? credential.accountId : credential.refresh || credential.access : credential?.key;
430
- return createHash("sha256").update(JSON.stringify([provider, baseUrl.replace(/\/+$/, ""), identity ?? null])).digest("hex");
431
- }
432
-
433
- // packages/coding-agent/dist/core/catalog-merge.js
434
- import { withOpenAiEffortMetadata, withXaiEffortMetadata } from "@ashx-j/lunr-ai";
435
-
436
- // packages/coding-agent/dist/core/official-catalog.js
437
- import { createHash as createHash2, randomUUID } from "node:crypto";
438
- import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, renameSync as renameSync2, unlinkSync as unlinkSync2, writeFileSync as writeFileSync2 } from "node:fs";
439
- import { dirname as dirname2, join as join2 } from "node:path";
440
- import { fileURLToPath } from "node:url";
441
-
442
- // packages/coding-agent/dist/utils/pi-user-agent.js
443
- function getPiUserAgent(version) {
444
- let runtime = process.versions.bun ? `bun/${process.versions.bun}` : `node/${process.version}`;
445
- return `pi/${version} (${process.platform}; ${runtime}; ${process.arch})`;
446
- }
447
-
448
- // packages/coding-agent/dist/core/official-catalog.js
449
- var OFFICIAL_CATALOG_DEFAULT_URL = "https://raw.githubusercontent.com/ashx-j/lunR/master/catalog", VERSIONED_CATALOG_URL = "https://raw.githubusercontent.com/ashx-j/lunR/model-catalog/catalog", OFFICIAL_CATALOG_TIMEOUT_MS = 4e3, OFFICIAL_CATALOG_CACHE_FILENAME = "official-catalog-cache.json", THINKING_LEVEL_KEYS = ["off", "minimal", "low", "medium", "high", "xhigh", "max"], META_KEYS = /* @__PURE__ */ new Set(["version", "updatedAt", "generatedAt", "sourceCommit", "providerCount", "modelCount"]), BUNDLED_OFFICIAL_CATALOG = {
450
- version: 1,
451
- updatedAt: "2026-08-15T00:00:00Z",
452
- models: [
453
- {
454
- id: "grok-4.6",
455
- name: "Grok 4.6",
456
- api: "openai-completions",
457
- provider: "xai",
458
- baseUrl: "https://api.x.ai/v1",
459
- reasoning: !0,
460
- input: ["text", "image"],
461
- cost: { input: 2, output: 6, cacheRead: 0.5, cacheWrite: 0 },
462
- contextWindow: 5e5,
463
- maxTokens: 5e5
464
- }
465
- ]
466
- };
467
- function officialCatalogCachePath(agentDir = getAgentDir()) {
468
- return join2(agentDir, OFFICIAL_CATALOG_CACHE_FILENAME);
469
- }
470
- function officialCatalogBaseUrl(override) {
471
- return ((override ?? process.env.LUNR_OFFICIAL_CATALOG_URL)?.trim() || OFFICIAL_CATALOG_DEFAULT_URL).replace(/\/+$/, "");
472
- }
473
- function officialCatalogUrlFor(path, base) {
474
- let normalized = path.replace(/^\/+/, "");
475
- return `${officialCatalogBaseUrl(base)}/${normalized}`;
476
- }
477
- function modelKey(provider, id) {
478
- return `${provider}/${id}`;
479
- }
480
- function isRecord(value) {
481
- return typeof value == "object" && value !== null && !Array.isArray(value);
482
- }
483
- function asFiniteNumber(value) {
484
- if (typeof value == "number" && Number.isFinite(value))
485
- return value;
486
- if (typeof value == "string" && value.trim()) {
487
- let parsed = Number(value);
488
- if (Number.isFinite(parsed))
489
- return parsed;
490
- }
491
- }
492
- function parseCost(value) {
493
- if (!isRecord(value))
494
- return;
495
- let input = asFiniteNumber(value.input), output = asFiniteNumber(value.output);
496
- if (!(input === void 0 || output === void 0))
497
- return {
498
- input,
499
- output,
500
- cacheRead: asFiniteNumber(value.cacheRead) ?? 0,
501
- cacheWrite: asFiniteNumber(value.cacheWrite) ?? 0,
502
- ...Array.isArray(value.tiers) ? {
503
- tiers: value.tiers.flatMap((tier) => {
504
- if (!isRecord(tier) || !(typeof tier.inputTokensAbove == "number" && tier.inputTokensAbove >= 0))
505
- return [];
506
- let rates = parseCost({
507
- input: tier.input,
508
- output: tier.output,
509
- cacheRead: tier.cacheRead,
510
- cacheWrite: tier.cacheWrite
511
- });
512
- return rates ? [{ ...rates, inputTokensAbove: tier.inputTokensAbove }] : [];
513
- })
514
- } : {}
515
- };
516
- }
517
- function parseInput(value) {
518
- if (!Array.isArray(value))
519
- return;
520
- let input = [];
521
- for (let entry of value)
522
- (entry === "text" || entry === "image") && input.push(entry);
523
- return input.length > 0 ? input : void 0;
524
- }
525
- function parseThinkingLevelMap(value) {
526
- if (!isRecord(value))
527
- return;
528
- let map = {}, any = !1;
529
- for (let level of THINKING_LEVEL_KEYS) {
530
- let mapped = value[level];
531
- (mapped === null || typeof mapped == "string") && (map[level] = mapped, any = !0);
532
- }
533
- return any ? map : void 0;
534
- }
535
- function parseHeaders(value) {
536
- if (!isRecord(value))
537
- return;
538
- let headers = {};
539
- for (let [name, headerValue] of Object.entries(value))
540
- typeof headerValue == "string" && (headers[name] = headerValue);
541
- return Object.keys(headers).length > 0 ? headers : void 0;
542
- }
543
- function parseOfficialEntry(value) {
544
- if (!isRecord(value))
545
- return;
546
- let id = typeof value.id == "string" ? value.id.trim() : "", provider = typeof value.provider == "string" ? value.provider.trim() : "";
547
- if (!id || !provider)
548
- return;
549
- let api = typeof value.api == "string" && value.api.trim() ? value.api.trim() : "openai-completions", name = typeof value.name == "string" && value.name.trim() ? value.name.trim() : id, baseUrl = typeof value.baseUrl == "string" ? value.baseUrl.trim() : "", cost = parseCost(value.cost) ?? { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, input = parseInput(value.input) ?? ["text"], compat = isRecord(value.compat) ? value.compat : void 0, thinkingLevelMap = parseThinkingLevelMap(value.thinkingLevelMap), headers = parseHeaders(value.headers);
550
- return {
551
- id,
552
- ...isRecord(value.catalog) && value.catalog.source === "provider" && Array.isArray(value.catalog.supplied) ? { catalog: value.catalog } : {},
553
- name,
554
- api,
555
- provider,
556
- baseUrl,
557
- reasoning: value.reasoning === !0,
558
- input,
559
- cost,
560
- contextWindow: asFiniteNumber(value.contextWindow) ?? 128e3,
561
- maxTokens: asFiniteNumber(value.maxTokens) ?? 8192,
562
- ...compat ? { compat } : {},
563
- ...thinkingLevelMap ? { thinkingLevelMap } : {},
564
- ...headers ? { headers } : {}
565
- };
566
- }
567
- function catalogFile(models, value) {
568
- let version = value ? asFiniteNumber(value.version) ?? 1 : 1, updatedAt = value && typeof value.updatedAt == "string" && value.updatedAt.trim() ? value.updatedAt : "";
569
- return { version, updatedAt, models };
570
- }
571
- function parseKeyedCatalog(value) {
572
- let models = [];
573
- for (let [key, entry] of Object.entries(value))
574
- if (!(META_KEYS.has(key) || !isRecord(entry))) {
575
- if (typeof entry.id == "string") {
576
- let parsed = parseOfficialEntry(entry);
577
- parsed && models.push(parsed);
578
- continue;
579
- }
580
- for (let [modelId, model] of Object.entries(entry)) {
581
- if (!isRecord(model))
582
- continue;
583
- let parsed = parseOfficialEntry({
584
- ...model,
585
- id: typeof model.id == "string" && model.id.trim() ? model.id : modelId,
586
- provider: typeof model.provider == "string" && model.provider.trim() ? model.provider : key
587
- });
588
- parsed && models.push(parsed);
589
- }
590
- }
591
- return models.length > 0 ? catalogFile(models, value) : void 0;
592
- }
593
- function parseOfficialCatalog(value) {
594
- if (isRecord(value)) {
595
- if (Array.isArray(value.models)) {
596
- let models = [];
597
- for (let entry of value.models) {
598
- let parsed = parseOfficialEntry(entry);
599
- parsed && models.push(parsed);
600
- }
601
- return catalogFile(models, value);
602
- }
603
- if (!("models" in value))
604
- return parseKeyedCatalog(value);
605
- }
606
- }
607
- function parseProviderIndex(value) {
608
- if (!(!Array.isArray(value) || !value.every((entry) => typeof entry == "string")))
609
- return value;
610
- }
611
- function readCatalogFile(path) {
612
- try {
613
- return existsSync2(path) ? parseOfficialCatalog(JSON.parse(readFileSync2(path, "utf-8"))) : void 0;
614
- } catch {
615
- return;
616
- }
617
- }
618
- function bundledCatalogCandidates() {
619
- let here = dirname2(fileURLToPath(new URL("../core/official-catalog.js", import.meta.url).href)), packageDir = getPackageDir();
620
- return [
621
- join2(packageDir, "dist", "catalog", "models.json"),
622
- join2(packageDir, "..", "..", "catalog", "models.json"),
623
- join2(here, "../../../../catalog/models.json"),
624
- join2(packageDir, "catalog", "models.json"),
625
- join2(here, "../catalog/models.json"),
626
- join2(here, "models.json"),
627
- join2(packageDir, "dist", "catalog", "official-models.json"),
628
- join2(packageDir, "..", "..", "catalog", "official-models.json"),
629
- join2(here, "../../../../catalog/official-models.json"),
630
- join2(here, "official-models.json"),
631
- join2(here, "../catalog/official-models.json")
632
- ];
633
- }
634
- function loadBundledOfficialCatalog() {
635
- for (let path of bundledCatalogCandidates()) {
636
- let parsed = readCatalogFile(path);
637
- if (parsed)
638
- return parsed;
639
- }
640
- return BUNDLED_OFFICIAL_CATALOG;
641
- }
642
- function loadCachedOfficialCatalog(cachePath) {
643
- if (cachePath)
644
- return readCatalogFile(cachePath);
645
- }
646
- function writeOfficialCatalogCache(catalog, cachePath) {
647
- let temporary = `${cachePath}.${randomUUID()}.tmp`;
648
- try {
649
- mkdirSync2(dirname2(cachePath), { recursive: !0, mode: 448 }), writeFileSync2(temporary, `${JSON.stringify(catalog, null, 2)}
650
- `, { encoding: "utf-8", mode: 384 }), renameSync2(temporary, cachePath);
651
- } catch {
652
- } finally {
653
- try {
654
- unlinkSync2(temporary);
655
- } catch {
656
- }
657
- }
658
- }
659
- function officialModelsByProvider(catalog) {
660
- let byProvider = /* @__PURE__ */ new Map();
661
- for (let model of catalog.models) {
662
- let list = byProvider.get(model.provider) ?? [];
663
- list.push(model), byProvider.set(model.provider, list);
664
- }
665
- return byProvider;
666
- }
667
- function mergeOfficialCatalogByProvider(base, replacements, updatedAt) {
668
- let byProvider = officialModelsByProvider(base);
669
- for (let [providerId, models] of replacements)
670
- byProvider.set(providerId, models);
671
- return {
672
- version: base.version || 1,
673
- updatedAt: updatedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
674
- models: [...byProvider.values()].flat()
675
- };
676
- }
677
- function officialCatalogBase(bundled, cachePath) {
678
- let cached = loadCachedOfficialCatalog(cachePath);
679
- return cached ? mergeOfficialCatalogByProvider(bundled, officialModelsByProvider(cached), cached.updatedAt) : bundled;
680
- }
681
- function preferOfficialCatalog(previous, next) {
682
- return next.source === "github" ? next : previous?.source === "github" ? { ...previous, errors: next.errors } : next;
683
- }
684
- function officialModelKeys(catalog) {
685
- return new Set(catalog.models.map((model) => modelKey(model.provider, model.id)));
686
- }
687
- var ZERO_COST = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
688
- function officialEntryToModel(entry, template) {
689
- return {
690
- catalog: entry.catalog,
691
- id: entry.id,
692
- name: entry.name,
693
- api: entry.api || template?.api || "openai-completions",
694
- provider: entry.provider,
695
- baseUrl: entry.baseUrl || template?.baseUrl || "",
696
- reasoning: entry.reasoning,
697
- input: entry.input.length > 0 ? entry.input : template?.input ?? ["text"],
698
- cost: entry.cost ?? template?.cost ?? ZERO_COST,
699
- contextWindow: entry.contextWindow,
700
- maxTokens: entry.maxTokens,
701
- compat: entry.compat ?? template?.compat,
702
- thinkingLevelMap: entry.thinkingLevelMap ?? template?.thinkingLevelMap,
703
- headers: entry.headers ?? template?.headers
704
- };
705
- }
706
- function resolveBundledCatalog(bundled) {
707
- return bundled || loadBundledOfficialCatalog();
708
- }
709
- function fallbackCatalog(bundled, cachePath) {
710
- let cached = loadCachedOfficialCatalog(cachePath);
711
- if (cached)
712
- return { catalog: cached, source: "cache" };
713
- let resolved = resolveBundledCatalog(bundled);
714
- return resolved.models.length > 0 ? { catalog: resolved, source: "bundled" } : { catalog: BUNDLED_OFFICIAL_CATALOG, source: "bundled" };
715
- }
716
- async function fetchJson(url, options) {
717
- let controller = new AbortController(), timer = setTimeout(() => controller.abort(), options.timeoutMs), onParentAbort = () => controller.abort();
718
- options.signal?.addEventListener("abort", onParentAbort, { once: !0 }), options.signal?.aborted && controller.abort();
719
- try {
720
- let abortError = () => {
721
- let error = new Error("The operation was aborted");
722
- return error.name = "AbortError", error;
723
- };
724
- return await Promise.race([
725
- (async () => {
726
- let response = await options.fetchImpl(url, {
727
- headers: options.headers,
728
- signal: controller.signal
729
- });
730
- return response.ok ? { ok: !0, value: await response.json() } : { ok: !1, status: response.status };
731
- })(),
732
- new Promise((_, reject) => {
733
- controller.signal.addEventListener("abort", () => reject(abortError()), { once: !0 }), controller.signal.aborted && reject(abortError());
734
- })
735
- ]);
736
- } catch {
737
- return { ok: !1 };
738
- } finally {
739
- clearTimeout(timer), options.signal?.removeEventListener("abort", onParentAbort);
740
- }
741
- }
742
- async function loadOfficialCatalog(options = {}) {
743
- let cachePath = options.cachePath;
744
- if (!options.allowNetwork)
745
- return fallbackCatalog(options.bundled, cachePath);
746
- let bundled = resolveBundledCatalog(options.bundled), timeoutMs = options.timeoutMs ?? OFFICIAL_CATALOG_TIMEOUT_MS, fetchImpl = options.fetchImpl ?? fetch, headers = {
747
- accept: "application/json",
748
- "User-Agent": getPiUserAgent(VERSION)
749
- }, fetchOptions = { timeoutMs, signal: options.signal, fetchImpl, headers }, unavailable = () => ({
750
- ...fallbackCatalog(bundled, cachePath),
751
- errors: Object.fromEntries((options.providerIds ?? []).map((id) => [id, "Published catalog unavailable; using cached metadata"]))
752
- }), base = options.url ?? officialCatalogBaseUrl(), manifest;
753
- if (!options.url && !process.env.LUNR_OFFICIAL_CATALOG_URL) {
754
- let result = await fetchJson(`${VERSIONED_CATALOG_URL}/publication.json`, fetchOptions);
755
- result.ok && isRecord(result.value) && result.value.version === 2 && typeof result.value.revision == "string" && /^sha256-[a-f0-9]{64}$/.test(result.value.revision) && isRecord(result.value.shards) && parseProviderIndex(result.value.providers) && (manifest = result.value, base = `${VERSIONED_CATALOG_URL}/snapshots/${result.value.revision}`);
756
- }
757
- try {
758
- let indexResult = manifest ? { ok: !0, value: manifest.providers } : await fetchJson(officialCatalogUrlFor("providers.json", base), fetchOptions);
759
- if (!indexResult.ok)
760
- return unavailable();
761
- let index = parseProviderIndex(indexResult.value);
762
- if (!index)
763
- return unavailable();
764
- let wanted = new Set(index), shardIds = (options.providerIds ?? []).filter((providerId) => wanted.has(providerId));
765
- if (shardIds.length === 0)
766
- return fallbackCatalog(bundled, cachePath);
767
- let replacements = /* @__PURE__ */ new Map(), errors = {};
768
- if (await Promise.all(shardIds.map(async (providerId) => {
769
- let result = await fetchJson(officialCatalogUrlFor(`providers/${encodeURIComponent(providerId)}.json`, base), fetchOptions);
770
- if (!result.ok) {
771
- errors[providerId] = "Catalog shard unavailable; using cached metadata";
772
- return;
773
- }
774
- if (manifest && manifest.shards[providerId] !== createHash2("sha256").update(JSON.stringify(result.value)).digest("hex")) {
775
- errors[providerId] = "Catalog shard checksum mismatch; using cached metadata";
776
- return;
777
- }
778
- let parsed = parseOfficialCatalog(result.value);
779
- if (!parsed || parsed.models.length === 0 || parsed.models.some((model) => model.provider !== providerId)) {
780
- errors[providerId] = "Invalid catalog shard; using cached metadata";
781
- return;
782
- }
783
- replacements.set(providerId, parsed.models);
784
- })), replacements.size === 0)
785
- return { ...fallbackCatalog(bundled, cachePath), errors };
786
- let catalog = mergeOfficialCatalogByProvider(officialCatalogBase(bundled, cachePath), replacements, typeof manifest?.generatedAt == "string" ? manifest.generatedAt : void 0);
787
- return cachePath && writeOfficialCatalogCache(catalog, cachePath), { catalog, source: "github", ...Object.keys(errors).length ? { errors } : {} };
788
- } catch {
789
- return unavailable();
790
- }
791
- }
792
-
793
- // packages/coding-agent/dist/core/catalog-merge.js
794
- function mergeCatalogLayers(args) {
795
- let byId = /* @__PURE__ */ new Map();
796
- for (let model of args.bakedIn)
797
- byId.set(model.id, model);
798
- for (let model of args.live ?? [])
799
- byId.set(model.id, model);
800
- for (let model of args.user ?? [])
801
- byId.set(model.id, model);
802
- for (let model of args.official ?? [])
803
- byId.set(model.id, model);
804
- let seen = /* @__PURE__ */ new Set(), result = [];
805
- for (let baked of args.bakedIn) {
806
- let merged = byId.get(baked.id);
807
- merged && (result.push(merged), seen.add(baked.id));
808
- }
809
- for (let model of [...args.live ?? [], ...args.user ?? [], ...args.official ?? []]) {
810
- if (seen.has(model.id))
811
- continue;
812
- let winner = byId.get(model.id);
813
- winner && (result.push(winner), seen.add(model.id));
814
- }
815
- let liveById = new Map((args.live ?? []).map((model) => [model.id, model])), pricedIds = new Set([...args.bakedIn, ...args.official ?? [], ...args.user ?? []].filter((model) => model.catalog?.pricing !== "unknown").map((model) => model.id));
816
- return result.map((model) => {
817
- let resolved = withXaiEffortMetadata(model);
818
- model.catalog?.supplied.includes("thinkingLevelMap") || (resolved = withOpenAiEffortMetadata(resolved));
819
- let live = liveById.get(model.id);
820
- if (!live?.catalog)
821
- return resolved;
822
- resolved = { ...resolved, catalog: { ...live.catalog } };
823
- for (let field of live.catalog.supplied)
824
- Object.assign(resolved, { [field]: live[field] });
825
- return (pricedIds.has(model.id) || live.catalog.supplied.includes("cost")) && delete resolved.catalog.pricing, resolved;
826
- });
827
- }
828
- var CatalogOverlaySource = class {
829
- official = /* @__PURE__ */ new Map();
830
- user = /* @__PURE__ */ new Map();
831
- live = /* @__PURE__ */ new Map();
832
- setOfficial(models) {
833
- this.official = groupByProvider(models);
834
- }
835
- setUser(models) {
836
- this.user = groupByProvider(models);
837
- }
838
- setLive(providerId, models) {
839
- this.live.set(providerId, [...models]);
840
- }
841
- officialFor(providerId) {
842
- return this.official.get(providerId) ?? [];
843
- }
844
- userFor(providerId) {
845
- return this.user.get(providerId) ?? [];
846
- }
847
- liveFor(providerId) {
848
- return this.live.get(providerId) ?? [];
849
- }
850
- /** Codex's complete account catalog is authoritative for picker availability only. */
851
- isAvailable(model) {
852
- if (model.catalog?.hidden)
853
- return !1;
854
- let live = this.liveFor(model.provider);
855
- return model.provider !== "openai-codex" || !live.length || live.some((row) => row.id === model.id && !row.catalog?.hidden);
856
- }
857
- };
858
- function groupByProvider(models) {
859
- let byProvider = /* @__PURE__ */ new Map();
860
- for (let model of models) {
861
- let list = byProvider.get(model.provider) ?? [];
862
- list.push(model), byProvider.set(model.provider, list);
863
- }
864
- return byProvider;
865
- }
866
- function withCatalogOverlay(provider, overlay) {
867
- let bakedIn = () => provider.getModels();
868
- return {
869
- ...provider,
870
- getModels: () => mergeCatalogLayers({
871
- bakedIn: bakedIn(),
872
- live: overlay.liveFor(provider.id),
873
- user: overlay.userFor(provider.id),
874
- official: overlay.officialFor(provider.id)
875
- })
876
- };
877
- }
878
- function formatCatalogRefreshSummary(input) {
879
- let parts = [];
880
- if (input.official?.source === "github") {
881
- let evicted = input.official.evictedUserRows > 0 ? `; replaced ${input.official.evictedUserRows} user-filled row` : "", plural = input.official.evictedUserRows === 1 ? "" : input.official.evictedUserRows > 0 ? "s" : "";
882
- parts.push(`Official catalog updated (${input.official.modelCount} models)${evicted}${plural}.`);
883
- }
884
- let refreshed = [], failed = [];
885
- for (let provider of input.providers)
886
- if (provider.status === "ok") {
887
- let added = provider.added ?? 0, total = provider.total ?? 0;
888
- refreshed.push(added > 0 ? `${provider.id} (+${added})` : `${provider.id} (${total})`);
889
- } else provider.status === "timeout" ? failed.push(`${provider.id} timed out (cached)`) : provider.status === "error" && failed.push(formatLiveProviderError(provider));
890
- return refreshed.length > 0 ? parts.push(`Refreshed ${refreshed.join(", ")}.`) : input.providers.some((provider) => provider.status === "ok") && parts.push("Refreshed model catalogs."), failed.length > 0 && parts.push(`${failed.join("; ")}.`), input.asked && input.asked.length > 0 && parts.push(`Asked for missing metadata on ${input.asked.join(", ")}.`), input.extraDefaults && input.extraDefaults > 0 && parts.push(`+${input.extraDefaults} more using defaults.`), input.ollama && parts.push(input.ollama), parts.length === 0 ? "Model catalogs refreshed." : parts.join(" ");
891
- }
892
- function formatLiveProviderError(provider) {
893
- return provider.id === "xai" && provider.error && /invalid_grant|refresh token revoked/i.test(provider.error) && !/timed out|aborted|cancelled|ECONN|ENOTFOUND|network/i.test(provider.error) ? "xai login expired (run /login xai)" : provider.error ? `${provider.id} failed (${provider.error})` : `${provider.id} failed`;
894
- }
895
- function knownModelKeys(bakedIn, official, user) {
896
- let keys = new Set(official);
897
- for (let key of user)
898
- keys.add(key);
899
- for (let model of bakedIn)
900
- keys.add(modelKey(model.provider, model.id));
901
- return keys;
902
- }
903
-
904
- // packages/coding-agent/dist/core/grok-cli-auth.js
905
- var import_proper_lockfile2 = __toESM(require_proper_lockfile(), 1);
906
- import { chmodSync as chmodSync2, existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync3, renameSync as renameSync3, unlinkSync as unlinkSync3, writeFileSync as writeFileSync3 } from "node:fs";
907
- import { homedir } from "node:os";
908
- import { dirname as dirname3, join as join3 } from "node:path";
909
- var XAI_PROVIDER_ID = "xai", XAI_GROK_CLI_CLIENT_ID = "b1a00492-073a-47ea-816f-4c329264a828", REFRESH_SKEW_MS = 300 * 1e3, AUTH_FILE_WRITE_OPTIONS2 = { encoding: "utf-8", mode: 384 };
910
- function grokHomeDir(grokHome) {
911
- if (grokHome)
912
- return grokHome;
913
- let fromEnv = process.env.GROK_HOME?.trim();
914
- return fromEnv || join3(homedir(), ".grok");
915
- }
916
- function grokAuthPath(grokHome) {
917
- return join3(grokHomeDir(grokHome), "auth.json");
918
- }
919
- function grokOidcEntryKey(clientId = XAI_GROK_CLI_CLIENT_ID) {
920
- return `https://auth.x.ai::${clientId}`;
921
- }
922
- function parseGrokExpiresAt(value) {
923
- if (typeof value == "number" && Number.isFinite(value) && value > 0)
924
- return value < 1e12 ? Math.round(value * 1e3) : Math.round(value);
925
- if (typeof value == "string" && value.trim()) {
926
- let numeric = Number(value);
927
- if (Number.isFinite(numeric) && numeric > 0)
928
- return numeric < 1e12 ? Math.round(numeric * 1e3) : Math.round(numeric);
929
- let parsed = Date.parse(value);
930
- if (Number.isFinite(parsed))
931
- return parsed;
932
- }
933
- }
934
- function formatGrokExpiresAt(expires) {
935
- return new Date(expires).toISOString();
936
- }
937
- function grokEntryToOAuth(entry) {
938
- if (!entry || typeof entry != "object" || Array.isArray(entry))
939
- return;
940
- let record = entry, access = typeof record.key == "string" ? record.key : void 0, refresh = typeof record.refresh_token == "string" ? record.refresh_token : void 0, expires = parseGrokExpiresAt(record.expires_at);
941
- if (!(!access || !refresh || expires === void 0))
942
- return { type: "oauth", access, refresh, expires };
943
- }
944
- function readGrokCliXaiOAuth(options = {}) {
945
- try {
946
- let raw = readFileSync3(grokAuthPath(options.grokHome), "utf-8"), parsed = JSON.parse(raw);
947
- return !parsed || typeof parsed != "object" || Array.isArray(parsed) ? void 0 : grokEntryToOAuth(parsed[grokOidcEntryKey()]);
948
- } catch {
949
- return;
950
- }
951
- }
952
- function hasGrokCliXaiAuth(options = {}) {
953
- return readGrokCliXaiOAuth(options) !== void 0;
954
- }
955
- function chooseXaiOAuth(lunr, grok) {
956
- if (lunr?.type === "api_key")
957
- return lunr;
958
- let lunrOAuth = lunr?.type === "oauth" ? lunr : void 0;
959
- if (lunrOAuth && grok) {
960
- if (lunrOAuth.refresh === grok.refresh)
961
- return grok.expires >= lunrOAuth.expires ? grok : lunrOAuth;
962
- let now = Date.now(), lunrLive = now < lunrOAuth.expires, grokLive = now < grok.expires;
963
- return grokLive && !lunrLive ? grok : lunrLive && !grokLive ? lunrOAuth : !lunrLive && !grokLive && grok.expires >= lunrOAuth.expires ? grok : lunrOAuth;
964
- }
965
- return grok ?? lunrOAuth ?? lunr;
966
- }
967
- function oauthRefreshFailed(error) {
968
- let parts = [], current = error, seen = /* @__PURE__ */ new Set();
969
- for (; current && typeof current == "object" && !seen.has(current); ) {
970
- if (seen.add(current), current instanceof Error) {
971
- parts.push(current.message), current = current.cause;
972
- continue;
973
- }
974
- break;
975
- }
976
- let chain = parts.join(" ");
977
- return /timed out|aborted|cancelled|ECONN|ENOTFOUND|network/i.test(chain) ? !1 : /invalid_grant|refresh token revoked/i.test(chain);
978
- }
979
- function shouldAdopt(lunr, chosen) {
980
- return !chosen || chosen.type !== "oauth" ? !1 : !lunr || lunr.type !== "oauth" ? !0 : lunr.access !== chosen.access || lunr.refresh !== chosen.refresh;
981
- }
982
- function writeAuthFileAtomic2(authPath, contents) {
983
- let tmp = `${authPath}.${process.pid}.${Date.now()}.tmp`;
984
- writeFileSync3(tmp, contents, AUTH_FILE_WRITE_OPTIONS2);
985
- try {
986
- chmodSync2(tmp, 384);
987
- } catch {
988
- }
989
- try {
990
- if (process.platform === "win32" && existsSync3(authPath)) {
991
- writeFileSync3(authPath, contents, AUTH_FILE_WRITE_OPTIONS2), chmodSync2(authPath, 384);
992
- return;
993
- }
994
- renameSync3(tmp, authPath);
995
- try {
996
- chmodSync2(authPath, 384);
997
- } catch {
998
- }
999
- } finally {
1000
- try {
1001
- unlinkSync3(tmp);
1002
- } catch {
1003
- }
1004
- }
1005
- }
1006
- function acquireGrokLock(authPath) {
1007
- let lastError;
1008
- for (let attempt = 1; attempt <= 10; attempt++)
1009
- try {
1010
- return import_proper_lockfile2.default.lockSync(authPath, { realpath: !1, stale: 12e4 });
1011
- } catch (error) {
1012
- if ((typeof error == "object" && error !== null && "code" in error ? String(error.code) : void 0) !== "ELOCKED" || attempt === 10)
1013
- throw error;
1014
- lastError = error;
1015
- let start = Date.now();
1016
- for (; Date.now() - start < 20; )
1017
- ;
1018
- }
1019
- throw lastError ?? new Error("Failed to acquire Grok CLI auth lock");
1020
- }
1021
- function writeGrokCliXaiOAuth(credential, options = {}) {
1022
- let authPath = grokAuthPath(options.grokHome);
1023
- if (options.onlyIfFileExists !== !1 && !existsSync3(authPath))
1024
- return !1;
1025
- let dir = dirname3(authPath);
1026
- existsSync3(dir) || mkdirSync3(dir, { recursive: !0, mode: 448 }), existsSync3(authPath) || writeAuthFileAtomic2(authPath, `{}
1027
- `);
1028
- let release;
1029
- try {
1030
- release = acquireGrokLock(authPath);
1031
- let data = {};
1032
- try {
1033
- let parsed = JSON.parse(readFileSync3(authPath, "utf-8"));
1034
- if (parsed && typeof parsed == "object" && !Array.isArray(parsed))
1035
- data = parsed;
1036
- else
1037
- return !1;
1038
- } catch {
1039
- return !1;
1040
- }
1041
- let key = grokOidcEntryKey(), previous = data[key] && typeof data[key] == "object" && !Array.isArray(data[key]) ? data[key] : {}, existing = grokEntryToOAuth(previous);
1042
- return existing && existing.refresh !== credential.refresh && existing.expires > credential.expires + REFRESH_SKEW_MS ? !1 : (data[key] = {
1043
- ...previous,
1044
- key: credential.access,
1045
- refresh_token: credential.refresh,
1046
- expires_at: formatGrokExpiresAt(credential.expires)
1047
- }, writeAuthFileAtomic2(authPath, `${JSON.stringify(data, null, 2)}
1048
- `), !0);
1049
- } finally {
1050
- if (release)
1051
- try {
1052
- release();
1053
- } catch {
1054
- }
1055
- }
1056
- }
1057
- function wrapXaiGrokCliCredentials(store, options = {}) {
1058
- let grokHome = options.grokHome;
1059
- return {
1060
- async read(providerId) {
1061
- let stored = await store.read(providerId);
1062
- if (providerId !== XAI_PROVIDER_ID || stored?.type === "api_key")
1063
- return stored;
1064
- let grok = readGrokCliXaiOAuth({ grokHome }), chosen = chooseXaiOAuth(stored, grok);
1065
- if (shouldAdopt(stored, chosen) && chosen?.type === "oauth")
1066
- try {
1067
- await store.modify(providerId, async (current) => {
1068
- if (current?.type === "api_key")
1069
- return;
1070
- let latestGrok = readGrokCliXaiOAuth({ grokHome }), latestChosen = chooseXaiOAuth(current, latestGrok);
1071
- if (shouldAdopt(current, latestChosen) && latestChosen?.type === "oauth")
1072
- return latestChosen;
1073
- });
1074
- } catch {
1075
- }
1076
- return chosen;
1077
- },
1078
- async list() {
1079
- let entries = new Map((await store.list()).map((entry) => [entry.providerId, entry]));
1080
- return !entries.has(XAI_PROVIDER_ID) && hasGrokCliXaiAuth({ grokHome }) && entries.set(XAI_PROVIDER_ID, { providerId: XAI_PROVIDER_ID, type: "oauth" }), [...entries.values()];
1081
- },
1082
- modify(providerId, fn) {
1083
- return providerId !== XAI_PROVIDER_ID ? store.modify(providerId, fn) : store.modify(providerId, async (lunrCurrent) => {
1084
- if (lunrCurrent?.type === "api_key")
1085
- return fn(lunrCurrent);
1086
- let grok = readGrokCliXaiOAuth({ grokHome }), chosen = chooseXaiOAuth(lunrCurrent, grok), next;
1087
- try {
1088
- next = await fn(chosen);
1089
- } catch (error) {
1090
- let retryGrok = readGrokCliXaiOAuth({ grokHome });
1091
- if (!(oauthRefreshFailed(error) && retryGrok && !(chosen?.type === "oauth" && retryGrok.refresh === chosen.refresh)))
1092
- throw error;
1093
- try {
1094
- next = await fn(retryGrok);
1095
- } catch {
1096
- throw error;
1097
- }
1098
- }
1099
- if (next?.type === "oauth")
1100
- try {
1101
- writeGrokCliXaiOAuth(next, { grokHome, onlyIfFileExists: !0 });
1102
- } catch {
1103
- }
1104
- return next;
1105
- });
1106
- },
1107
- delete(providerId) {
1108
- return store.delete(providerId);
1109
- }
1110
- };
1111
- }
1112
-
1113
- // packages/coding-agent/dist/core/live-catalog.js
1114
- import { isOpenAiChatModel, parseOpenAiGptVersion } from "@ashx-j/lunr-ai";
1115
- import { codexModelsUrl, resolveCodexCatalogVersion } from "@ashx-j/lunr-ai/catalog/codex";
1116
- import { normalizeCatalogPricing } from "@ashx-j/lunr-ai/catalog/metadata";
1117
-
1118
- // packages/coding-agent/dist/core/codex-catalog.js
1119
- import { parseCodexCatalog } from "@ashx-j/lunr-ai/catalog/codex";
1120
- function discoverCodexModels(payload, baseUrl) {
1121
- return parseCodexCatalog(payload, baseUrl).map((model) => ({
1122
- model,
1123
- supplied: {
1124
- name: model.catalog.supplied.includes("name"),
1125
- contextWindow: model.catalog.supplied.includes("contextWindow"),
1126
- maxTokens: model.catalog.supplied.includes("maxTokens"),
1127
- input: model.catalog.supplied.includes("input"),
1128
- cost: !1,
1129
- reasoning: model.catalog.supplied.includes("reasoning")
1130
- }
1131
- }));
1132
- }
1133
-
1134
- // packages/coding-agent/dist/core/live-catalog.js
1135
- var LIVE_CATALOG_TIMEOUT_MS = 4e3;
1136
- var DEFAULT_CONTEXT_WINDOW = 128e3, DEFAULT_MAX_TOKENS = 8192, LIVE_LIST_PROVIDER_IDS = [
1137
- "openai-codex",
1138
- "xai",
1139
- "openrouter",
1140
- "qwen-cloud",
1141
- "qwen-cloud-cn",
1142
- "groq",
1143
- "openai",
1144
- "deepseek"
1145
- ], LIVE_LIST_PROVIDER_SET = new Set(LIVE_LIST_PROVIDER_IDS);
1146
- var ZERO_COST2 = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, NONE_SUPPLIED = {
1147
- contextWindow: !1,
1148
- maxTokens: !1,
1149
- input: !1,
1150
- name: !1,
1151
- cost: !1,
1152
- reasoning: !1
1153
- };
1154
- function isRecord2(value) {
1155
- return typeof value == "object" && value !== null && !Array.isArray(value);
1156
- }
1157
- function asFiniteNumber2(value) {
1158
- if (typeof value == "number" && Number.isFinite(value))
1159
- return value;
1160
- if (typeof value == "string" && value.trim()) {
1161
- let parsed = Number(value);
1162
- if (Number.isFinite(parsed))
1163
- return parsed;
1164
- }
1165
- }
1166
- function roundCost(value) {
1167
- return Number(value.toFixed(6));
1168
- }
1169
- function modelsListUrl(baseUrl) {
1170
- return `${baseUrl.replace(/\/+$/u, "")}/models`;
1171
- }
1172
- function credentialAuthHeaders(credential) {
1173
- return credential ? credential.type === "api_key" && credential.key ? { Authorization: `Bearer ${credential.key}` } : credential.type === "oauth" && typeof credential.access == "string" && credential.access ? { Authorization: `Bearer ${credential.access}` } : {} : {};
1174
- }
1175
- function parseOpenAIModelsList(value) {
1176
- let entries = isRecord2(value) && Array.isArray(value.data) ? value.data : Array.isArray(value) ? value : [], rows = [];
1177
- for (let entry of entries) {
1178
- if (typeof entry == "string" && entry.trim()) {
1179
- rows.push({ id: entry.trim() });
1180
- continue;
1181
- }
1182
- isRecord2(entry) && typeof entry.id == "string" && entry.id.trim() && rows.push(entry);
1183
- }
1184
- return rows;
1185
- }
1186
- function firstBakedInModel(models) {
1187
- return models[0];
1188
- }
1189
- function selectLiveTemplate(providerId, id, bakedIn) {
1190
- let exact = bakedIn.find((model) => model.id === id);
1191
- if (exact)
1192
- return exact;
1193
- let version = parseOpenAiGptVersion(id);
1194
- if (providerId !== "openai" || !version || version.major < 5 || isOpenAiChatModel(id))
1195
- return firstBakedInModel(bakedIn);
1196
- let reasoning;
1197
- for (let model of bakedIn)
1198
- model.reasoning && parseOpenAiGptVersion(model.id) && (reasoning = model);
1199
- return reasoning ?? firstBakedInModel(bakedIn);
1200
- }
1201
- function uniqueApis(models) {
1202
- let seen = /* @__PURE__ */ new Set(), apis = [];
1203
- for (let model of models)
1204
- seen.has(model.api) || (seen.add(model.api), apis.push(model.api));
1205
- return apis;
1206
- }
1207
- function synthesizeLiveModel(id, template, raw = {}) {
1208
- let name = typeof raw.name == "string" && raw.name.trim() ? raw.name.trim() : id, exact = id === template.id, discovery = {
1209
- model: {
1210
- id,
1211
- name,
1212
- api: template.api,
1213
- provider: template.provider,
1214
- baseUrl: template.baseUrl,
1215
- reasoning: template.reasoning,
1216
- input: exact ? template.input : ["text"],
1217
- cost: ZERO_COST2,
1218
- contextWindow: DEFAULT_CONTEXT_WINDOW,
1219
- maxTokens: DEFAULT_MAX_TOKENS,
1220
- compat: template.compat,
1221
- thinkingLevelMap: exact ? template.thinkingLevelMap : void 0,
1222
- catalog: { source: "provider", supplied: typeof raw.name == "string" ? ["name"] : [], pricing: "unknown" }
1223
- },
1224
- supplied: {
1225
- ...NONE_SUPPLIED,
1226
- name: typeof raw.name == "string" && raw.name.trim().length > 0
1227
- }
1228
- }, context = asFiniteNumber2(raw.context_window ?? raw.context_length ?? raw.max_context_length), output = asFiniteNumber2(raw.max_output_tokens ?? raw.max_completion_tokens);
1229
- if (context && context > 0 && (discovery.model.contextWindow = context, discovery.supplied.contextWindow = !0), output && output > 0 && (discovery.model.maxTokens = output, discovery.supplied.maxTokens = !0), typeof raw.reasoning == "boolean" && (discovery.model.reasoning = raw.reasoning, discovery.supplied.reasoning = !0), Array.isArray(raw.input_modalities)) {
1230
- let input = raw.input_modalities.filter((value) => value === "text" || value === "image");
1231
- input.length && (discovery.model.input = input, discovery.supplied.input = !0);
1232
- }
1233
- return discovery.model.catalog.supplied = Object.entries(discovery.supplied).filter(([, value]) => value).map(([field]) => field), discovery;
1234
- }
1235
- function mapOpenRouterModel(raw, template) {
1236
- let id = typeof raw.id == "string" ? raw.id.trim() : "";
1237
- if (!id)
1238
- return;
1239
- let supported = Array.isArray(raw.supported_parameters) ? raw.supported_parameters : [];
1240
- if (!supported.includes("tools"))
1241
- return;
1242
- let architecture = isRecord2(raw.architecture) ? raw.architecture : void 0, modality = typeof architecture?.modality == "string" ? architecture.modality : "", input = ["text"];
1243
- modality.includes("image") && input.push("image");
1244
- let pricing = isRecord2(raw.pricing) ? raw.pricing : void 0, inputCost = roundCost((asFiniteNumber2(pricing?.prompt) ?? 0) * 1e6), outputCost = roundCost((asFiniteNumber2(pricing?.completion) ?? 0) * 1e6), cacheReadCost = roundCost((asFiniteNumber2(pricing?.input_cache_read) ?? 0) * 1e6), cacheWriteCost = roundCost((asFiniteNumber2(pricing?.input_cache_write) ?? 0) * 1e6), topProvider = isRecord2(raw.top_provider) ? raw.top_provider : void 0, contextWindow = asFiniteNumber2(topProvider?.context_length) ?? asFiniteNumber2(raw.context_length), maxTokens = asFiniteNumber2(topProvider?.max_completion_tokens) ?? asFiniteNumber2(raw.max_completion_tokens), name = typeof raw.name == "string" && raw.name.trim() ? raw.name.trim() : id;
1245
- return {
1246
- model: {
1247
- id,
1248
- name,
1249
- api: template.api,
1250
- provider: template.provider,
1251
- baseUrl: template.baseUrl,
1252
- reasoning: supported.includes("reasoning") || template.reasoning,
1253
- input,
1254
- cost: {
1255
- input: inputCost,
1256
- output: outputCost,
1257
- cacheRead: cacheReadCost,
1258
- cacheWrite: cacheWriteCost
1259
- },
1260
- contextWindow: contextWindow ?? DEFAULT_CONTEXT_WINDOW,
1261
- maxTokens: maxTokens ?? DEFAULT_MAX_TOKENS,
1262
- compat: template.compat,
1263
- thinkingLevelMap: template.thinkingLevelMap
1264
- },
1265
- supplied: {
1266
- contextWindow: contextWindow !== void 0,
1267
- maxTokens: maxTokens !== void 0,
1268
- input: !0,
1269
- name: typeof raw.name == "string" && raw.name.trim().length > 0,
1270
- cost: asFiniteNumber2(pricing?.prompt) !== void 0 && asFiniteNumber2(pricing?.completion) !== void 0,
1271
- reasoning: supported.includes("reasoning")
1272
- }
1273
- };
1274
- }
1275
- function discoverLiveModels(providerId, payload, bakedIn) {
1276
- if (providerId === "openai-codex")
1277
- return discoverCodexModels(payload, bakedIn[0]?.baseUrl ?? "https://chatgpt.com/backend-api");
1278
- let fallback = firstBakedInModel(bakedIn);
1279
- if (!fallback)
1280
- return [];
1281
- let rows = parseOpenAIModelsList(payload), discoveries = [];
1282
- for (let raw of rows) {
1283
- let id = typeof raw.id == "string" ? raw.id.trim() : "";
1284
- if (!id || raw.tool_call === !1 || raw.type === "embedding" || providerId === "openai" && /^(?:text-embedding-|tts-|whisper-|dall-e-|gpt-image-|gpt-audio|gpt-realtime|sora-|.*moderation)/i.test(id))
1285
- continue;
1286
- let template = { ...selectLiveTemplate(providerId, id, bakedIn) ?? fallback, provider: providerId };
1287
- if (providerId === "openrouter") {
1288
- let mapped = mapOpenRouterModel(raw, template);
1289
- mapped && (mapped.model.catalog = {
1290
- source: "provider",
1291
- ...mapped.supplied.cost ? {} : { pricing: "unknown" },
1292
- supplied: Object.entries(mapped.supplied).filter(([, supplied]) => supplied).map(([key]) => key)
1293
- }, mapped.model = normalizeCatalogPricing(mapped.model), mapped.model.catalog?.pricing === "unknown" && (mapped.supplied.cost = !1), discoveries.push(mapped));
1294
- continue;
1295
- }
1296
- discoveries.push(synthesizeLiveModel(id, template, raw));
1297
- }
1298
- return discoveries;
1299
- }
1300
- function missingLiveFields(supplied) {
1301
- let missing = [];
1302
- return supplied.contextWindow || missing.push("contextWindow"), supplied.maxTokens || missing.push("maxTokens"), supplied.input || missing.push("input"), missing;
1303
- }
1304
- function isLiveModelIncomplete(discovery, knownKeys) {
1305
- return knownKeys.has(modelKey(discovery.model.provider, discovery.model.id)) ? !1 : missingLiveFields(discovery.supplied).length > 0;
1306
- }
1307
- function collectIncompleteLiveModels(discoveries, bakedIn, knownKeys) {
1308
- let apis = uniqueApis(bakedIn), incomplete = [];
1309
- for (let discovery of discoveries)
1310
- isLiveModelIncomplete(discovery, knownKeys) && incomplete.push({
1311
- provider: discovery.model.provider,
1312
- id: discovery.model.id,
1313
- name: discovery.model.name,
1314
- missing: missingLiveFields(discovery.supplied),
1315
- draft: discovery.model,
1316
- availableApis: apis
1317
- });
1318
- return incomplete;
1319
- }
1320
- function buildLiveOverlay(bakedIn, discoveries) {
1321
- let bakedById = new Map(bakedIn.map((model) => [model.id, model])), overlay = [];
1322
- for (let discovery of discoveries) {
1323
- let baked = bakedById.get(discovery.model.id);
1324
- if (!baked) {
1325
- overlay.push(discovery.model);
1326
- continue;
1327
- }
1328
- overlay.push({
1329
- ...baked,
1330
- catalog: discovery.model.catalog,
1331
- thinkingLevelMap: discovery.model.catalog?.supplied.includes("thinkingLevelMap") ? discovery.model.thinkingLevelMap : baked.thinkingLevelMap,
1332
- name: discovery.supplied.name ? discovery.model.name : baked.name,
1333
- contextWindow: discovery.supplied.contextWindow ? discovery.model.contextWindow : baked.contextWindow,
1334
- maxTokens: discovery.supplied.maxTokens ? discovery.model.maxTokens : baked.maxTokens,
1335
- input: discovery.supplied.input ? discovery.model.input : baked.input,
1336
- cost: discovery.supplied.cost ? discovery.model.cost : baked.cost,
1337
- reasoning: discovery.supplied.reasoning ? discovery.model.reasoning : baked.reasoning
1338
- });
1339
- }
1340
- return overlay;
1341
- }
1342
- async function fetchLiveProviderModels(options) {
1343
- let empty = {
1344
- providerId: options.providerId,
1345
- status: "skipped",
1346
- discoveries: [],
1347
- added: 0,
1348
- total: 0,
1349
- incomplete: []
1350
- };
1351
- if (!firstBakedInModel(options.bakedIn) && options.providerId !== "openai-codex" || !options.baseUrl)
1352
- return empty;
1353
- let timeoutMs = options.timeoutMs ?? LIVE_CATALOG_TIMEOUT_MS, controller = new AbortController(), timedOut = !1, timer = setTimeout(() => {
1354
- timedOut = !0, controller.abort();
1355
- }, timeoutMs), onParentAbort = () => controller.abort();
1356
- options.signal?.addEventListener("abort", onParentAbort, { once: !0 }), options.signal?.aborted && controller.abort();
1357
- try {
1358
- let fetchImpl = options.fetchImpl ?? fetch, codex = options.providerId === "openai-codex", accountId = options.credential?.type === "oauth" && typeof options.credential.accountId == "string" ? options.credential.accountId : void 0, discoveryClientVersion = options.discoveryClientVersion, payload = await Promise.race([
1359
- (async () => {
1360
- codex && (discoveryClientVersion = await resolveCodexCatalogVersion(fetchImpl, controller.signal, discoveryClientVersion));
1361
- let response = await fetchImpl(codex ? codexModelsUrl(options.baseUrl, discoveryClientVersion) : modelsListUrl(options.baseUrl), {
1362
- headers: {
1363
- accept: "application/json",
1364
- "User-Agent": getPiUserAgent(VERSION),
1365
- ...credentialAuthHeaders(options.credential),
1366
- ...accountId ? { "ChatGPT-Account-ID": accountId } : {}
1367
- },
1368
- signal: controller.signal
1369
- });
1370
- if (!response.ok)
1371
- throw new Error(`HTTP ${response.status}`);
1372
- return response.json();
1373
- })(),
1374
- new Promise((_, reject) => {
1375
- let abortError = new Error("The operation was aborted");
1376
- abortError.name = "AbortError", controller.signal.addEventListener("abort", () => reject(abortError), { once: !0 }), controller.signal.aborted && reject(abortError);
1377
- })
1378
- ]), discoveries = codex ? discoverCodexModels(payload, options.baseUrl) : discoverLiveModels(options.providerId, payload, options.bakedIn);
1379
- if (!discoveries.length)
1380
- throw new Error("No usable models returned; retaining cached models");
1381
- let bakedIds = new Set(options.bakedIn.map((model) => model.id)), added = discoveries.filter((discovery) => !bakedIds.has(discovery.model.id)).length;
1382
- return {
1383
- providerId: options.providerId,
1384
- discoveryClientVersion,
1385
- status: "ok",
1386
- discoveries,
1387
- added,
1388
- total: discoveries.length,
1389
- incomplete: collectIncompleteLiveModels(discoveries, options.bakedIn, options.knownKeys)
1390
- };
1391
- } catch (error) {
1392
- return options.signal?.aborted && !timedOut ? { ...empty, status: "skipped", error: "aborted" } : timedOut || error instanceof Error && error.name === "AbortError" ? { ...empty, status: "timeout", error: "timed out" } : {
1393
- ...empty,
1394
- status: "error",
1395
- error: error instanceof Error ? error.message : String(error)
1396
- };
1397
- } finally {
1398
- clearTimeout(timer), options.signal?.removeEventListener("abort", onParentAbort);
1399
- }
1400
- }
1401
-
1402
- // packages/coding-agent/dist/core/model-config.js
1403
- import { readFile } from "node:fs/promises";
1404
- import { Type } from "typebox";
1405
- import { Compile } from "typebox/compile";
1406
-
1407
- // packages/coding-agent/dist/utils/json.js
1408
- function stripJsonComments(input) {
1409
- return input.replace(/"(?:\\.|[^"\\])*"|\/\/[^\n]*/g, (m) => m[0] === '"' ? m : "").replace(/"(?:\\.|[^"\\])*"|,(\s*[}\]])/g, (m, tail) => tail ?? (m[0] === '"' ? m : ""));
1410
- }
1411
-
1412
- // packages/coding-agent/dist/core/model-config.js
1413
- var PercentileCutoffsSchema = Type.Object({
1414
- p50: Type.Optional(Type.Number()),
1415
- p75: Type.Optional(Type.Number()),
1416
- p90: Type.Optional(Type.Number()),
1417
- p99: Type.Optional(Type.Number())
1418
- }), OpenRouterRoutingSchema = Type.Object({
1419
- allow_fallbacks: Type.Optional(Type.Boolean()),
1420
- require_parameters: Type.Optional(Type.Boolean()),
1421
- data_collection: Type.Optional(Type.Union([Type.Literal("deny"), Type.Literal("allow")])),
1422
- zdr: Type.Optional(Type.Boolean()),
1423
- enforce_distillable_text: Type.Optional(Type.Boolean()),
1424
- order: Type.Optional(Type.Array(Type.String())),
1425
- only: Type.Optional(Type.Array(Type.String())),
1426
- ignore: Type.Optional(Type.Array(Type.String())),
1427
- quantizations: Type.Optional(Type.Array(Type.String())),
1428
- sort: Type.Optional(Type.Union([
1429
- Type.String(),
1430
- Type.Object({
1431
- by: Type.Optional(Type.String()),
1432
- partition: Type.Optional(Type.Union([Type.String(), Type.Null()]))
1433
- })
1434
- ])),
1435
- max_price: Type.Optional(Type.Object({
1436
- prompt: Type.Optional(Type.Union([Type.Number(), Type.String()])),
1437
- completion: Type.Optional(Type.Union([Type.Number(), Type.String()])),
1438
- image: Type.Optional(Type.Union([Type.Number(), Type.String()])),
1439
- audio: Type.Optional(Type.Union([Type.Number(), Type.String()])),
1440
- request: Type.Optional(Type.Union([Type.Number(), Type.String()]))
1441
- })),
1442
- preferred_min_throughput: Type.Optional(Type.Union([Type.Number(), PercentileCutoffsSchema])),
1443
- preferred_max_latency: Type.Optional(Type.Union([Type.Number(), PercentileCutoffsSchema]))
1444
- }), VercelGatewayRoutingSchema = Type.Object({
1445
- only: Type.Optional(Type.Array(Type.String())),
1446
- order: Type.Optional(Type.Array(Type.String()))
1447
- }), ThinkingLevelMapValueSchema = Type.Union([Type.String(), Type.Null()]), ThinkingLevelMapSchema = Type.Object({
1448
- off: Type.Optional(ThinkingLevelMapValueSchema),
1449
- minimal: Type.Optional(ThinkingLevelMapValueSchema),
1450
- low: Type.Optional(ThinkingLevelMapValueSchema),
1451
- medium: Type.Optional(ThinkingLevelMapValueSchema),
1452
- high: Type.Optional(ThinkingLevelMapValueSchema),
1453
- xhigh: Type.Optional(ThinkingLevelMapValueSchema),
1454
- max: Type.Optional(ThinkingLevelMapValueSchema)
1455
- }), ChatTemplateKwargScalarSchema = Type.Union([Type.String(), Type.Number(), Type.Boolean(), Type.Null()]), ChatTemplateKwargVariableSchema = Type.Object({
1456
- $var: Type.Union([Type.Literal("thinking.enabled"), Type.Literal("thinking.effort")]),
1457
- omitWhenOff: Type.Optional(Type.Boolean())
1458
- }), ChatTemplateKwargSchema = Type.Union([ChatTemplateKwargScalarSchema, ChatTemplateKwargVariableSchema]), OpenAICompletionsCompatSchema = Type.Object({
1459
- supportsStore: Type.Optional(Type.Boolean()),
1460
- supportsDeveloperRole: Type.Optional(Type.Boolean()),
1461
- supportsReasoningEffort: Type.Optional(Type.Boolean()),
1462
- supportsUsageInStreaming: Type.Optional(Type.Boolean()),
1463
- maxTokensField: Type.Optional(Type.Union([Type.Literal("max_completion_tokens"), Type.Literal("max_tokens")])),
1464
- requiresToolResultName: Type.Optional(Type.Boolean()),
1465
- requiresAssistantAfterToolResult: Type.Optional(Type.Boolean()),
1466
- requiresThinkingAsText: Type.Optional(Type.Boolean()),
1467
- requiresReasoningContentOnAssistantMessages: Type.Optional(Type.Boolean()),
1468
- thinkingFormat: Type.Optional(Type.Union([
1469
- Type.Literal("openai"),
1470
- Type.Literal("openrouter"),
1471
- Type.Literal("together"),
1472
- Type.Literal("deepseek"),
1473
- Type.Literal("zai"),
1474
- Type.Literal("qwen"),
1475
- Type.Literal("chat-template"),
1476
- Type.Literal("qwen-chat-template"),
1477
- Type.Literal("string-thinking"),
1478
- Type.Literal("ant-ling")
1479
- ])),
1480
- chatTemplateKwargs: Type.Optional(Type.Record(Type.String(), ChatTemplateKwargSchema)),
1481
- cacheControlFormat: Type.Optional(Type.Literal("anthropic")),
1482
- openRouterRouting: Type.Optional(OpenRouterRoutingSchema),
1483
- vercelGatewayRouting: Type.Optional(VercelGatewayRoutingSchema),
1484
- supportsStrictMode: Type.Optional(Type.Boolean()),
1485
- sendSessionAffinityHeaders: Type.Optional(Type.Boolean()),
1486
- deferredToolsMode: Type.Optional(Type.Literal("kimi")),
1487
- sessionAffinityFormat: Type.Optional(Type.Union([Type.Literal("openai"), Type.Literal("openai-nosession"), Type.Literal("openrouter")])),
1488
- supportsLongCacheRetention: Type.Optional(Type.Boolean())
1489
- }), OpenAIResponsesCompatSchema = Type.Object({
1490
- supportsDeveloperRole: Type.Optional(Type.Boolean()),
1491
- sessionAffinityFormat: Type.Optional(Type.Union([Type.Literal("openai"), Type.Literal("openai-nosession"), Type.Literal("openrouter")])),
1492
- supportsLongCacheRetention: Type.Optional(Type.Boolean()),
1493
- supportsToolSearch: Type.Optional(Type.Boolean())
1494
- }), AnthropicMessagesCompatSchema = Type.Object({
1495
- supportsEagerToolInputStreaming: Type.Optional(Type.Boolean()),
1496
- supportsLongCacheRetention: Type.Optional(Type.Boolean()),
1497
- sendSessionAffinityHeaders: Type.Optional(Type.Boolean()),
1498
- supportsCacheControlOnTools: Type.Optional(Type.Boolean()),
1499
- forceAdaptiveThinking: Type.Optional(Type.Boolean()),
1500
- supportsToolReferences: Type.Optional(Type.Boolean())
1501
- }), ProviderCompatSchema = Type.Union([
1502
- OpenAICompletionsCompatSchema,
1503
- OpenAIResponsesCompatSchema,
1504
- AnthropicMessagesCompatSchema
1505
- ]), ModelCostRatesSchema = {
1506
- input: Type.Number(),
1507
- output: Type.Number(),
1508
- cacheRead: Type.Number(),
1509
- cacheWrite: Type.Number()
1510
- }, ModelCostTierSchema = Type.Object({
1511
- inputTokensAbove: Type.Number(),
1512
- ...ModelCostRatesSchema
1513
- }), ModelCostSchema = Type.Object({
1514
- ...ModelCostRatesSchema,
1515
- tiers: Type.Optional(Type.Array(ModelCostTierSchema))
1516
- }), ModelDefinitionSchema = Type.Object({
1517
- id: Type.String({ minLength: 1 }),
1518
- name: Type.Optional(Type.String({ minLength: 1 })),
1519
- api: Type.Optional(Type.String({ minLength: 1 })),
1520
- baseUrl: Type.Optional(Type.String({ minLength: 1 })),
1521
- reasoning: Type.Optional(Type.Boolean()),
1522
- thinkingLevelMap: Type.Optional(ThinkingLevelMapSchema),
1523
- input: Type.Optional(Type.Array(Type.Union([Type.Literal("text"), Type.Literal("image")]))),
1524
- cost: Type.Optional(ModelCostSchema),
1525
- contextWindow: Type.Optional(Type.Number()),
1526
- maxTokens: Type.Optional(Type.Number()),
1527
- headers: Type.Optional(Type.Record(Type.String(), Type.String())),
1528
- compat: Type.Optional(ProviderCompatSchema)
1529
- }), ModelOverrideSchema = Type.Object({
1530
- name: Type.Optional(Type.String({ minLength: 1 })),
1531
- reasoning: Type.Optional(Type.Boolean()),
1532
- thinkingLevelMap: Type.Optional(ThinkingLevelMapSchema),
1533
- input: Type.Optional(Type.Array(Type.Union([Type.Literal("text"), Type.Literal("image")]))),
1534
- cost: Type.Optional(Type.Object({
1535
- input: Type.Optional(Type.Number()),
1536
- output: Type.Optional(Type.Number()),
1537
- cacheRead: Type.Optional(Type.Number()),
1538
- cacheWrite: Type.Optional(Type.Number()),
1539
- tiers: Type.Optional(Type.Array(ModelCostTierSchema))
1540
- })),
1541
- contextWindow: Type.Optional(Type.Number()),
1542
- maxTokens: Type.Optional(Type.Number()),
1543
- headers: Type.Optional(Type.Record(Type.String(), Type.String())),
1544
- compat: Type.Optional(ProviderCompatSchema)
1545
- }), ProviderConfigSchema = Type.Object({
1546
- name: Type.Optional(Type.String({ minLength: 1 })),
1547
- baseUrl: Type.Optional(Type.String({ minLength: 1 })),
1548
- apiKey: Type.Optional(Type.String({ minLength: 1 })),
1549
- api: Type.Optional(Type.String({ minLength: 1 })),
1550
- oauth: Type.Optional(Type.Literal("radius")),
1551
- headers: Type.Optional(Type.Record(Type.String(), Type.String())),
1552
- compat: Type.Optional(ProviderCompatSchema),
1553
- authHeader: Type.Optional(Type.Boolean()),
1554
- models: Type.Optional(Type.Array(ModelDefinitionSchema)),
1555
- modelOverrides: Type.Optional(Type.Record(Type.String(), ModelOverrideSchema))
1556
- }), ModelsConfigSchema = Type.Object({
1557
- providers: Type.Record(Type.String(), ProviderConfigSchema)
1558
- }), validateModelsConfig = Compile(ModelsConfigSchema);
1559
- function formatValidationPath(error) {
1560
- if (error.keyword === "required") {
1561
- let requiredProperty = error.params.requiredProperties?.[0];
1562
- if (requiredProperty) {
1563
- let basePath = error.instancePath.replace(/^\//, "").replace(/\//g, ".");
1564
- return basePath ? `${basePath}.${requiredProperty}` : requiredProperty;
1565
- }
1566
- }
1567
- return error.instancePath.replace(/^\//, "").replace(/\//g, ".") || "root";
1568
- }
1569
- function deepFreeze(value) {
1570
- if (typeof value != "object" || value === null || Object.isFrozen(value))
1571
- return value;
1572
- for (let child of Object.values(value))
1573
- deepFreeze(child);
1574
- return Object.freeze(value);
1575
- }
1576
- var ModelConfig = class _ModelConfig {
1577
- providers;
1578
- error;
1579
- constructor(providers, error) {
1580
- this.providers = providers, this.error = error;
1581
- }
1582
- static async load(modelsJsonPath) {
1583
- if (!modelsJsonPath)
1584
- return new _ModelConfig(/* @__PURE__ */ new Map());
1585
- let path = normalizePath(modelsJsonPath), content;
1586
- try {
1587
- content = await readFile(path, "utf-8");
1588
- } catch (error) {
1589
- return error.code === "ENOENT" ? new _ModelConfig(/* @__PURE__ */ new Map()) : new _ModelConfig(/* @__PURE__ */ new Map(), `Failed to load models.json: ${error instanceof Error ? error.message : error}
1590
-
1591
- File: ${path}`);
1592
- }
1593
- let parsed;
1594
- try {
1595
- parsed = JSON.parse(stripJsonComments(content));
1596
- } catch (error) {
1597
- return new _ModelConfig(/* @__PURE__ */ new Map(), `Failed to parse models.json: ${error instanceof Error ? error.message : error}
1598
-
1599
- File: ${path}`);
1600
- }
1601
- if (!validateModelsConfig.Check(parsed)) {
1602
- let errors = validateModelsConfig.Errors(parsed).map((error) => ` - ${formatValidationPath(error)}: ${error.message}`).join(`
1603
- `) || "Unknown schema error";
1604
- return new _ModelConfig(/* @__PURE__ */ new Map(), `Invalid models.json schema:
1605
- ${errors}
1606
-
1607
- File: ${path}`);
1608
- }
1609
- let config = parsed, providers = /* @__PURE__ */ new Map();
1610
- for (let [providerId, provider] of Object.entries(config.providers))
1611
- providers.set(providerId, deepFreeze(structuredClone(provider)));
1612
- return new _ModelConfig(providers);
1613
- }
1614
- getProvider(providerId) {
1615
- return this.providers.get(providerId);
1616
- }
1617
- getProviderIds() {
1618
- return [...this.providers.keys()];
1619
- }
1620
- getError() {
1621
- return this.error;
1622
- }
1623
- };
1624
-
1625
- // packages/coding-agent/dist/core/models-store.js
1626
- import { join as join4 } from "node:path";
1627
- var InMemoryCodingAgentModelsStore = class {
1628
- entries = /* @__PURE__ */ new Map();
1629
- async read(providerId) {
1630
- return this.entries.get(providerId);
1631
- }
1632
- async write(providerId, entry) {
1633
- this.entries.set(providerId, entry);
1634
- }
1635
- async delete(providerId) {
1636
- this.entries.delete(providerId);
1637
- }
1638
- }, FileModelsStore = class {
1639
- storage;
1640
- constructor(path = join4(getAgentDir(), "models-store.json")) {
1641
- this.storage = new FileAuthStorageBackend(path);
1642
- }
1643
- parse(content) {
1644
- let trimmed = content?.replace(/^\uFEFF/, "").trim();
1645
- if (!trimmed)
1646
- return {};
1647
- try {
1648
- let parsed = JSON.parse(trimmed);
1649
- return !parsed || typeof parsed != "object" || Array.isArray(parsed) ? {} : parsed;
1650
- } catch {
1651
- return {};
1652
- }
1653
- }
1654
- async read(providerId) {
1655
- return this.storage.withLock((content) => ({
1656
- result: structuredClone(this.parse(content)[providerId])
1657
- }));
1658
- }
1659
- async write(providerId, entry) {
1660
- await this.storage.withLockAsync(async (content) => {
1661
- let current = this.parse(content);
1662
- return current[providerId] = structuredClone(entry), { result: void 0, next: JSON.stringify(current, null, 2) };
1663
- });
1664
- }
1665
- async delete(providerId) {
1666
- await this.storage.withLockAsync(async (content) => {
1667
- let current = this.parse(content);
1668
- return delete current[providerId], { result: void 0, next: JSON.stringify(current, null, 2) };
1669
- });
1670
- }
1671
- };
1672
-
1673
- // packages/coding-agent/dist/core/provider-composer.js
1674
- import { lazyStream } from "@ashx-j/lunr-ai";
1675
- import { getApiProvider } from "@ashx-j/lunr-ai/compat";
1676
- function mergeCompat(base, override) {
1677
- if (!override)
1678
- return base;
1679
- let merged = { ...base, ...override }, baseNested = base, overrideNested = override, mergedNested = merged;
1680
- for (let key of ["openRouterRouting", "vercelGatewayRouting", "chatTemplateKwargs"]) {
1681
- let baseValue = baseNested?.[key], overrideValue = overrideNested[key];
1682
- (typeof baseValue == "object" && baseValue !== null || typeof overrideValue == "object" && overrideValue !== null) && (mergedNested[key] = { ...baseValue, ...overrideValue });
1683
- }
1684
- return merged;
1685
- }
1686
- function applyModelOverride(model, override) {
1687
- return {
1688
- ...model,
1689
- name: override.name ?? model.name,
1690
- reasoning: override.reasoning ?? model.reasoning,
1691
- thinkingLevelMap: override.thinkingLevelMap ? { ...model.thinkingLevelMap, ...override.thinkingLevelMap } : model.thinkingLevelMap,
1692
- input: override.input ?? model.input,
1693
- cost: override.cost ? {
1694
- input: override.cost.input ?? model.cost.input,
1695
- output: override.cost.output ?? model.cost.output,
1696
- cacheRead: override.cost.cacheRead ?? model.cost.cacheRead,
1697
- cacheWrite: override.cost.cacheWrite ?? model.cost.cacheWrite,
1698
- tiers: override.cost.tiers ?? model.cost.tiers
1699
- } : model.cost,
1700
- contextWindow: override.contextWindow ?? model.contextWindow,
1701
- maxTokens: override.maxTokens ?? model.maxTokens,
1702
- compat: mergeCompat(model.compat, override.compat)
1703
- };
1704
- }
1705
- function modelFromJson(providerId, definition, providerConfig, defaults) {
1706
- let api = definition.api ?? providerConfig.api ?? defaults?.api;
1707
- if (!api)
1708
- throw new Error(`Provider ${providerId}, model ${definition.id}: no "api" specified. Set at provider or model level.`);
1709
- let baseUrl = definition.baseUrl ?? providerConfig.baseUrl ?? defaults?.baseUrl;
1710
- if (!baseUrl)
1711
- throw new Error(`Provider ${providerId}: "baseUrl" is required when defining custom models.`);
1712
- if (definition.contextWindow !== void 0 && definition.contextWindow <= 0)
1713
- throw new Error(`Provider ${providerId}, model ${definition.id}: invalid contextWindow`);
1714
- if (definition.maxTokens !== void 0 && definition.maxTokens <= 0)
1715
- throw new Error(`Provider ${providerId}, model ${definition.id}: invalid maxTokens`);
1716
- return {
1717
- id: definition.id,
1718
- name: definition.name ?? definition.id,
1719
- api,
1720
- provider: providerId,
1721
- baseUrl,
1722
- reasoning: definition.reasoning ?? !1,
1723
- thinkingLevelMap: definition.thinkingLevelMap,
1724
- input: definition.input ?? ["text"],
1725
- cost: definition.cost ?? { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
1726
- contextWindow: definition.contextWindow ?? 128e3,
1727
- maxTokens: definition.maxTokens ?? 16384,
1728
- headers: void 0,
1729
- compat: mergeCompat(providerConfig.compat, definition.compat)
1730
- };
1731
- }
1732
- function applyModelsJson(providerId, baseModels, config) {
1733
- if (!config)
1734
- return [...baseModels];
1735
- if (config.oauth && !config.baseUrl)
1736
- throw new Error(`Provider ${providerId}: "baseUrl" is required when "oauth" is set.`);
1737
- let hasOverrides = config.modelOverrides && Object.keys(config.modelOverrides).length > 0;
1738
- if (!config.models?.length && !config.baseUrl && !config.headers && !config.compat && !hasOverrides && !config.apiKey && !config.oauth && config.authHeader === void 0)
1739
- throw new Error(`Provider ${providerId}: must specify "baseUrl", "headers", "compat", "modelOverrides", or "models".`);
1740
- let models = baseModels.map((model) => ({
1741
- ...model,
1742
- baseUrl: config.oauth === "radius" ? model.baseUrl : config.baseUrl ?? model.baseUrl,
1743
- compat: mergeCompat(model.compat, config.compat)
1744
- }));
1745
- for (let definition of config.models ?? []) {
1746
- let existingIndex = models.findIndex((model2) => model2.id === definition.id), defaults = existingIndex >= 0 ? models[existingIndex] : models[0], model = modelFromJson(providerId, definition, config, defaults);
1747
- existingIndex >= 0 ? models[existingIndex] = model : models.push(model);
1748
- }
1749
- return models;
1750
- }
1751
- function applyExtension(providerId, models, config) {
1752
- return config ? config.models ? config.models.map((definition) => {
1753
- let defaults = models.find((model) => model.id === definition.id) ?? models[0], api = definition.api ?? config.api ?? defaults?.api;
1754
- if (!api)
1755
- throw new Error(`Provider ${providerId}, model ${definition.id}: no "api" specified. Set at provider or model level.`);
1756
- let baseUrl = definition.baseUrl ?? config.baseUrl ?? defaults?.baseUrl;
1757
- if (!baseUrl)
1758
- throw new Error(`Provider ${providerId}: "baseUrl" is required when defining custom models.`);
1759
- return {
1760
- ...definition,
1761
- api,
1762
- provider: providerId,
1763
- baseUrl,
1764
- headers: void 0
1765
- };
1766
- }) : config.baseUrl ? models.map((model) => ({ ...model, baseUrl: config.baseUrl })) : [...models] : [...models];
1767
- }
1768
- function adaptOAuth(config) {
1769
- return {
1770
- name: config.name,
1771
- login: async (callbacks) => ({ ...await config.login({
1772
- onAuth: (info) => callbacks.notify({ type: "auth_url", ...info }),
1773
- onDeviceCode: (info) => callbacks.notify({ type: "device_code", ...info }),
1774
- onPrompt: (prompt) => callbacks.prompt({ type: "text", ...prompt }),
1775
- onProgress: (message) => callbacks.notify({ type: "progress", message }),
1776
- onManualCodeInput: () => callbacks.prompt({ type: "manual_code", message: "Paste the authorization code" }),
1777
- onSelect: (prompt) => callbacks.prompt({ type: "select", ...prompt }),
1778
- signal: callbacks.signal
1779
- }), type: "oauth" }),
1780
- refresh: async (credential) => ({ ...await config.refreshToken(credential), type: "oauth" }),
1781
- toAuth: async (credential) => ({ apiKey: config.getApiKey(credential) })
1782
- };
1783
- }
1784
- function withConfiguredAuth(auth, headers, authHeader) {
1785
- let mergedHeaders = auth.headers || headers ? { ...auth.headers, ...headers } : void 0;
1786
- if (authHeader) {
1787
- if (!auth.apiKey)
1788
- throw new Error("authHeader requires a resolved API key");
1789
- mergedHeaders = { ...mergedHeaders, Authorization: `Bearer ${auth.apiKey}` };
1790
- }
1791
- return { ...auth, headers: mergedHeaders };
1792
- }
1793
- function configuredApiKey(config, extension) {
1794
- return extension?.apiKey ?? config?.apiKey;
1795
- }
1796
- function configuredHeaders(config, extension) {
1797
- if (!(!config?.headers && !extension?.headers))
1798
- return { ...config?.headers, ...extension?.headers };
1799
- }
1800
- async function configContextEnv(values, ctx, explicit) {
1801
- let env = { ...explicit };
1802
- for (let name of new Set(values.flatMap(getConfigValueEnvVarNames))) {
1803
- if (env[name] !== void 0)
1804
- continue;
1805
- let value = await ctx.env(name);
1806
- value !== void 0 && (env[name] = value);
1807
- }
1808
- return Object.keys(env).length > 0 ? env : void 0;
1809
- }
1810
- function composeApiKeyAuth(providerId, base, config, extension) {
1811
- let inherited = base?.auth.apiKey, rawKey = configuredApiKey(config, extension), oauth = extension?.oauth ?? base?.auth.oauth;
1812
- if (!inherited && rawKey === void 0 && oauth)
1813
- return;
1814
- let rawHeaders = configuredHeaders(config, extension), authHeader = extension?.authHeader ?? config?.authHeader ?? !1;
1815
- return {
1816
- name: inherited?.name ?? "API key",
1817
- login: inherited?.login ?? (async (interaction) => ({
1818
- type: "api_key",
1819
- key: await interaction.prompt({ type: "secret", message: "Enter API key" })
1820
- })),
1821
- check: async (input) => {
1822
- if (input.credential) {
1823
- if (inherited?.check)
1824
- return inherited.check(input);
1825
- if (input.credential.key)
1826
- return { type: "api_key", source: "stored credential" };
1827
- let resolved2 = await inherited?.resolve(input);
1828
- return resolved2 ? { type: "api_key", source: resolved2.source } : void 0;
1829
- }
1830
- if (rawKey !== void 0) {
1831
- if (isCommandConfigValue(rawKey))
1832
- return { type: "api_key", source: "configured API key" };
1833
- let envNames = getConfigValueEnvVarNames(rawKey);
1834
- for (let name of envNames)
1835
- if (await input.ctx.env(name) === void 0)
1836
- return;
1837
- return { type: "api_key", source: "configured API key" };
1838
- }
1839
- if (inherited?.check)
1840
- return inherited.check(input);
1841
- let resolved = await inherited?.resolve(input);
1842
- return resolved ? { type: "api_key", source: resolved.source } : void 0;
1843
- },
1844
- resolve: async (input) => {
1845
- let result;
1846
- if (input.credential)
1847
- result = inherited ? await inherited.resolve(input) : input.credential.key ? { auth: { apiKey: input.credential.key }, env: input.credential.env, source: "stored credential" } : void 0;
1848
- else if (rawKey !== void 0) {
1849
- let env = await configContextEnv([rawKey], input.ctx), key = resolveConfigValueOrThrow(rawKey, `API key for provider "${providerId}"`, env);
1850
- result = inherited ? await inherited.resolve({ ...input, credential: { type: "api_key", key } }) : { auth: { apiKey: key }, source: "configured API key" };
1851
- } else
1852
- result = await inherited?.resolve(input);
1853
- if (!result)
1854
- return;
1855
- let explicitEnv = { ...input.credential?.env ?? {}, ...result.env ?? {} }, headerEnv = await configContextEnv(Object.values(rawHeaders ?? {}), input.ctx, explicitEnv), headers = resolveHeadersOrThrow(rawHeaders, `provider "${providerId}"`, headerEnv);
1856
- return { ...result, auth: withConfiguredAuth(result.auth, headers, authHeader) };
1857
- }
1858
- };
1859
- }
1860
- function composeOAuthAuth(providerId, base, config, extension) {
1861
- let oauth = extension?.oauth ? adaptOAuth(extension.oauth) : base?.auth.oauth;
1862
- if (!oauth)
1863
- return;
1864
- let rawHeaders = configuredHeaders(config, extension), authHeader = extension?.authHeader ?? config?.authHeader ?? !1;
1865
- return {
1866
- ...oauth,
1867
- toAuth: async (credential) => {
1868
- let auth = await oauth.toAuth(credential), env = credential.env, headers = resolveHeadersOrThrow(rawHeaders, `provider "${providerId}"`, typeof env == "object" && env !== null ? env : void 0);
1869
- return withConfiguredAuth(auth, headers, authHeader);
1870
- }
1871
- };
1872
- }
1873
- function rawModelHeaders(model, config, extension) {
1874
- let definition = config?.models?.find((entry) => entry.id === model.id), extensionModel = extension?.models?.find((entry) => entry.id === model.id), headers = {
1875
- ...config?.modelOverrides?.[model.id]?.headers,
1876
- ...definition?.headers,
1877
- ...extensionModel?.headers
1878
- };
1879
- return Object.keys(headers).length > 0 ? headers : void 0;
1880
- }
1881
- function validateExtensionProvider(providerId, base, modelsConfig, extension) {
1882
- if (extension.streamSimple && !extension.api)
1883
- throw new Error(`Provider ${providerId}: "api" is required when registering streamSimple.`);
1884
- applyExtension(providerId, applyModelsJson(providerId, base?.getModels() ?? [], modelsConfig), extension);
1885
- }
1886
- function composeModelProvider(providerId, base, modelConfig, extension) {
1887
- let config = modelConfig.getProvider(providerId), extensionOAuthCredential, refreshedExtensionModels, currentExtension = () => extension && refreshedExtensionModels ? { ...extension, models: refreshedExtensionModels } : extension, getModels = () => {
1888
- let models = applyExtension(providerId, applyModelsJson(providerId, base?.getModels() ?? [], config), currentExtension());
1889
- return extensionOAuthCredential && extension?.oauth?.modifyModels && (models = extension.oauth.modifyModels(models, extensionOAuthCredential)), models.map((model) => {
1890
- let override = config?.modelOverrides?.[model.id];
1891
- return override ? applyModelOverride(model, override) : model;
1892
- });
1893
- };
1894
- getModels();
1895
- let apiKey = composeApiKeyAuth(providerId, base, config, extension), oauth = composeOAuthAuth(providerId, base, config, extension);
1896
- if (!apiKey && !oauth)
1897
- throw new Error(`Provider ${providerId}: no authentication method configured.`);
1898
- let supportsBaseApi = (model) => base?.getModels().some((entry) => entry.api === model.api) ?? !1, streamWith = (model, context, options, simple) => lazyStream(model, async () => {
1899
- if (extension?.streamSimple && model.api === extension.api)
1900
- return extension.streamSimple(model, context, options);
1901
- if (base && supportsBaseApi(model))
1902
- return simple ? base.streamSimple(model, context, options) : base.stream(model, context, options);
1903
- let api = getApiProvider(model.api);
1904
- if (!api)
1905
- throw new Error(`No API provider registered for api: ${model.api}`);
1906
- return simple ? api.streamSimple(model, context, options) : api.stream(model, context, options);
1907
- });
1908
- return {
1909
- id: providerId,
1910
- name: extension?.name ?? config?.name ?? base?.name ?? extension?.oauth?.name ?? providerId,
1911
- baseUrl: extension?.baseUrl ?? config?.baseUrl ?? base?.baseUrl,
1912
- headers: base?.headers,
1913
- auth: { ...apiKey ? { apiKey } : {}, ...oauth ? { oauth } : {} },
1914
- getModels,
1915
- refreshModels: base?.refreshModels || extension?.refreshModels || extension?.oauth?.modifyModels ? async (context) => {
1916
- if (await base?.refreshModels?.(context), extension?.refreshModels) {
1917
- let refreshed = await extension.refreshModels(context);
1918
- context.signal?.aborted || (applyExtension(providerId, applyModelsJson(providerId, base?.getModels() ?? [], config), {
1919
- ...extension,
1920
- models: refreshed
1921
- }), refreshedExtensionModels = refreshed);
1922
- }
1923
- extensionOAuthCredential = context.credential?.type === "oauth" ? context.credential : void 0;
1924
- } : void 0,
1925
- filterModels: base?.filterModels ? (models, credential) => base.filterModels(models, credential) : void 0,
1926
- stream: (model, context, options) => streamWith(model, context, options, !1),
1927
- streamSimple: (model, context, options) => streamWith(model, context, options, !0)
1928
- };
1929
- }
1930
- function resolveConfiguredModelHeaders(model, config, extension, env) {
1931
- return resolveHeadersOrThrow(rawModelHeaders(model, config, extension), `model "${model.provider}/${model.id}"`, env);
1932
- }
1933
- function resolveCompatibilityRequestConfig(model, config, extension) {
1934
- let configured = resolveHeadersOrThrow({ ...configuredHeaders(config, extension), ...rawModelHeaders(model, config, extension) }, `model "${model.provider}/${model.id}"`);
1935
- return {
1936
- headers: model.headers || configured ? { ...model.headers, ...configured } : void 0,
1937
- authHeader: extension?.authHeader ?? config?.authHeader ?? !1
1938
- };
1939
- }
1940
- function configuredRequestAuthStatus(config, extension) {
1941
- let value = configuredApiKey(config, extension);
1942
- if (value === void 0)
1943
- return;
1944
- if (isCommandConfigValue(value))
1945
- return { configured: !0, source: "models_json_command" };
1946
- let names = getConfigValueEnvVarNames(value);
1947
- return names.length > 0 ? isConfigValueConfigured(value) ? { configured: !0, source: "environment", label: names.join(", ") } : { configured: !1 } : { configured: !0, source: extension?.apiKey !== void 0 ? "fallback" : "models_json_key" };
1948
- }
1949
-
1950
- // packages/coding-agent/dist/core/runtime-credentials.js
1951
- var RuntimeCredentials = class {
1952
- store;
1953
- overrides = /* @__PURE__ */ new Map();
1954
- constructor(store) {
1955
- this.store = store;
1956
- }
1957
- setRuntimeApiKey(providerId, apiKey) {
1958
- this.overrides.set(providerId, apiKey);
1959
- }
1960
- removeRuntimeApiKey(providerId) {
1961
- this.overrides.delete(providerId);
1962
- }
1963
- hasRuntimeApiKey(providerId) {
1964
- return this.overrides.has(providerId);
1965
- }
1966
- async read(providerId) {
1967
- let override = this.overrides.get(providerId);
1968
- return override ? { type: "api_key", key: override } : this.store.read(providerId);
1969
- }
1970
- async list() {
1971
- let entries = new Map((await this.store.list()).map((entry) => [entry.providerId, entry]));
1972
- for (let providerId of this.overrides.keys())
1973
- entries.set(providerId, { providerId, type: "api_key" });
1974
- return [...entries.values()];
1975
- }
1976
- modify(providerId, fn) {
1977
- return this.store.modify(providerId, fn);
1978
- }
1979
- async delete(providerId) {
1980
- this.overrides.delete(providerId), await this.store.delete(providerId);
1981
- }
1982
- };
1983
-
1984
- // packages/coding-agent/dist/core/subscriptions.js
1985
- import { join as join5 } from "path";
1986
-
1987
- // packages/coding-agent/dist/core/usage-limit.js
1988
- var USAGE_LIMIT_ERROR_PATTERNS = [
1989
- // Provider-declared subscription/free-tier limit error types and wording
1990
- // (pi-ai NON_RETRYABLE_PROVIDER_LIMIT_ERROR_PATTERN spirit).
1991
- "GoUsageLimitError",
1992
- "FreeUsageLimitError",
1993
- "Monthly usage limit reached",
1994
- "available balance",
1995
- "insufficient_quota",
1996
- "out of budget",
1997
- "quota exceeded",
1998
- "billing"
1999
- ], USAGE_LIMIT_ERROR_REGEXES = [
2000
- // Goal runtime USAGE_LIMIT_GOAL_ERROR_PATTERNS: usage caps, quota exhaustion,
2001
- // credit/balance exhaustion, payment required.
2002
- /usage[_\s-]*(?:limit|cap)|chatgpt.{0,32}usage/i,
2003
- /quota.{0,32}(?:reached|exceeded|exhausted|depleted)|(?:reached|exceeded|exhausted|depleted).{0,32}quota/i,
2004
- /insufficient[_\s-]*(?:quota|credits?)|out of credits|out of budget|available balance|payment required/i,
2005
- /(?:credit|balance).{0,32}(?:low|exhausted|depleted)|billing/i
2006
- ], AUTH_INVALID_ERROR_PATTERN = /\b401\b|unauthori[sz]ed|unauthenticated|invalid.{0,16}(?:api.?key|token|credentials?)|authentication.{0,16}failed/i;
2007
- function isUsageLimitError(errorMessage) {
2008
- return errorMessage ? USAGE_LIMIT_ERROR_PATTERNS.some((pattern) => errorMessage.toLowerCase().includes(pattern.toLowerCase())) ? !0 : USAGE_LIMIT_ERROR_REGEXES.some((pattern) => pattern.test(errorMessage)) : !1;
2009
- }
2010
- function isAuthInvalidError(errorMessage) {
2011
- return errorMessage ? AUTH_INVALID_ERROR_PATTERN.test(errorMessage) : !1;
2012
- }
2013
- var RESET_TIME_PATTERNS = [
2014
- /reset(?:s|ting)?\s*(?:in|after|at)?\s*(\d+)\s*s(ec)?/i,
2015
- /reset(?:s|ting)?\s*(?:in|after|at)?\s*(\d+)\s*m(in)?/i,
2016
- /reset(?:s|ting)?\s*(?:in|after|at)?\s*(\d+)\s*h(our|r)?/i,
2017
- /(?:retry|try(?:\s+again)?|available)\s+(?:in|after|at)\s*(\d+)\s*s(ec)?/i,
2018
- /(?:retry|try(?:\s+again)?|available)\s+(?:in|after|at)\s*(\d+)\s*m(in)?/i,
2019
- /(?:retry|try(?:\s+again)?|available)\s+(?:in|after|at)\s*(\d+)\s*h(our|r)?/i
2020
- ];
2021
- function parseResetTimeMs(errorMessage) {
2022
- if (!errorMessage)
2023
- return;
2024
- let now = Date.now();
2025
- for (let pattern of RESET_TIME_PATTERNS) {
2026
- let match = errorMessage.match(pattern);
2027
- if (!match)
2028
- continue;
2029
- let value = Number.parseInt(match[1] ?? "", 10);
2030
- if (!Number.isFinite(value) || value <= 0)
2031
- continue;
2032
- let unit = pattern.source.includes("\\s*h") ? 36e5 : pattern.source.includes("\\s*m") ? 6e4 : 1e3;
2033
- return now + value * unit;
2034
- }
2035
- let isoMatch = errorMessage.match(/(?:reset|available).{0,12}(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(:\d{2})?(?:\.\d+)?(?:Z|[+-]\d{2}:?\d{2})?)/i);
2036
- if (isoMatch?.[1]) {
2037
- let parsed = Date.parse(isoMatch[1]);
2038
- if (Number.isFinite(parsed) && parsed > now)
2039
- return parsed;
2040
- }
2041
- }
2042
-
2043
- // packages/coding-agent/dist/core/subscriptions.js
2044
- var SubscriptionManager = class _SubscriptionManager {
2045
- data = {};
2046
- loaded = !1;
2047
- storage;
2048
- authStorage;
2049
- // In-process write queue so mutations serialize even before the file lock.
2050
- queue = Promise.resolve();
2051
- // Per-provider ids of keys exhausted without a parseable reset time.
2052
- // Process-local on purpose: infinite exhaustion is never persisted.
2053
- memoryExhausted = /* @__PURE__ */ new Map();
2054
- constructor(authStorage, storage) {
2055
- this.authStorage = authStorage, this.storage = storage;
2056
- }
2057
- static create(authStorage, path) {
2058
- return new _SubscriptionManager(authStorage, new FileAuthStorageBackend(path ?? join5(getAgentDir(), "subscriptions.json")));
2059
- }
2060
- static fromStorage(authStorage, storage) {
2061
- return new _SubscriptionManager(authStorage, storage);
2062
- }
2063
- static inMemory(authStorage, data = {}) {
2064
- let storage = new InMemoryAuthStorageBackend();
2065
- return storage.withLock(() => ({ result: void 0, next: JSON.stringify(data, null, 2) })), _SubscriptionManager.fromStorage(authStorage, storage);
2066
- }
2067
- parseStorageData(content) {
2068
- return content ? JSON.parse(content) : {};
2069
- }
2070
- ensureLoaded() {
2071
- if (this.loaded)
2072
- return;
2073
- this.loaded = !0;
2074
- let content;
2075
- try {
2076
- this.storage.withLock((current) => (content = current, { result: void 0 })), this.data = this.parseStorageData(content);
2077
- } catch {
2078
- }
2079
- }
2080
- enqueue(fn) {
2081
- let next = this.queue.then(fn);
2082
- return this.queue = next.catch(() => {
2083
- }), next;
2084
- }
2085
- persist() {
2086
- return this.storage.withLockAsync(async () => ({
2087
- result: void 0,
2088
- next: JSON.stringify(this.data, null, 2)
2089
- }));
2090
- }
2091
- /** Raw stored credential read via the modify path (returning undefined leaves it unchanged). */
2092
- async readRawCredential(providerId) {
2093
- let current;
2094
- return await this.authStorage.modify(providerId, async (credential) => {
2095
- current = credential;
2096
- }), current;
2097
- }
2098
- /**
2099
- * Pool for a provider, lazy-importing an existing stored api_key credential
2100
- * as "Sub 1" on first access. OAuth credentials are not imported.
2101
- */
2102
- async ensurePool(providerId) {
2103
- this.ensureLoaded();
2104
- let existing = this.data[providerId];
2105
- if (existing)
2106
- return existing;
2107
- let credential = await this.readRawCredential(providerId);
2108
- if (credential?.type !== "api_key" || credential.key === void 0)
2109
- return;
2110
- let pool = {
2111
- active: "1",
2112
- keys: [{ id: "1", name: "Sub 1", key: credential.key, addedAt: Date.now() }]
2113
- };
2114
- return this.data = { ...this.data, [providerId]: pool }, await this.persist(), pool;
2115
- }
2116
- nextId(pool) {
2117
- let max = 0;
2118
- for (let entry of pool.keys) {
2119
- let numeric = Number.parseInt(entry.id, 10);
2120
- Number.isFinite(numeric) && numeric > max && (max = numeric);
2121
- }
2122
- return String(max + 1);
2123
- }
2124
- async mirrorActive(providerId, key) {
2125
- await this.authStorage.modify(providerId, async () => ({ type: "api_key", key }));
2126
- }
2127
- async list(providerId) {
2128
- return this.enqueue(async () => {
2129
- let pool = await this.ensurePool(providerId);
2130
- return pool ? [...pool.keys] : [];
2131
- });
2132
- }
2133
- async getActive(providerId) {
2134
- return this.enqueue(async () => {
2135
- let pool = await this.ensurePool(providerId);
2136
- return pool?.keys.find((entry) => entry.id === pool.active);
2137
- });
2138
- }
2139
- async addKey(providerId, key, name) {
2140
- return this.enqueue(async () => {
2141
- this.ensureLoaded();
2142
- let pool = await this.ensurePool(providerId), id = pool ? this.nextId(pool) : "1", entry = { id, name: name ?? `Sub ${id}`, key, addedAt: Date.now() }, keys = [...pool?.keys ?? [], entry];
2143
- return this.data = { ...this.data, [providerId]: { active: id, keys } }, await this.persist(), await this.mirrorActive(providerId, key), entry;
2144
- });
2145
- }
2146
- async removeKey(providerId, id) {
2147
- return this.enqueue(async () => {
2148
- let pool = await this.ensurePool(providerId);
2149
- if (!pool || !pool.keys.some((entry) => entry.id === id))
2150
- return;
2151
- let keys = pool.keys.filter((entry) => entry.id !== id);
2152
- if (this.memoryExhausted.get(providerId)?.delete(id), keys.length === 0) {
2153
- let data = { ...this.data };
2154
- delete data[providerId], this.data = data, await this.persist(), await this.authStorage.delete(providerId);
2155
- return;
2156
- }
2157
- let active = pool.active;
2158
- if (active === id) {
2159
- active = keys[0]?.id ?? active, this.data = { ...this.data, [providerId]: { active, keys } }, await this.persist();
2160
- let promoted = keys.find((entry) => entry.id === active);
2161
- promoted && await this.mirrorActive(providerId, promoted.key);
2162
- return;
2163
- }
2164
- this.data = { ...this.data, [providerId]: { active, keys } }, await this.persist();
2165
- });
2166
- }
2167
- async renameKey(providerId, id, name) {
2168
- return this.enqueue(async () => {
2169
- let pool = await this.ensurePool(providerId);
2170
- if (!pool)
2171
- return;
2172
- let keys = pool.keys.map((entry) => entry.id === id ? { ...entry, name } : entry);
2173
- this.data = { ...this.data, [providerId]: { ...pool, keys } }, await this.persist();
2174
- });
2175
- }
2176
- async setActive(providerId, id) {
2177
- return this.enqueue(async () => {
2178
- let pool = await this.ensurePool(providerId), entry = pool?.keys.find((candidate) => candidate.id === id);
2179
- !pool || !entry || (this.data = { ...this.data, [providerId]: { ...pool, active: id } }, await this.persist(), await this.mirrorActive(providerId, entry.key));
2180
- });
2181
- }
2182
- /**
2183
- * Mark the active key exhausted and rotate to the next non-exhausted key in
2184
- * round-robin order. A parseable reset time is persisted as exhaustedUntil;
2185
- * otherwise the exhaustion is process-local only. Returns the new active key,
2186
- * or null when no non-exhausted alternative exists (current key stays active).
2187
- */
2188
- async rotateOnFailure(providerId, errorMessage, now = Date.now()) {
2189
- return this.enqueue(async () => {
2190
- let pool = await this.ensurePool(providerId);
2191
- if (!pool)
2192
- return null;
2193
- let currentIndex = pool.keys.findIndex((entry) => entry.id === pool.active);
2194
- if (currentIndex === -1)
2195
- return null;
2196
- let current = pool.keys[currentIndex];
2197
- if (!current)
2198
- return null;
2199
- let resetAt = parseResetTimeMs(errorMessage), keys = pool.keys;
2200
- if (resetAt !== void 0 && resetAt > now)
2201
- keys = pool.keys.map((entry) => entry.id === current.id ? { ...entry, exhaustedUntil: resetAt, lastError: errorMessage } : entry);
2202
- else {
2203
- let set = this.memoryExhausted.get(providerId) ?? /* @__PURE__ */ new Set();
2204
- set.add(current.id), this.memoryExhausted.set(providerId, set);
2205
- }
2206
- let isExhausted = (entry) => this.memoryExhausted.get(providerId)?.has(entry.id) === !0 || entry.exhaustedUntil !== void 0 && entry.exhaustedUntil > now;
2207
- for (let offset = 1; offset < keys.length; offset++) {
2208
- let candidate = keys[(currentIndex + offset) % keys.length];
2209
- if (!(!candidate || isExhausted(candidate)))
2210
- return this.data = { ...this.data, [providerId]: { active: candidate.id, keys } }, await this.persist(), await this.mirrorActive(providerId, candidate.key), candidate;
2211
- }
2212
- return keys !== pool.keys && (this.data = { ...this.data, [providerId]: { ...pool, keys } }, await this.persist()), null;
2213
- });
2214
- }
2215
- /** Manual reactivate: clears persisted and process-local exhaustion for a key. */
2216
- async clearExhaustion(providerId, id) {
2217
- return this.enqueue(async () => {
2218
- this.memoryExhausted.get(providerId)?.delete(id);
2219
- let pool = await this.ensurePool(providerId);
2220
- if (!pool)
2221
- return;
2222
- let target = pool.keys.find((entry) => entry.id === id);
2223
- if (!target || target.exhaustedUntil === void 0 && target.lastError === void 0)
2224
- return;
2225
- let keys = pool.keys.map((entry) => {
2226
- if (entry.id !== id)
2227
- return entry;
2228
- let { exhaustedUntil: _exhaustedUntil, lastError: _lastError, ...rest } = entry;
2229
- return rest;
2230
- });
2231
- this.data = { ...this.data, [providerId]: { ...pool, keys } }, await this.persist();
2232
- });
2233
- }
2234
- };
2235
-
2236
- // packages/coding-agent/dist/core/user-models.js
2237
- import { existsSync as existsSync4, mkdirSync as mkdirSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync4 } from "node:fs";
2238
- import { dirname as dirname4, join as join6 } from "node:path";
2239
- var USER_MODELS_FILENAME = "user-models.json";
2240
- function userModelsPath(agentDir = getAgentDir()) {
2241
- return join6(agentDir, USER_MODELS_FILENAME);
2242
- }
2243
- function isRecord3(value) {
2244
- return typeof value == "object" && value !== null && !Array.isArray(value);
2245
- }
2246
- function asFiniteNumber3(value) {
2247
- if (typeof value == "number" && Number.isFinite(value))
2248
- return value;
2249
- }
2250
- function parseUserEntry(value) {
2251
- if (!isRecord3(value))
2252
- return;
2253
- let id = typeof value.id == "string" ? value.id.trim() : "", provider = typeof value.provider == "string" ? value.provider.trim() : "";
2254
- if (!id || !provider)
2255
- return;
2256
- let parsedInput = Array.isArray(value.input) ? value.input.filter((entry) => entry === "text" || entry === "image") : ["text"], input = parsedInput.length > 0 ? parsedInput : ["text"], cost = isRecord3(value.cost) ? {
2257
- input: asFiniteNumber3(value.cost.input) ?? 0,
2258
- output: asFiniteNumber3(value.cost.output) ?? 0,
2259
- cacheRead: asFiniteNumber3(value.cost.cacheRead) ?? 0,
2260
- cacheWrite: asFiniteNumber3(value.cost.cacheWrite) ?? 0
2261
- } : { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
2262
- return {
2263
- id,
2264
- name: typeof value.name == "string" && value.name.trim() ? value.name : id,
2265
- api: typeof value.api == "string" && value.api.trim() ? value.api : "openai-completions",
2266
- provider,
2267
- baseUrl: typeof value.baseUrl == "string" ? value.baseUrl : "",
2268
- reasoning: value.reasoning === !0,
2269
- input,
2270
- cost,
2271
- contextWindow: asFiniteNumber3(value.contextWindow) ?? 128e3,
2272
- maxTokens: asFiniteNumber3(value.maxTokens) ?? 8192,
2273
- compat: isRecord3(value.compat) ? value.compat : void 0,
2274
- thinkingLevelMap: isRecord3(value.thinkingLevelMap) ? value.thinkingLevelMap : void 0,
2275
- source: "user"
2276
- };
2277
- }
2278
- function emptyUserModels() {
2279
- return { version: 1, models: [] };
2280
- }
2281
- function readUserModels(path) {
2282
- try {
2283
- if (!existsSync4(path))
2284
- return emptyUserModels();
2285
- let parsed = JSON.parse(readFileSync4(path, "utf-8"));
2286
- if (!isRecord3(parsed) || !Array.isArray(parsed.models))
2287
- return emptyUserModels();
2288
- let models = [];
2289
- for (let entry of parsed.models) {
2290
- let model = parseUserEntry(entry);
2291
- model && models.push(model);
2292
- }
2293
- return { version: asFiniteNumber3(parsed.version) ?? 1, models };
2294
- } catch {
2295
- return emptyUserModels();
2296
- }
2297
- }
2298
- function writeUserModels(file, path) {
2299
- mkdirSync4(dirname4(path), { recursive: !0, mode: 448 }), writeFileSync4(path, `${JSON.stringify({ version: file.version ?? 1, models: file.models }, null, 2)}
2300
- `, "utf-8");
2301
- }
2302
- function evictUserModelsOnOfficial(user, officialKeys) {
2303
- let hits = new Set(officialKeys), kept = [], evicted = [];
2304
- for (let model of user.models)
2305
- hits.has(modelKey(model.provider, model.id)) ? evicted.push(model) : kept.push(model);
2306
- return { next: { version: user.version, models: kept }, evicted };
2307
- }
2308
- function evictUserModelsByProvider(user, providerId) {
2309
- let kept = [], evicted = [];
2310
- for (let model of user.models)
2311
- model.provider === providerId ? evicted.push(model) : kept.push(model);
2312
- return { next: { version: user.version, models: kept }, evicted };
2313
- }
2314
- function upsertUserModels(existing, rows) {
2315
- let byKey = new Map(existing.models.map((model) => [modelKey(model.provider, model.id), model]));
2316
- for (let row of rows)
2317
- byKey.set(modelKey(row.provider, row.id), { ...row, source: "user" });
2318
- return { version: existing.version ?? 1, models: [...byKey.values()] };
2319
- }
2320
- function userEntryToModel(entry) {
2321
- return {
2322
- id: entry.id,
2323
- name: entry.name,
2324
- api: entry.api,
2325
- provider: entry.provider,
2326
- baseUrl: entry.baseUrl,
2327
- reasoning: entry.reasoning,
2328
- input: entry.input,
2329
- cost: entry.cost,
2330
- contextWindow: entry.contextWindow,
2331
- maxTokens: entry.maxTokens,
2332
- compat: entry.compat,
2333
- thinkingLevelMap: entry.thinkingLevelMap
2334
- };
2335
- }
2336
- var UserModelsStore = class {
2337
- path;
2338
- file;
2339
- constructor(path) {
2340
- this.path = path, this.file = path ? readUserModels(path) : emptyUserModels();
2341
- }
2342
- list() {
2343
- return this.file.models;
2344
- }
2345
- keys() {
2346
- return new Set(this.file.models.map((model) => modelKey(model.provider, model.id)));
2347
- }
2348
- modelsFor(providerId) {
2349
- return this.file.models.filter((model) => model.provider === providerId).map(userEntryToModel);
2350
- }
2351
- evictOfficial(officialKeys) {
2352
- let { next, evicted } = evictUserModelsOnOfficial(this.file, officialKeys);
2353
- return evicted.length > 0 && (this.file = next, this.persist()), evicted;
2354
- }
2355
- evictProvider(providerId) {
2356
- let { next, evicted } = evictUserModelsByProvider(this.file, providerId);
2357
- return evicted.length > 0 && (this.file = next, this.persist()), evicted;
2358
- }
2359
- upsert(rows) {
2360
- rows.length !== 0 && (this.file = upsertUserModels(this.file, rows), this.persist());
2361
- }
2362
- persist() {
2363
- if (this.path)
2364
- try {
2365
- writeUserModels(this.file, this.path);
2366
- } catch {
2367
- }
2368
- }
2369
- };
2370
-
2371
- // packages/coding-agent/dist/core/model-runtime.js
2372
- function mergeHeaders(base, override) {
2373
- if (!base && !override)
2374
- return;
2375
- let merged = { ...base };
2376
- for (let [name, value] of Object.entries(override ?? {})) {
2377
- let lowerName = name.toLowerCase();
2378
- for (let existingName of Object.keys(merged))
2379
- existingName.toLowerCase() === lowerName && delete merged[existingName];
2380
- merged[name] = value;
2381
- }
2382
- return merged;
2383
- }
2384
- var ModelRuntime = class _ModelRuntime {
2385
- models;
2386
- credentials;
2387
- /** lunr: per-provider subscription-key pools; rotation mirrors the active key into the credential store. */
2388
- subscriptionManager;
2389
- defaultBuiltins;
2390
- builtins = /* @__PURE__ */ new Map();
2391
- extensionProviders = /* @__PURE__ */ new Map();
2392
- compositionErrors = /* @__PURE__ */ new Map();
2393
- modelsPath;
2394
- allowModelNetwork;
2395
- config;
2396
- snapshot = {
2397
- all: [],
2398
- available: [],
2399
- configuredProviders: /* @__PURE__ */ new Set(),
2400
- storedProviders: /* @__PURE__ */ new Set(),
2401
- auth: /* @__PURE__ */ new Map()
2402
- };
2403
- availabilityRefresh;
2404
- availabilityError;
2405
- modelsStore;
2406
- overlay = new CatalogOverlaySource();
2407
- userModels;
2408
- officialCachePath;
2409
- lastCatalogRefresh = { aborted: !1, errors: /* @__PURE__ */ new Map(), live: [], incomplete: [] };
2410
- lastOfficial;
2411
- catalogRefresh;
2412
- catalogRefreshAllowsNetwork = !1;
2413
- nextAutomaticRefresh = 0;
2414
- automaticRefreshIdentity = "";
2415
- grokHome;
2416
- constructor(credentials, config, modelsPath, modelsStore, providers, allowModelNetwork, subscriptionManager, catalogDir, grokHome) {
2417
- this.credentials = credentials, this.config = config, this.modelsPath = modelsPath, this.modelsStore = modelsStore, this.allowModelNetwork = allowModelNetwork, this.subscriptionManager = subscriptionManager, this.userModels = new UserModelsStore(catalogDir ? userModelsPath(catalogDir) : void 0), this.officialCachePath = catalogDir ? officialCatalogCachePath(catalogDir) : void 0, this.grokHome = grokHome, this.defaultBuiltins = new Map(providers.map((provider) => [provider.id, provider]));
2418
- for (let [providerId, provider] of this.defaultBuiltins)
2419
- this.builtins.set(providerId, provider);
2420
- this.models = createModels({ credentials, modelsStore }), this.rebuildProviders();
2421
- }
2422
- static async create(options = {}) {
2423
- let rawStore = options.credentials ?? AuthStorage.create(options.authPath), grokHomeDisabled = options.grokHome === null || options.grokHome === void 0 && options.credentials !== void 0, grokHome = grokHomeDisabled ? void 0 : options.grokHome ?? void 0, baseStore = grokHomeDisabled ? rawStore : wrapXaiGrokCliCredentials(rawStore, { grokHome }), credentials = new RuntimeCredentials(baseStore), subscriptionManager = options.subscriptions ?? (options.credentials && !options.authPath ? SubscriptionManager.inMemory(baseStore) : SubscriptionManager.create(baseStore, options.authPath ? join7(dirname5(options.authPath), "subscriptions.json") : void 0)), modelsPath = options.modelsPath === null ? void 0 : options.modelsPath ?? join7(getAgentDir(), "models.json"), config = await ModelConfig.load(modelsPath), modelsStore = options.modelsStore ?? (modelsPath ? new FileModelsStore(options.modelsStorePath ?? join7(dirname5(modelsPath), "models-store.json")) : new InMemoryCodingAgentModelsStore()), providers = builtinProviderCatalog.builtinProviders(), catalogDir = modelsPath ? dirname5(modelsPath) : options.authPath ? dirname5(options.authPath) : void 0, runtime = new _ModelRuntime(credentials, config, modelsPath, modelsStore, providers, options.allowModelNetwork ?? process.env.PI_OFFLINE === void 0, subscriptionManager, catalogDir, grokHome);
2424
- return runtime.configureRadiusProviders(), runtime.rebuildProviders(), await runtime.refresh({ allowNetwork: !1 }), runtime;
2425
- }
2426
- configureRadiusProviders() {
2427
- this.builtins.clear();
2428
- for (let [providerId, provider] of this.defaultBuiltins)
2429
- this.builtins.set(providerId, provider);
2430
- for (let providerId of this.config.getProviderIds()) {
2431
- let config = this.config.getProvider(providerId);
2432
- config?.oauth !== "radius" || !config.baseUrl || this.builtins.set(providerId, builtinProviderCatalog.radiusProvider({
2433
- id: providerId,
2434
- name: config.name ?? providerId,
2435
- gateway: config.baseUrl.replace(/\/v1\/?$/u, "")
2436
- }));
2437
- }
2438
- }
2439
- providerIds() {
2440
- return /* @__PURE__ */ new Set([...this.builtins.keys(), ...this.config.getProviderIds(), ...this.extensionProviders.keys()]);
2441
- }
2442
- recomposeProvider(providerId) {
2443
- let base = this.builtins.get(providerId), extension = this.extensionProviders.get(providerId);
2444
- if (!base && !this.config.getProvider(providerId) && !extension) {
2445
- this.models.deleteProvider(providerId), this.compositionErrors.delete(providerId);
2446
- return;
2447
- }
2448
- if (base && !this.config.getProvider(providerId) && !extension) {
2449
- this.models.setProvider(this.withLocalCatalog(base)), this.compositionErrors.delete(providerId);
2450
- return;
2451
- }
2452
- try {
2453
- this.models.setProvider(composeModelProvider(providerId, base ? this.withLocalCatalog(base) : void 0, this.config, extension)), this.compositionErrors.delete(providerId);
2454
- } catch (error) {
2455
- this.compositionErrors.set(providerId, error instanceof Error ? error.message : String(error)), base ? this.models.setProvider(this.withLocalCatalog(base)) : this.models.deleteProvider(providerId);
2456
- }
2457
- }
2458
- withLocalCatalog(provider) {
2459
- return withCatalogOverlay(provider, this.overlay);
2460
- }
2461
- bakedInModels(providerId) {
2462
- return [...this.defaultBuiltins.get(providerId)?.getModels() ?? []];
2463
- }
2464
- rebuildProviders() {
2465
- this.models.clearProviders(), this.compositionErrors.clear();
2466
- for (let providerId of this.providerIds())
2467
- this.recomposeProvider(providerId);
2468
- this.updateModelSnapshot();
2469
- }
2470
- updateModelSnapshot() {
2471
- let all = [...this.models.getModels()];
2472
- this.snapshot = {
2473
- ...this.snapshot,
2474
- all,
2475
- available: all.filter((model) => this.snapshot.configuredProviders.has(model.provider) && this.isCatalogModelAvailable(model))
2476
- };
2477
- }
2478
- isCatalogModelAvailable(model) {
2479
- return !!this.config.getProvider(model.provider)?.models?.some((row) => row.id === model.id) || !!this.extensionProviders.get(model.provider)?.models?.some((row) => row.id === model.id) || this.overlay.isAvailable(model);
2480
- }
2481
- async listStoredProviderIds() {
2482
- let credentials = await this.credentials.list();
2483
- return new Set(credentials.map((entry) => entry.providerId));
2484
- }
2485
- /** `/model` lists stored creds + models.json/extension keys, never ambient envApiKeyAuth. */
2486
- configuredProviderIds(storedProviders) {
2487
- let configured = new Set(storedProviders);
2488
- for (let provider of this.models.getProviders())
2489
- configuredRequestAuthStatus(this.config.getProvider(provider.id), this.extensionProviders.get(provider.id))?.configured && configured.add(provider.id);
2490
- return configured;
2491
- }
2492
- userModelsForStoredProviders(storedProviders) {
2493
- return this.userModels.list().filter((row) => storedProviders.has(row.provider)).map(userEntryToModel);
2494
- }
2495
- async runAvailabilityRefresh() {
2496
- let providers = this.models.getProviders(), [available, checks, storedProviders] = await Promise.all([
2497
- this.models.getAvailable(),
2498
- Promise.all(providers.map(async (provider) => [
2499
- provider.id,
2500
- await this.models.checkAuth(provider.id)
2501
- ])),
2502
- this.listStoredProviderIds()
2503
- ]), auth = new Map(checks), configuredProviders = this.configuredProviderIds(storedProviders);
2504
- this.snapshot = {
2505
- all: [...this.models.getModels()],
2506
- available: available.filter((model) => configuredProviders.has(model.provider) && this.isCatalogModelAvailable(model)),
2507
- configuredProviders,
2508
- storedProviders,
2509
- auth
2510
- }, this.availabilityError = void 0;
2511
- }
2512
- queueAvailabilityRefresh(after) {
2513
- let tracked = (after ?? Promise.resolve()).catch(() => {
2514
- }).then(() => this.runAvailabilityRefresh()).catch((error) => {
2515
- throw this.availabilityError = error instanceof Error ? error.message : String(error), error;
2516
- }).finally(() => {
2517
- this.availabilityRefresh === tracked && (this.availabilityRefresh = void 0);
2518
- });
2519
- return this.availabilityRefresh = tracked, tracked;
2520
- }
2521
- /** Coalesce concurrent readers onto the pending refresh. */
2522
- refreshAvailability() {
2523
- return this.availabilityRefresh ?? this.queueAvailabilityRefresh(void 0);
2524
- }
2525
- /** Mutations must not observe an in-flight refresh started before them. */
2526
- forceRefreshAvailability() {
2527
- return this.queueAvailabilityRefresh(this.availabilityRefresh);
2528
- }
2529
- getProviders() {
2530
- return this.models.getProviders();
2531
- }
2532
- getProvider(providerId) {
2533
- return this.models.getProvider(providerId);
2534
- }
2535
- getModels(providerId) {
2536
- return this.models.getModels(providerId);
2537
- }
2538
- getModel(providerId, modelId) {
2539
- return this.models.getModel(providerId, modelId);
2540
- }
2541
- async checkAuth(providerId) {
2542
- return this.models.checkAuth(providerId);
2543
- }
2544
- async getAvailable(providerId) {
2545
- if (providerId) {
2546
- if (this.availabilityRefresh)
2547
- return await this.availabilityRefresh, this.snapshot.available.filter((model) => model.provider === providerId);
2548
- try {
2549
- return (await this.models.getAvailable(providerId)).filter((model) => this.isCatalogModelAvailable(model));
2550
- } catch (error) {
2551
- throw this.availabilityError = error instanceof Error ? error.message : String(error), error;
2552
- }
2553
- }
2554
- return await this.refreshAvailability(), this.snapshot.available;
2555
- }
2556
- getAvailableSnapshot() {
2557
- return this.snapshot.available;
2558
- }
2559
- getError() {
2560
- let errors = [], configError = this.config.getError();
2561
- configError && errors.push(configError);
2562
- for (let [providerId, error] of this.compositionErrors)
2563
- errors.push(`Provider "${providerId}": ${error}`);
2564
- return this.availabilityError && errors.push(`Availability refresh: ${this.availabilityError}`), errors.length > 0 ? errors.join(`
3
+ TODO_TOOL_NAMES
4
+ } from "./chunk-CCCN2UCX.js";
5
+ import {
6
+ DefaultResourceLoader,
7
+ createSyntheticSourceInfo,
8
+ expandPromptTemplate,
9
+ formatSkillsForPrompt
10
+ } from "./chunk-IQIEU7SB.js";
11
+ import {
12
+ stripFrontmatter
13
+ } from "./chunk-QFWG2RVL.js";
14
+ import {
15
+ createAllToolDefinitions,
16
+ createLocalBashOperations,
17
+ createToolDefinitionFromAgentTool,
18
+ wrapToolDefinition
19
+ } from "./chunk-VSSXXL36.js";
20
+ import {
21
+ DEFAULT_MAX_BYTES,
22
+ truncateTail
23
+ } from "./chunk-53YJI7JU.js";
24
+ import {
25
+ stripAnsi
26
+ } from "./chunk-5ZQXRPMC.js";
27
+ import {
28
+ ModelRuntime,
29
+ isAuthInvalidError,
30
+ isUsageLimitError
31
+ } from "./chunk-GS66LV4M.js";
32
+ import {
33
+ SettingsManager
34
+ } from "./chunk-WADV2VDS.js";
35
+ import {
36
+ DEFAULT_THINKING_LEVEL,
37
+ calculateContextTokens,
38
+ collectEntriesForBranchSummary,
39
+ compact,
40
+ estimateContextTokens,
41
+ estimateTokens,
42
+ findInitialModel,
43
+ generateBranchSummary,
44
+ prepareCompaction,
45
+ shouldCompact
46
+ } from "./chunk-OFKSVRV7.js";
47
+ import {
48
+ ExtensionRunner,
49
+ emitSessionShutdownEvent
50
+ } from "./chunk-5BNJ4JUH.js";
51
+ import {
52
+ getSubagentCancellation
53
+ } from "./chunk-BBUVIEZB.js";
54
+ import {
55
+ gateToolCall
56
+ } from "./chunk-5D7LC2ZQ.js";
57
+ import {
58
+ isUserInstructionsPath,
59
+ loadSelectedUserInstructions
60
+ } from "./chunk-M3LZLQW2.js";
61
+ import {
62
+ list
63
+ } from "./chunk-KKUTQQV7.js";
64
+ import {
65
+ sanitizeBinaryOutput
66
+ } from "./chunk-CSFI6YXL.js";
67
+ import {
68
+ SessionTransferError
69
+ } from "./chunk-AZJHNQKQ.js";
70
+ import {
71
+ CURRENT_SESSION_VERSION,
72
+ SessionManager,
73
+ getDefaultSessionDir,
74
+ getLatestCompactionEntry
75
+ } from "./chunk-XLTL257W.js";
76
+ import {
77
+ convertToLlm
78
+ } from "./chunk-FVDOXRUD.js";
79
+ import {
80
+ MEMORY_TOOL_NAMES
81
+ } from "./chunk-UJOCPOMX.js";
82
+ import {
83
+ SessionOwnership,
84
+ canonicalSessionPath
85
+ } from "./chunk-UAEOTO52.js";
86
+ import {
87
+ measureStartup,
88
+ time
89
+ } from "./chunk-PVCDKGR6.js";
90
+ import {
91
+ getThemeByName,
92
+ theme
93
+ } from "./chunk-7QWNYZDI.js";
94
+ import {
95
+ CONFIG_DIR_NAME,
96
+ getAgentDir,
97
+ getDocsPath,
98
+ getExamplesPath,
99
+ getReadmePath,
100
+ resolvePath
101
+ } from "./chunk-FQMM2EZ2.js";
2565
102
 
2566
- `) : void 0;
2567
- }
2568
- getRegisteredProviderConfig(providerId) {
2569
- return this.extensionProviders.get(providerId);
2570
- }
2571
- getRegisteredProviderIds() {
2572
- return [...this.extensionProviders.keys()];
2573
- }
2574
- /** @internal Compatibility fallback for ModelRegistry when provider auth is unconfigured. */
2575
- getCompatibilityRequestConfig(model) {
2576
- return resolveCompatibilityRequestConfig(model, this.config.getProvider(model.provider), this.extensionProviders.get(model.provider));
2577
- }
2578
- isUsingOAuth(providerId) {
2579
- return this.snapshot.auth.get(providerId)?.type === "oauth";
2580
- }
2581
- hasConfiguredAuth(providerId) {
2582
- return this.snapshot.configuredProviders.has(providerId);
2583
- }
2584
- async getAuth(providerOrModel, overrides = {}) {
2585
- if (typeof providerOrModel == "string")
2586
- return this.models.getAuth(providerOrModel, overrides);
2587
- let resolution = await this.models.getAuth(providerOrModel, overrides);
2588
- if (!resolution)
2589
- return;
2590
- let configuredHeaders2 = resolveConfiguredModelHeaders(providerOrModel, this.config.getProvider(providerOrModel.provider), this.extensionProviders.get(providerOrModel.provider), { ...resolution.env ?? {}, ...overrides.env ?? {} });
2591
- return {
2592
- ...resolution,
2593
- auth: {
2594
- ...resolution.auth,
2595
- headers: mergeHeaders(resolution.auth.headers, configuredHeaders2)
2596
- }
2597
- };
2598
- }
2599
- /** lunr: whether a runtime --api-key override is active for the provider (it shadows auth.json). */
2600
- hasRuntimeApiKey(providerId) {
2601
- return this.credentials.hasRuntimeApiKey(providerId);
2602
- }
2603
- async setRuntimeApiKey(providerId, apiKey, options) {
2604
- this.credentials.setRuntimeApiKey(providerId, apiKey);
2605
- let auth = new Map(this.snapshot.auth).set(providerId, { type: "api_key", source: "runtime API key" }), configuredProviders = new Set(this.snapshot.configuredProviders).add(providerId), storedProviders = new Set(this.snapshot.storedProviders).add(providerId);
2606
- this.snapshot = {
2607
- ...this.snapshot,
2608
- auth,
2609
- configuredProviders,
2610
- storedProviders,
2611
- available: this.snapshot.all.filter((model) => configuredProviders.has(model.provider) && this.isCatalogModelAvailable(model))
2612
- }, await this.refresh({ allowNetwork: options?.allowNetwork ?? this.allowModelNetwork });
2613
- }
2614
- async removeRuntimeApiKey(providerId) {
2615
- this.credentials.removeRuntimeApiKey(providerId), await this.refresh({ allowNetwork: this.allowModelNetwork });
2616
- }
2617
- /** lunr: whether network model-catalog fetches are allowed (offline mode disables them). */
2618
- isNetworkAllowed() {
2619
- return this.allowModelNetwork;
2620
- }
2621
- listCredentials() {
2622
- return this.credentials.list();
2623
- }
2624
- getProviderAuthStatus(providerId) {
2625
- if (this.credentials.hasRuntimeApiKey(providerId))
2626
- return { configured: !0, source: "runtime" };
2627
- if (this.snapshot.storedProviders.has(providerId))
2628
- return { configured: !0, source: "stored" };
2629
- let configured = configuredRequestAuthStatus(this.config.getProvider(providerId), this.extensionProviders.get(providerId));
2630
- if (configured)
2631
- return configured;
2632
- let check = this.snapshot.auth.get(providerId);
2633
- return check ? { configured: !0, source: "environment", label: check.source } : { configured: !1 };
2634
- }
2635
- async prepareRequest(model, options) {
2636
- let provider = this.models.getProvider(model.provider);
2637
- if (!provider)
2638
- throw new ModelsError("provider", `Unknown provider: ${model.provider}`);
2639
- let resolution = await this.getAuth(model, { apiKey: options?.apiKey, env: options?.env });
2640
- if (!resolution)
2641
- throw new ModelsError("auth", `Provider is not configured: ${model.provider}`);
2642
- let { transformHeaders, ...providerOptions } = options ?? {}, headers = mergeHeaders(resolution.auth.headers, providerOptions.headers);
2643
- transformHeaders && (headers = await transformHeaders(headers ?? {}));
2644
- let env = resolution.env || providerOptions.env ? { ...resolution.env ?? {}, ...providerOptions.env ?? {} } : void 0;
2645
- return {
2646
- provider,
2647
- model: resolution.auth.baseUrl ? { ...model, baseUrl: resolution.auth.baseUrl } : model,
2648
- options: {
2649
- ...providerOptions,
2650
- apiKey: providerOptions.apiKey ?? resolution.auth.apiKey,
2651
- headers,
2652
- env
2653
- }
2654
- };
2655
- }
2656
- stream(model, context, options) {
2657
- return lazyStream2(model, async () => {
2658
- let prepared = await this.prepareRequest(model, options);
2659
- return prepared.provider.stream(prepared.model, context, prepared.options);
2660
- });
2661
- }
2662
- complete(model, context, options) {
2663
- return this.stream(model, context, options).result();
2664
- }
2665
- streamSimple(model, context, options) {
2666
- return lazyStream2(model, async () => {
2667
- let prepared = await this.prepareRequest(model, options);
2668
- return prepared.provider.streamSimple(prepared.model, context, prepared.options);
2669
- });
2670
- }
2671
- completeSimple(model, context, options) {
2672
- return this.streamSimple(model, context, options).result();
2673
- }
2674
- async login(providerId, type, interaction) {
2675
- let credential = await this.models.login(providerId, type, interaction);
2676
- return clearPlanUsageCache(), await this.refresh({ allowNetwork: this.allowModelNetwork }), credential;
2677
- }
2678
- async logout(providerId) {
2679
- await this.models.logout(providerId), await this.modelsStore.delete(providerId), this.userModels.evictProvider(providerId), this.overlay.setLive(providerId, []), this.recomposeProvider(providerId), clearPlanUsageCache(), await this.refresh({ allowNetwork: this.allowModelNetwork });
2680
- }
2681
- /** Copy a live Grok CLI SuperGrok session into lunR `auth.json`. */
2682
- async importGrokCliXaiAuth() {
2683
- let grok = readGrokCliXaiOAuth({ grokHome: this.grokHome });
2684
- if (!grok)
2685
- return;
2686
- let stored = await this.credentials.modify("xai", async () => grok);
2687
- return clearPlanUsageCache(), await this.refresh({ allowNetwork: this.allowModelNetwork }), stored;
2688
- }
2689
- async reloadConfig() {
2690
- this.config = await ModelConfig.load(this.modelsPath), this.configureRadiusProviders(), this.rebuildProviders(), await this.refresh({ allowNetwork: this.allowModelNetwork });
2691
- }
2692
- async refresh(options = {}) {
2693
- let allowNetwork = options.allowNetwork ?? this.allowModelNetwork;
2694
- if (this.catalogRefresh)
2695
- return this.catalogRefreshAllowsNetwork || !allowNetwork ? this.catalogRefresh : (await this.catalogRefresh.catch(() => {
2696
- }), this.refresh({ ...options, allowNetwork }));
2697
- let run = this.executeCatalogRefresh({ ...options, allowNetwork }).finally(() => {
2698
- this.catalogRefresh === run && (this.catalogRefresh = void 0, this.catalogRefreshAllowsNetwork = !1);
2699
- });
2700
- return this.catalogRefresh = run, this.catalogRefreshAllowsNetwork = allowNetwork, run;
2701
- }
2702
- async executeCatalogRefresh(refreshOptions) {
2703
- let official = await this.refreshOfficialCatalog(refreshOptions.allowNetwork, refreshOptions.signal), live = refreshOptions.allowNetwork ? await this.refreshLiveCatalogs(official ? officialModelKeys(official.catalog) : /* @__PURE__ */ new Set(), refreshOptions.signal) : await this.restoreLiveCatalogs(), result = await this.models.refresh(refreshOptions) ?? {
2704
- aborted: refreshOptions.signal?.aborted ?? !1,
2705
- errors: /* @__PURE__ */ new Map()
2706
- }, errors = new Map(result.errors);
2707
- for (let [id, error] of Object.entries(official?.errors ?? {}))
2708
- errors.set(id, new Error(error));
2709
- for (let entry of live)
2710
- (entry.status === "error" || entry.status === "timeout") && errors.set(entry.providerId, new Error(entry.error ?? entry.status));
2711
- this.updateModelSnapshot();
2712
- try {
2713
- await this.forceRefreshAvailability();
2714
- } catch {
2715
- }
2716
- let catalogResult = {
2717
- aborted: result.aborted,
2718
- errors,
2719
- official,
2720
- live,
2721
- incomplete: live.flatMap((entry) => entry.incomplete)
2722
- };
2723
- return this.lastCatalogRefresh = catalogResult, catalogResult;
2724
- }
2725
- getLastCatalogRefresh() {
2726
- return this.lastCatalogRefresh;
2727
- }
2728
- /** Called after first paint and by the picker; explicit /refresh always bypasses this gate. */
2729
- async refreshIfStale(options = {}) {
2730
- if (!this.allowModelNetwork || options.signal?.aborted)
2731
- return this.lastCatalogRefresh;
2732
- if (this.catalogRefresh)
2733
- return this.refresh({ allowNetwork: !0, signal: options.signal });
2734
- let providers = [...await this.listStoredProviderIds()].sort(), identity = (await Promise.all(providers.map(async (id) => this.scopeFor(id)))).join(":");
2735
- if (identity === this.automaticRefreshIdentity && Date.now() < this.nextAutomaticRefresh)
2736
- return this.lastCatalogRefresh;
2737
- this.automaticRefreshIdentity = identity, this.nextAutomaticRefresh = Date.now() + 6e4;
2738
- let result = await this.refresh({ allowNetwork: !0, signal: options.signal });
2739
- return !result.aborted && !result.errors.size && (this.nextAutomaticRefresh = Date.now() + 36e5), result;
2740
- }
2741
- async scopeFor(providerId) {
2742
- let provider = this.models.getProvider(providerId) ?? this.defaultBuiltins.get(providerId);
2743
- return catalogCacheScope(providerId, provider?.baseUrl ?? "", await this.credentials.read(providerId));
2744
- }
2745
- persistUserModels(rows) {
2746
- this.userModels.upsert(rows), this.overlay.setUser(this.userModelsForStoredProviders(this.snapshot.storedProviders)), this.updateModelSnapshot();
2747
- }
2748
- async refreshOfficialCatalog(allowNetwork, signal) {
2749
- let storedProviders = await this.listStoredProviderIds(), loaded = preferOfficialCatalog(this.lastOfficial, await loadOfficialCatalog({
2750
- allowNetwork,
2751
- cachePath: this.officialCachePath,
2752
- signal,
2753
- providerIds: [...storedProviders]
2754
- }));
2755
- this.lastOfficial = loaded;
2756
- let evicted = this.userModels.evictOfficial(officialModelKeys(loaded.catalog)), templateByProvider = /* @__PURE__ */ new Map(), officialModels = loaded.catalog.models.filter((entry) => storedProviders.has(entry.provider)).map((entry) => (templateByProvider.has(entry.provider) || templateByProvider.set(entry.provider, this.bakedInModels(entry.provider)[0]), officialEntryToModel(entry, templateByProvider.get(entry.provider))));
2757
- return this.overlay.setOfficial(officialModels), this.overlay.setUser(this.userModelsForStoredProviders(storedProviders)), { ...loaded, evictedUserRows: evicted.length };
2758
- }
2759
- async restoreLiveCatalogs() {
2760
- let storedProviders = await this.listStoredProviderIds(), results = [];
2761
- for (let providerId of LIVE_LIST_PROVIDER_IDS) {
2762
- let stored = storedProviders.has(providerId) ? await this.modelsStore.read(providerId) : void 0;
2763
- (!stored?.scope && providerId !== "openai-codex" || stored?.scope === await this.scopeFor(providerId)) && stored?.models ? this.overlay.setLive(providerId, stored.models) : this.overlay.setLive(providerId, []), results.push({
2764
- providerId,
2765
- status: "skipped",
2766
- discoveries: [],
2767
- added: 0,
2768
- total: stored?.models.length ?? 0,
2769
- incomplete: []
2770
- });
2771
- }
2772
- return results;
2773
- }
2774
- async refreshLiveCatalogs(officialKeys, signal) {
2775
- let storedProviders = await this.listStoredProviderIds(), known = knownModelKeys(LIVE_LIST_PROVIDER_IDS.flatMap((id) => this.bakedInModels(id)), officialKeys, this.userModels.keys());
2776
- return await Promise.all(LIVE_LIST_PROVIDER_IDS.map(async (providerId) => {
2777
- if (!storedProviders.has(providerId))
2778
- return this.overlay.setLive(providerId, []), {
2779
- providerId,
2780
- status: "skipped",
2781
- discoveries: [],
2782
- added: 0,
2783
- total: 0,
2784
- incomplete: []
2785
- };
2786
- let stored = await this.modelsStore.read(providerId), initialScope = await this.scopeFor(providerId);
2787
- if (stored?.models && (stored.scope === initialScope || !stored.scope && providerId !== "openai-codex") ? this.overlay.setLive(providerId, stored.models) : this.overlay.setLive(providerId, []), signal?.aborted)
2788
- return {
2789
- providerId,
2790
- status: "skipped",
2791
- discoveries: [],
2792
- added: 0,
2793
- total: stored?.models.length ?? 0,
2794
- incomplete: [],
2795
- error: "aborted"
2796
- };
2797
- let bakedIn = this.bakedInModels(providerId), baseUrl = (this.models.getProvider(providerId) ?? this.defaultBuiltins.get(providerId))?.baseUrl ?? bakedIn[0]?.baseUrl;
2798
- if (!baseUrl)
2799
- return {
2800
- providerId,
2801
- status: "skipped",
2802
- discoveries: [],
2803
- added: 0,
2804
- total: 0,
2805
- incomplete: []
2806
- };
2807
- let credential;
2808
- try {
2809
- credential = await this.refreshCredentialFor(providerId);
2810
- } catch (error) {
2811
- return {
2812
- providerId,
2813
- status: "error",
2814
- discoveries: [],
2815
- added: 0,
2816
- total: stored?.models.length ?? 0,
2817
- incomplete: [],
2818
- error: error instanceof Error ? error.message : String(error)
2819
- };
2820
- }
2821
- if (!credential)
2822
- return {
2823
- providerId,
2824
- status: "skipped",
2825
- discoveries: [],
2826
- added: 0,
2827
- total: stored?.models.length ?? 0,
2828
- incomplete: []
2829
- };
2830
- let requestScope = catalogCacheScope(providerId, baseUrl, credential), result = await fetchLiveProviderModels({
2831
- discoveryClientVersion: stored?.scope === requestScope ? stored.discoveryClientVersion : void 0,
2832
- providerId,
2833
- baseUrl,
2834
- bakedIn,
2835
- credential,
2836
- knownKeys: known,
2837
- signal
2838
- }), accountChanged = await this.scopeFor(providerId) !== requestScope;
2839
- if (accountChanged && this.overlay.setLive(providerId, []), signal?.aborted || accountChanged)
2840
- return { ...result, status: "skipped", discoveries: [], incomplete: [] };
2841
- if (result.status === "ok") {
2842
- let overlayModels = buildLiveOverlay(bakedIn, result.discoveries);
2843
- this.overlay.setLive(providerId, overlayModels);
2844
- try {
2845
- await this.modelsStore.write(providerId, {
2846
- models: overlayModels,
2847
- checkedAt: Date.now(),
2848
- scope: requestScope,
2849
- discoveryClientVersion: result.discoveryClientVersion
2850
- });
2851
- } catch {
2852
- }
2853
- }
2854
- return result;
2855
- }));
2856
- }
2857
- async refreshCredentialFor(providerId) {
2858
- let resolved = await this.getAuth(providerId), stored = await this.credentials.read(providerId);
2859
- if (stored?.type === "oauth")
2860
- return { ...stored, access: resolved?.auth.apiKey ?? stored.access };
2861
- if (resolved?.auth.apiKey)
2862
- return { type: "api_key", key: resolved.auth.apiKey, env: resolved.env };
2863
- if (stored?.type === "api_key" && stored.key)
2864
- return stored;
2865
- }
2866
- registerProvider(providerId, config) {
2867
- validateExtensionProvider(providerId, this.builtins.get(providerId), this.config.getProvider(providerId), config);
2868
- let effective = { ...this.extensionProviders.get(providerId) };
2869
- for (let [key, value] of Object.entries(config))
2870
- value !== void 0 && (effective[key] = value);
2871
- if (this.extensionProviders.set(providerId, effective), this.recomposeProvider(providerId), this.updateModelSnapshot(), this.snapshot.storedProviders.has(providerId) || configuredRequestAuthStatus(this.config.getProvider(providerId), effective)?.configured) {
2872
- let configuredProviders = new Set(this.snapshot.configuredProviders).add(providerId), auth = new Map(this.snapshot.auth);
2873
- auth.get(providerId) || auth.set(providerId, {
2874
- type: effective.oauth && !effective.apiKey ? "oauth" : "api_key",
2875
- source: "configured provider"
2876
- }), this.snapshot = {
2877
- ...this.snapshot,
2878
- auth,
2879
- configuredProviders,
2880
- available: this.snapshot.all.filter((model) => configuredProviders.has(model.provider) && this.isCatalogModelAvailable(model))
2881
- };
2882
- }
2883
- this.refresh({ allowNetwork: !1 });
2884
- }
2885
- unregisterProvider(providerId) {
2886
- this.extensionProviders.delete(providerId), this.recomposeProvider(providerId), this.updateModelSnapshot(), this.refresh({ allowNetwork: !1 });
2887
- }
2888
- };
2889
- async function refreshModelCandidatesForInit(runtime) {
2890
- return await runtime.refresh({ allowNetwork: !1 }), runtime.getAvailableSnapshot();
2891
- }
103
+ // packages/coding-agent/dist/core/agent-session-services.js
104
+ import { join as join7 } from "node:path";
2892
105
 
2893
106
  // packages/coding-agent/dist/core/sdk.js
2894
- import { join as join13 } from "node:path";
107
+ import { join as join6 } from "node:path";
2895
108
  import { Agent } from "@ashx-j/lunr-agent";
2896
109
  import { clampThinkingLevel as clampThinkingLevel2 } from "@ashx-j/lunr-ai";
2897
110
 
2898
111
  // packages/coding-agent/dist/core/agent-session.js
2899
- import { existsSync as existsSync6, mkdirSync as mkdirSync6, readFileSync as readFileSync6, writeFileSync as writeFileSync6 } from "node:fs";
2900
- import { basename, dirname as dirname7, join as join11, resolve as resolve2 } from "node:path";
112
+ import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "node:fs";
113
+ import { basename, dirname as dirname2, join as join4, resolve as resolve2 } from "node:path";
2901
114
  import { clampThinkingLevel, cleanupSessionResources, getSupportedThinkingLevels, isContextOverflow, isRetryableAssistantError, modelsAreEqual, resetApiProviders, streamSimple } from "@ashx-j/lunr-ai/compat";
2902
115
 
2903
116
  // packages/coding-agent/dist/utils/sleep.js
2904
117
  function sleep(ms, signal) {
2905
- return new Promise((resolve4, reject) => {
118
+ return new Promise((resolve3, reject) => {
2906
119
  if (signal?.aborted) {
2907
120
  reject(new Error("Aborted"));
2908
121
  return;
2909
122
  }
2910
- let timeout = setTimeout(resolve4, ms);
123
+ let timeout = setTimeout(resolve3, ms);
2911
124
  signal?.addEventListener("abort", () => {
2912
125
  clearTimeout(timeout), reject(new Error("Aborted"));
2913
126
  });
@@ -2915,13 +128,13 @@ function sleep(ms, signal) {
2915
128
  }
2916
129
 
2917
130
  // packages/coding-agent/dist/core/auth-guidance.js
2918
- import { join as join8 } from "node:path";
131
+ import { join } from "node:path";
2919
132
  var UNKNOWN_PROVIDER = "unknown";
2920
133
  function getProviderLoginHelp() {
2921
134
  return [
2922
135
  "Use /login to log into a provider via OAuth or API key. See:",
2923
- ` ${join8(getDocsPath(), "providers.md")}`,
2924
- ` ${join8(getDocsPath(), "models.md")}`
136
+ ` ${join(getDocsPath(), "providers.md")}`,
137
+ ` ${join(getDocsPath(), "models.md")}`
2925
138
  ].join(`
2926
139
  `);
2927
140
  }
@@ -2945,13 +158,13 @@ ${getProviderLoginHelp()}`;
2945
158
  import { randomBytes } from "node:crypto";
2946
159
  import { createWriteStream } from "node:fs";
2947
160
  import { tmpdir } from "node:os";
2948
- import { join as join9 } from "node:path";
161
+ import { join as join2 } from "node:path";
2949
162
  async function executeBashWithOperations(command, cwd, operations, options) {
2950
163
  let outputChunks = [], outputBytes = 0, maxOutputBytes = 51200 * 2, tempFilePath, tempFileStream, totalBytes = 0, ensureTempFile = () => {
2951
164
  if (tempFilePath)
2952
165
  return;
2953
166
  let id = randomBytes(8).toString("hex");
2954
- tempFilePath = join9(tmpdir(), `lunr-bash-${id}.log`), tempFileStream = createWriteStream(tempFilePath);
167
+ tempFilePath = join2(tmpdir(), `lunr-bash-${id}.log`), tempFileStream = createWriteStream(tempFilePath);
2955
168
  for (let chunk of outputChunks)
2956
169
  tempFileStream.write(chunk);
2957
170
  }, decoder = new TextDecoder(), onData = (data) => {
@@ -3086,12 +299,12 @@ var ModelRegistry = class {
3086
299
  };
3087
300
 
3088
301
  // packages/coding-agent/dist/core/rollback.js
3089
- import { spawnSync as spawnSync2 } from "node:child_process";
3090
- import { createHash as createHash3 } from "node:crypto";
3091
- import { cpSync, existsSync as existsSync5, mkdirSync as mkdirSync5, readdirSync, readFileSync as readFileSync5, renameSync as renameSync4, rmSync, unlinkSync as unlinkSync4, writeFileSync as writeFileSync5 } from "node:fs";
3092
- import { homedir as homedir2 } from "node:os";
3093
- import { dirname as dirname6, join as join10, normalize, resolve } from "node:path";
3094
- var ROLLBACK_BASE = join10(homedir2(), ".lunr", "rollback"), contexts = /* @__PURE__ */ new Map(), lastSessionId, globalSettingsManager, warningHandler;
302
+ import { spawnSync } from "node:child_process";
303
+ import { createHash } from "node:crypto";
304
+ import { cpSync, existsSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, unlinkSync, writeFileSync } from "node:fs";
305
+ import { homedir } from "node:os";
306
+ import { dirname, join as join3, normalize, resolve } from "node:path";
307
+ var ROLLBACK_BASE = join3(homedir(), ".lunr", "rollback"), contexts = /* @__PURE__ */ new Map(), lastSessionId, globalSettingsManager, warningHandler;
3095
308
  function setRollbackWarningHandler(handler) {
3096
309
  warningHandler = handler;
3097
310
  }
@@ -3151,8 +364,8 @@ function rollbackSnapshotBeforeWrite(absPath, sessionId) {
3151
364
  let turn = ctx.turns[ctx.turns.length - 1];
3152
365
  if (turn && !turn.files.has(absPath))
3153
366
  try {
3154
- let existed = existsSync5(absPath), content;
3155
- existed && (content = readFileSync5(absPath)), turn.files.set(absPath, {
367
+ let existed = existsSync(absPath), content;
368
+ existed && (content = readFileSync(absPath)), turn.files.set(absPath, {
3156
369
  existed,
3157
370
  content,
3158
371
  createdByTool: !0
@@ -3169,13 +382,13 @@ function captureTreeBaseline(ctx, cwd) {
3169
382
  for (let { path } of entries) {
3170
383
  if (!path)
3171
384
  continue;
3172
- let abs = join10(cwd, path);
385
+ let abs = join3(cwd, path);
3173
386
  if (!turn.files.has(abs))
3174
387
  try {
3175
- let existed = existsSync5(abs);
388
+ let existed = existsSync(abs);
3176
389
  turn.files.set(abs, {
3177
390
  existed,
3178
- content: existed ? readFileSync5(abs) : void 0,
391
+ content: existed ? readFileSync(abs) : void 0,
3179
392
  createdByTool: !1
3180
393
  }), persistSnapshot(ctx, turn, abs);
3181
394
  } catch {
@@ -3194,14 +407,14 @@ function captureTreeChanges(cwd, sessionId) {
3194
407
  for (let { status, path, source } of entries) {
3195
408
  if (!path)
3196
409
  continue;
3197
- let abs = join10(cwd, path);
410
+ let abs = join3(cwd, path);
3198
411
  if (!turn.files.has(abs))
3199
412
  try {
3200
413
  if (status === "??" || status.includes("R")) {
3201
414
  if (turn.files.set(abs, { existed: !1, createdByTool: !1 }), persistSnapshot(ctx, turn, abs), status.includes("R") && source) {
3202
- let sourceAbs = join10(cwd, source);
415
+ let sourceAbs = join3(cwd, source);
3203
416
  if (!turn.files.has(sourceAbs)) {
3204
- let headSrc = spawnSync2("git", ["show", `HEAD:${source}`], {
417
+ let headSrc = spawnSync("git", ["show", `HEAD:${source}`], {
3205
418
  cwd,
3206
419
  timeout: 5e3,
3207
420
  maxBuffer: 33554432
@@ -3214,7 +427,7 @@ function captureTreeChanges(cwd, sessionId) {
3214
427
  }
3215
428
  }
3216
429
  } else {
3217
- let head = spawnSync2("git", ["show", `HEAD:${path}`], {
430
+ let head = spawnSync("git", ["show", `HEAD:${path}`], {
3218
431
  cwd,
3219
432
  timeout: 5e3,
3220
433
  maxBuffer: 33554432
@@ -3233,7 +446,7 @@ function captureTreeChanges(cwd, sessionId) {
3233
446
  }
3234
447
  function gitPorcelain(ctx, cwd) {
3235
448
  try {
3236
- let result = spawnSync2("git", ["status", "--porcelain", "-z"], { cwd, encoding: "utf8", timeout: 5e3 });
449
+ let result = spawnSync("git", ["status", "--porcelain", "-z"], { cwd, encoding: "utf8", timeout: 5e3 });
3237
450
  if (result.error || result.status !== 0) {
3238
451
  warnOnce(ctx, "Rollback tree scope: not a git repository (or git failed) \u2014 bash side-effects won't be captured.");
3239
452
  return;
@@ -3264,21 +477,21 @@ function persistSnapshot(ctx, turn, absPath) {
3264
477
  if (!snap)
3265
478
  return;
3266
479
  let turnDir = getTurnDir(ctx, turn.turnIndex);
3267
- mkdirSync5(turnDir, { recursive: !0 });
3268
- let manifestPath = join10(turnDir, "manifest.json"), manifest = readManifest(manifestPath), entry = { existed: snap.existed, createdByTool: snap.createdByTool };
480
+ mkdirSync(turnDir, { recursive: !0 });
481
+ let manifestPath = join3(turnDir, "manifest.json"), manifest = readManifest(manifestPath), entry = { existed: snap.existed, createdByTool: snap.createdByTool };
3269
482
  if (snap.content) {
3270
483
  let snapFile = snapFileName(absPath);
3271
- writeFileSync5(join10(turnDir, snapFile), snap.content), entry.snapFile = snapFile;
484
+ writeFileSync(join3(turnDir, snapFile), snap.content), entry.snapFile = snapFile;
3272
485
  }
3273
- manifest.files[absPath] = entry, turn.cwd && (manifest.cwd = turn.cwd), writeFileSync5(manifestPath, JSON.stringify(manifest, null, 2));
486
+ manifest.files[absPath] = entry, turn.cwd && (manifest.cwd = turn.cwd), writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));
3274
487
  } catch {
3275
488
  }
3276
489
  }
3277
490
  function readManifest(path) {
3278
- if (!existsSync5(path))
491
+ if (!existsSync(path))
3279
492
  return { files: {} };
3280
493
  try {
3281
- let parsed = JSON.parse(readFileSync5(path, "utf-8"));
494
+ let parsed = JSON.parse(readFileSync(path, "utf-8"));
3282
495
  if (parsed && typeof parsed == "object" && !Array.isArray(parsed)) {
3283
496
  let files = parsed.files;
3284
497
  return {
@@ -3293,20 +506,20 @@ function readManifest(path) {
3293
506
  }
3294
507
  function loadPersistedTurns(ctx) {
3295
508
  try {
3296
- let sessionDir = join10(ROLLBACK_BASE, ctx.sessionId);
3297
- if (!existsSync5(sessionDir))
509
+ let sessionDir = join3(ROLLBACK_BASE, ctx.sessionId);
510
+ if (!existsSync(sessionDir))
3298
511
  return;
3299
512
  let loaded = [];
3300
513
  for (let dirName of readdirSync(sessionDir)) {
3301
514
  let match = /^turn-(\d+)$/.exec(dirName);
3302
515
  if (!match)
3303
516
  continue;
3304
- let turnIndex = Number(match[1]), turnDir = join10(sessionDir, dirName), manifest = readManifest(join10(turnDir, "manifest.json")), files = /* @__PURE__ */ new Map();
517
+ let turnIndex = Number(match[1]), turnDir = join3(sessionDir, dirName), manifest = readManifest(join3(turnDir, "manifest.json")), files = /* @__PURE__ */ new Map();
3305
518
  for (let [absPath, meta] of Object.entries(manifest.files)) {
3306
519
  let content;
3307
520
  if (meta.snapFile)
3308
521
  try {
3309
- content = readFileSync5(join10(turnDir, meta.snapFile));
522
+ content = readFileSync(join3(turnDir, meta.snapFile));
3310
523
  } catch {
3311
524
  content = void 0;
3312
525
  }
@@ -3319,12 +532,12 @@ function loadPersistedTurns(ctx) {
3319
532
  }
3320
533
  }
3321
534
  function getTurnDir(ctx, turnIndex) {
3322
- return join10(ROLLBACK_BASE, ctx.sessionId, `turn-${turnIndex}`);
535
+ return join3(ROLLBACK_BASE, ctx.sessionId, `turn-${turnIndex}`);
3323
536
  }
3324
537
  function cleanupTurnFiles(ctx, turn) {
3325
538
  try {
3326
539
  let dir = getTurnDir(ctx, turn.turnIndex);
3327
- existsSync5(dir) && rmSync(dir, { recursive: !0, force: !0 });
540
+ existsSync(dir) && rmSync(dir, { recursive: !0, force: !0 });
3328
541
  } catch {
3329
542
  }
3330
543
  }
@@ -3335,10 +548,10 @@ function isPathUnderRoot(absPath, root) {
3335
548
  function isWithinAllowedRoots(absPath, turn) {
3336
549
  return turn.cwd ? [
3337
550
  ROLLBACK_BASE,
3338
- join10(homedir2(), CONFIG_DIR_NAME),
551
+ join3(homedir(), CONFIG_DIR_NAME),
3339
552
  // lunr: agent settings / cron jobs.json live under the config dir
3340
553
  // lunr: simple-memory lives next to the lunr agent dir (~/.lunr/simple-memory)
3341
- join10(dirname6(getAgentDir()), "simple-memory"),
554
+ join3(dirname(getAgentDir()), "simple-memory"),
3342
555
  resolve(turn.cwd)
3343
556
  ].some((root) => isPathUnderRoot(absPath, root)) : !0;
3344
557
  }
@@ -3380,10 +593,10 @@ function rollbackLastTurn(sessionId) {
3380
593
  continue;
3381
594
  }
3382
595
  if (snap.existed && snap.content) {
3383
- if (!snap.createdByTool && existsSync5(absPath) && readFileSync5(absPath).equals(snap.content))
596
+ if (!snap.createdByTool && existsSync(absPath) && readFileSync(absPath).equals(snap.content))
3384
597
  continue;
3385
- mkdirSync5(dirname6(absPath), { recursive: !0 }), writeFileSync5(absPath, snap.content), restored.push(absPath);
3386
- } else snap.existed || (snap.createdByTool || capture === "hybrid" || capture === "shadow-git") && existsSync5(absPath) && (unlinkSync4(absPath), deleted.push(absPath));
598
+ mkdirSync(dirname(absPath), { recursive: !0 }), writeFileSync(absPath, snap.content), restored.push(absPath);
599
+ } else snap.existed || (snap.createdByTool || capture === "hybrid" || capture === "shadow-git") && existsSync(absPath) && (unlinkSync(absPath), deleted.push(absPath));
3387
600
  } catch {
3388
601
  }
3389
602
  return cleanupTurnFiles(ctx, turn), ctx.turns.pop(), { restored, deleted, turnsConsumed };
@@ -3394,11 +607,11 @@ function migrateRollbackSession(oldSessionId, newSessionId) {
3394
607
  let ctx = contexts.get(oldSessionId);
3395
608
  ctx && (contexts.delete(oldSessionId), ctx.sessionId = newSessionId, contexts.set(newSessionId, ctx));
3396
609
  try {
3397
- let oldDir = join10(ROLLBACK_BASE, oldSessionId), newDir = join10(ROLLBACK_BASE, newSessionId);
3398
- if (existsSync5(oldDir)) {
3399
- existsSync5(newDir) && rmSync(newDir, { recursive: !0, force: !0 });
610
+ let oldDir = join3(ROLLBACK_BASE, oldSessionId), newDir = join3(ROLLBACK_BASE, newSessionId);
611
+ if (existsSync(oldDir)) {
612
+ existsSync(newDir) && rmSync(newDir, { recursive: !0, force: !0 });
3400
613
  try {
3401
- renameSync4(oldDir, newDir);
614
+ renameSync(oldDir, newDir);
3402
615
  } catch {
3403
616
  cpSync(oldDir, newDir, { recursive: !0 }), rmSync(oldDir, { recursive: !0, force: !0 });
3404
617
  }
@@ -3412,8 +625,8 @@ function clearRollback(sessionId) {
3412
625
  for (let turn of ctx2.turns)
3413
626
  cleanupTurnFiles(ctx2, turn);
3414
627
  try {
3415
- let sessionDir = join10(ROLLBACK_BASE, ctx2.sessionId);
3416
- existsSync5(sessionDir) && rmSync(sessionDir, { recursive: !0, force: !0 });
628
+ let sessionDir = join3(ROLLBACK_BASE, ctx2.sessionId);
629
+ existsSync(sessionDir) && rmSync(sessionDir, { recursive: !0, force: !0 });
3417
630
  } catch {
3418
631
  }
3419
632
  }
@@ -3425,15 +638,15 @@ function clearRollback(sessionId) {
3425
638
  for (let turn of ctx.turns)
3426
639
  cleanupTurnFiles(ctx, turn);
3427
640
  try {
3428
- let sessionDir = join10(ROLLBACK_BASE, sessionId);
3429
- existsSync5(sessionDir) && rmSync(sessionDir, { recursive: !0, force: !0 });
641
+ let sessionDir = join3(ROLLBACK_BASE, sessionId);
642
+ existsSync(sessionDir) && rmSync(sessionDir, { recursive: !0, force: !0 });
3430
643
  } catch {
3431
644
  }
3432
645
  contexts.delete(sessionId);
3433
646
  }
3434
647
  }
3435
648
  function snapFileName(absPath) {
3436
- return `${createHash3("sha1").update(absPath).digest("hex")}.snap`;
649
+ return `${createHash("sha1").update(absPath).digest("hex")}.snap`;
3437
650
  }
3438
651
 
3439
652
  // packages/coding-agent/dist/core/system-prompt.js
@@ -3463,7 +676,8 @@ ${content}
3463
676
  return (!selectedTools || selectedTools.includes("read")) && skills.length > 0 && (prompt2 += formatSkillsForPrompt(skills)), prompt2 += `
3464
677
  Current working directory: ${promptCwd}`, prompt2;
3465
678
  }
3466
- let readmePath = getReadmePath(), docsPath = getDocsPath(), examplesPath = getExamplesPath(), currentModel = modelSlug?.trim() || "no model selected", hasRead = !selectedTools || selectedTools.includes("read"), prompt = `You are an expert coding assistant currently running ''${currentModel}'', operating inside lunR, a coding agent harness. You help users by reading files, executing commands, editing code, and writing new files.
679
+ let readmePath = getReadmePath(), docsPath = getDocsPath(), examplesPath = getExamplesPath(), currentModel = modelSlug?.trim() || "no model selected", hasRead = !selectedTools || selectedTools.includes("read"), todoGuideline = !selectedTools || selectedTools.includes("todo") ? `- Use todo for meaningful multi-step work. Every update must send the complete list, with exactly one item in progress at a time.
680
+ ` : "", prompt = `You are an expert coding assistant currently running ''${currentModel}'', operating inside lunR, a coding agent harness. You help users by reading files, executing commands, editing code, and writing new files.
3467
681
  Current working directory: ''${promptCwd}''
3468
682
 
3469
683
  Behavior guidelines:
@@ -3474,6 +688,7 @@ Behavior guidelines:
3474
688
  - When several agents work in parallel, state file ownership up front so they do not collide.
3475
689
  - Tests are good! Endless smoke tests, regressions tests for feature deletions, etc, much less good. Tests should be focused, not slop.
3476
690
  - Prefer editing existing files to creating new ones.
691
+ - When a reusable excerpt, prompt, or code fragment should have its own Copy button, wrap only that payload in a fenced Markdown block with the info string \`lunr-copy\`. Keep explanation outside the block. Use a longer backtick or tilde fence when the payload contains fenced code.
3477
692
  - Only use emojis if the user explicitly requests it.
3478
693
  - Never exfil private data on public platforms like github or any other services under any circumstances.
3479
694
 
@@ -3486,8 +701,7 @@ Guidelines:
3486
701
  - Each edits[].oldText is matched against the original file, not after earlier edits are applied. Do not emit overlapping or nested edits. Merge nearby changes into one edit.
3487
702
  - Keep edits[].oldText as small as possible while still being unique in the file. Do not pad with large unchanged regions.
3488
703
  - Use write only for new files or complete rewrites.
3489
- - Use todo for meaningful multi-step work. Every update must send the complete list, with exactly one item in progress at a time.
3490
- - Use subagents for independent parallel work, specialist analysis, or substantial research. Subagents start with fresh sessions. Use intercom instead to coordinate with an existing lunR session.
704
+ ${todoGuideline}- Use subagents for independent parallel work, specialist analysis, or substantial research. Subagents start with fresh sessions. Use intercom instead to coordinate with an existing lunR session.
3491
705
  - Use ast_search for structural code matches.
3492
706
  - Use cron only when the user asks to schedule or manage unattended prompts.
3493
707
  - Memory stores established, durable facts and stable preferences. Do not store behavior instructions, transient task details, transcripts, guesses, or secrets. Change memory only with the memory tools.
@@ -3670,10 +884,10 @@ var THINKING_LEVELS = ["off", "minimal", "low", "medium", "high", "xhigh", "max"
3670
884
  if (toolName === "edit" || toolName === "write")
3671
885
  argPath && pathsToSnapshot.push(argPath);
3672
886
  else if (toolName === "memory_add" || toolName === "memory_remove")
3673
- pathsToSnapshot.push(join11(dirname7(getAgentDir()), "simple-memory", "memory.md"));
887
+ pathsToSnapshot.push(join4(dirname2(getAgentDir()), "simple-memory", "memory.md"));
3674
888
  else if (toolName === "cron" && args && typeof args == "object") {
3675
889
  let action = String(args.action ?? "");
3676
- (action === "create" || action === "update" || action === "remove") && pathsToSnapshot.push(join11(getAgentDir(), "cron", "jobs.json"));
890
+ (action === "create" || action === "update" || action === "remove") && pathsToSnapshot.push(join4(getAgentDir(), "cron", "jobs.json"));
3677
891
  }
3678
892
  for (let p of pathsToSnapshot)
3679
893
  rollbackSnapshotBeforeWrite(p, this.sessionId);
@@ -3755,15 +969,15 @@ var THINKING_LEVELS = ["off", "minimal", "low", "medium", "high", "xhigh", "max"
3755
969
  });
3756
970
  }
3757
971
  _getIdleWaitPromise() {
3758
- return this._idleWaitPromise || (this._idleWaitPromise = new Promise((resolve4) => {
3759
- this._resolveIdleWait = resolve4;
972
+ return this._idleWaitPromise || (this._idleWaitPromise = new Promise((resolve3) => {
973
+ this._resolveIdleWait = resolve3;
3760
974
  })), this._idleWaitPromise;
3761
975
  }
3762
976
  _resolveIdleWaitIfIdle() {
3763
977
  if (this._isAgentRunActive || !this._resolveIdleWait)
3764
978
  return;
3765
- let resolve4 = this._resolveIdleWait;
3766
- this._idleWaitPromise = void 0, this._resolveIdleWait = void 0, resolve4();
979
+ let resolve3 = this._resolveIdleWait;
980
+ this._idleWaitPromise = void 0, this._resolveIdleWait = void 0, resolve3();
3767
981
  }
3768
982
  async _emitAgentSettled() {
3769
983
  this._isAgentRunActive = !1;
@@ -3936,12 +1150,20 @@ var THINKING_LEVELS = ["off", "minimal", "low", "medium", "high", "xhigh", "max"
3936
1150
  * Remove all listeners and disconnect from agent.
3937
1151
  * Call this when completely done with the session.
3938
1152
  */
1153
+ transferring = !1;
1154
+ setTransferring(value) {
1155
+ this.transferring = value;
1156
+ }
1157
+ assertCanStartWork() {
1158
+ if (this.sessionManager.assertWritable(), this.transferring)
1159
+ throw new Error("Session transfer is in progress. Wait or reclaim the session.");
1160
+ }
3939
1161
  dispose() {
3940
1162
  try {
3941
1163
  this.abortRetry(), this.abortCompaction(), this.abortBranchSummary(), this.abortBash(), this.agent.abort();
3942
1164
  } catch {
3943
1165
  }
3944
- this._extensionRunner.invalidate("This extension ctx is stale after session replacement or reload. Do not use a captured pi or command ctx after ctx.newSession(), ctx.fork(), ctx.switchSession(), or ctx.reload(). For newSession, fork, and switchSession, move post-replacement work into withSession and use the ctx passed to withSession. For reload, do not use the old ctx after await ctx.reload()."), this._disconnectFromAgent(), this._eventListeners = [], cleanupSessionResources(this.sessionId);
1166
+ this._extensionRunner.invalidate("This extension ctx is stale after session replacement or reload. Do not use a captured pi or command ctx after ctx.newSession(), ctx.fork(), ctx.switchSession(), or ctx.reload(). For newSession, fork, and switchSession, move post-replacement work into withSession and use the ctx passed to withSession. For reload, do not use the old ctx after await ctx.reload()."), this._disconnectFromAgent(), this._eventListeners = [], cleanupSessionResources(this.sessionId), this.sessionManager.dispose();
3945
1167
  }
3946
1168
  // =========================================================================
3947
1169
  // Read-only State Access
@@ -4158,6 +1380,7 @@ ${this._systemPromptAppend}` : prompt;
4158
1380
  * @throws Error if no model selected or no API key available (when not streaming)
4159
1381
  */
4160
1382
  async prompt(text, options) {
1383
+ this.assertCanStartWork();
4161
1384
  let expandPromptTemplates = options?.expandPromptTemplates ?? !0, preflightResult = options?.preflightResult, messages;
4162
1385
  try {
4163
1386
  if (expandPromptTemplates && text.startsWith("/") && await this._tryExecuteExtensionCommand(text)) {
@@ -4243,7 +1466,7 @@ ${this._systemPromptAppend}` : prompt;
4243
1466
  if (!skill)
4244
1467
  return text;
4245
1468
  try {
4246
- let content = readFileSync6(skill.filePath, "utf-8"), body = stripFrontmatter(content).trim(), skillBlock = `<skill name="${skill.name}" location="${skill.filePath}">
1469
+ let content = readFileSync2(skill.filePath, "utf-8"), body = stripFrontmatter(content).trim(), skillBlock = `<skill name="${skill.name}" location="${skill.filePath}">
4247
1470
  References are relative to ${skill.baseDir}.
4248
1471
 
4249
1472
  ${body}
@@ -4268,7 +1491,7 @@ ${args}` : skillBlock;
4268
1491
  * @throws Error if text is an extension command
4269
1492
  */
4270
1493
  async steer(text, images) {
4271
- text.startsWith("/") && this._throwIfExtensionCommand(text);
1494
+ this.assertCanStartWork(), text.startsWith("/") && this._throwIfExtensionCommand(text);
4272
1495
  let expandedText = this._expandSkillCommand(text);
4273
1496
  expandedText = expandPromptTemplate(expandedText, [...this.promptTemplates]), await this._queueSteer(expandedText, images);
4274
1497
  }
@@ -4280,7 +1503,7 @@ ${args}` : skillBlock;
4280
1503
  * @throws Error if text is an extension command
4281
1504
  */
4282
1505
  async followUp(text, images) {
4283
- text.startsWith("/") && this._throwIfExtensionCommand(text);
1506
+ this.assertCanStartWork(), text.startsWith("/") && this._throwIfExtensionCommand(text);
4284
1507
  let expandedText = this._expandSkillCommand(text);
4285
1508
  expandedText = expandPromptTemplate(expandedText, [...this.promptTemplates]), await this._queueFollowUp(expandedText, images);
4286
1509
  }
@@ -4329,6 +1552,7 @@ ${args}` : skillBlock;
4329
1552
  * @param options.deliverAs Delivery mode: "steer", "followUp", or "nextTurn"
4330
1553
  */
4331
1554
  async sendCustomMessage(message, options) {
1555
+ this.assertCanStartWork();
4332
1556
  let appMessage = {
4333
1557
  role: "custom",
4334
1558
  customType: message.customType,
@@ -4877,7 +2101,7 @@ ${args}` : skillBlock;
4877
2101
  }
4878
2102
  buildExtensionResourcePaths(entries) {
4879
2103
  return entries.map((entry) => {
4880
- let source = this.getExtensionSourceLabel(entry.extensionPath), baseDir = entry.extensionPath.startsWith("<") ? void 0 : dirname7(entry.extensionPath);
2104
+ let source = this.getExtensionSourceLabel(entry.extensionPath), baseDir = entry.extensionPath.startsWith("<") ? void 0 : dirname2(entry.extensionPath);
4881
2105
  return {
4882
2106
  path: entry.path,
4883
2107
  metadata: {
@@ -4972,7 +2196,7 @@ ${args}` : skillBlock;
4972
2196
  }
4973
2197
  this.abort();
4974
2198
  },
4975
- hasPendingMessages: () => this.pendingMessageCount > 0,
2199
+ hasPendingMessages: () => this.pendingMessageCount > 0 || this.agent.hasQueuedMessages(),
4976
2200
  shutdown: () => {
4977
2201
  this._extensionShutdownHandler?.();
4978
2202
  },
@@ -5000,7 +2224,7 @@ ${args}` : skillBlock;
5000
2224
  });
5001
2225
  }
5002
2226
  _refreshToolRegistry(options) {
5003
- let previousRegistryNames = new Set(this._toolRegistry.keys()), previousActiveToolNames = this.getActiveToolNames(), allowedToolNames = this._allowedToolNames, excludedToolNames = this._excludedToolNames, isAllowedTool = (name) => (!allowedToolNames || allowedToolNames.has(name)) && !excludedToolNames?.has(name) && (this.settingsManager.getMemoryEnabled() || !MEMORY_TOOL_NAMES.has(name)), allCustomTools = [
2227
+ let previousRegistryNames = new Set(this._toolRegistry.keys()), previousActiveToolNames = this.getActiveToolNames(), allowedToolNames = this._allowedToolNames, excludedToolNames = this._excludedToolNames, isAllowedTool = (name) => (!allowedToolNames || allowedToolNames.has(name)) && !excludedToolNames?.has(name) && (this.settingsManager.getMemoryEnabled() || !MEMORY_TOOL_NAMES.has(name)) && (this.settingsManager.getTodosEnabled() || !TODO_TOOL_NAMES.has(name)) && (name !== "browser" || this.settingsManager.getBrowserEnabled()), allCustomTools = [
5004
2228
  ...this._extensionRunner.getAllRegisteredTools(),
5005
2229
  ...this._customTools.map((definition) => ({
5006
2230
  definition,
@@ -5182,7 +2406,7 @@ ${args}` : skillBlock;
5182
2406
  * @param options.operations Custom BashOperations for remote execution
5183
2407
  */
5184
2408
  async executeBash(command, onChunk, options) {
5185
- this._bashAbortController = new AbortController();
2409
+ this.assertCanStartWork(), this._bashAbortController = new AbortController();
5186
2410
  let prefix = this.settingsManager.getShellCommandPrefix(), shellPath = this.settingsManager.getShellPath(), resolvedCommand = prefix ? `${prefix}
5187
2411
  ${command}` : command;
5188
2412
  try {
@@ -5439,7 +2663,7 @@ ${command}` : command;
5439
2663
  */
5440
2664
  async exportToHtml(outputPath) {
5441
2665
  let [{ exportSessionToHtml }, { createToolHtmlRenderer }] = await Promise.all([
5442
- import("./export-html-TEXVV5RP.js"),
2666
+ import("./export-html-KBFVV63J.js"),
5443
2667
  import("./tool-renderer-MV5O452K.js")
5444
2668
  ]), configuredThemeName = this.settingsManager.getTheme(), themeName = configuredThemeName && getThemeByName(configuredThemeName) ? configuredThemeName : void 0, toolRenderer = createToolHtmlRenderer({
5445
2669
  getToolDefinition: (name) => this.getToolDefinition(name),
@@ -5459,8 +2683,8 @@ ${command}` : command;
5459
2683
  * @returns The resolved output file path.
5460
2684
  */
5461
2685
  exportToJsonl(outputPath) {
5462
- let filePath = resolvePath(outputPath ?? `session-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}.jsonl`, process.cwd()), dir = dirname7(filePath);
5463
- existsSync6(dir) || mkdirSync6(dir, { recursive: !0 });
2686
+ let filePath = resolvePath(outputPath ?? `session-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}.jsonl`, process.cwd()), dir = dirname2(filePath);
2687
+ existsSync2(dir) || mkdirSync2(dir, { recursive: !0 });
5464
2688
  let header = {
5465
2689
  type: "session",
5466
2690
  version: CURRENT_SESSION_VERSION,
@@ -5472,7 +2696,7 @@ ${command}` : command;
5472
2696
  let linear = { ...entry, parentId: prevId };
5473
2697
  lines.push(JSON.stringify(linear)), prevId = entry.id;
5474
2698
  }
5475
- return writeFileSync6(filePath, `${lines.join(`
2699
+ return writeFileSync2(filePath, `${lines.join(`
5476
2700
  `)}
5477
2701
  `), filePath;
5478
2702
  }
@@ -5542,17 +2766,17 @@ function mergeProviderAttributionHeaders(model, _settingsManager, sessionId, ...
5542
2766
  }
5543
2767
 
5544
2768
  // packages/coding-agent/dist/core/agent-session-runtime.js
5545
- import { copyFileSync, existsSync as existsSync8, mkdirSync as mkdirSync7 } from "node:fs";
5546
- import { basename as basename2, join as join12, resolve as resolve3 } from "node:path";
2769
+ import { copyFileSync, existsSync as existsSync4, mkdirSync as mkdirSync3 } from "node:fs";
2770
+ import { basename as basename2, join as join5 } from "node:path";
5547
2771
 
5548
2772
  // packages/coding-agent/dist/core/session-cwd.js
5549
- import { existsSync as existsSync7 } from "node:fs";
2773
+ import { existsSync as existsSync3 } from "node:fs";
5550
2774
  function getMissingSessionCwdIssue(sessionManager, fallbackCwd) {
5551
2775
  let sessionFile = sessionManager.getSessionFile();
5552
2776
  if (!sessionFile)
5553
2777
  return;
5554
2778
  let sessionCwd = sessionManager.getCwd();
5555
- if (!(!sessionCwd || existsSync7(sessionCwd)))
2779
+ if (!(!sessionCwd || existsSync3(sessionCwd)))
5556
2780
  return {
5557
2781
  sessionFile,
5558
2782
  sessionCwd,
@@ -5603,9 +2827,40 @@ var AgentSessionRuntime = class {
5603
2827
  onRuntimeApplied;
5604
2828
  _diagnostics;
5605
2829
  _modelFallbackMessage;
2830
+ detached = !1;
2831
+ transferring = !1;
2832
+ get isDetached() {
2833
+ return this.detached;
2834
+ }
2835
+ async releaseForTransfer(options = {}) {
2836
+ if (options.signal?.throwIfAborted(), this.detached)
2837
+ return;
2838
+ if (this.transferring)
2839
+ throw new SessionTransferError("Session transfer is already in progress.", "busy");
2840
+ this.transferring = !0, this.session.setTransferring(!0);
2841
+ let hasAttachedWork = () => getSubagentCancellation(this.session.sessionId)?.hasActiveRuns() || getSubagentCancellation(this.session.sessionFile ?? "")?.hasActiveRuns() || list().some((entry) => entry.status !== "exited" && (!entry.sessionId || entry.sessionId === this.session.sessionId)), busy = () => this.session.isStreaming || this.session.isCompacting || this.session.isBashRunning || this.session.isRetrying || this.session.pendingMessageCount > 0;
2842
+ try {
2843
+ if (hasAttachedWork())
2844
+ throw new SessionTransferError("Live children or processes cannot move between runtimes. Wait for them to finish or stop them and retry.", "busy");
2845
+ if (busy() && !options.stop)
2846
+ throw new SessionTransferError("Session is busy. Wait and retry, explicitly request stop, or cancel.", "busy");
2847
+ if (busy() && (this.session.abortCompaction(), this.session.abortBranchSummary(), this.session.abortBash(), this.session.clearQueue(), await this.session.abort()), busy() || hasAttachedWork())
2848
+ throw new SessionTransferError("Work has not stopped yet. Wait and retry.", "busy");
2849
+ options.signal?.throwIfAborted(), this.session.sessionManager.flush(), await this.teardownCurrent("resume");
2850
+ } finally {
2851
+ this.transferring = !1, this.detached || this.session.setTransferring(!1);
2852
+ }
2853
+ }
5606
2854
  constructor(_session, _services, createRuntime, _diagnostics = [], _modelFallbackMessage, onRuntimeApplied) {
5607
2855
  this._session = _session, this._services = _services, this.createRuntime = createRuntime, this._diagnostics = _diagnostics, this._modelFallbackMessage = _modelFallbackMessage, this.onRuntimeApplied = onRuntimeApplied;
5608
2856
  }
2857
+ async createOwnedRuntime(options) {
2858
+ try {
2859
+ return await this.createRuntime(options);
2860
+ } catch (error) {
2861
+ throw options.sessionManager.dispose(), error;
2862
+ }
2863
+ }
5609
2864
  get services() {
5610
2865
  return this._services;
5611
2866
  }
@@ -5652,24 +2907,38 @@ var AgentSessionRuntime = class {
5652
2907
  }))?.cancel === !0 } : { cancelled: !1 };
5653
2908
  }
5654
2909
  async teardownCurrent(reason, targetSessionFile) {
5655
- await emitSessionShutdownEvent(this.session.extensionRunner, {
2910
+ this.detached || (await emitSessionShutdownEvent(this.session.extensionRunner, {
5656
2911
  type: "session_shutdown",
5657
2912
  reason,
5658
2913
  targetSessionFile
5659
- }), this.beforeSessionInvalidate?.(reason), this.session.dispose();
2914
+ }), this.beforeSessionInvalidate?.(reason), this.session.dispose(), this.detached = !0);
2915
+ }
2916
+ async teardownForReplacement(reason, sessionManager) {
2917
+ try {
2918
+ await this.teardownCurrent(reason, sessionManager.getSessionFile());
2919
+ } catch (error) {
2920
+ throw sessionManager.dispose(), error;
2921
+ }
5660
2922
  }
5661
2923
  apply(result) {
5662
- this._session = result.session, this._services = result.services, this._diagnostics = result.diagnostics, this._modelFallbackMessage = result.modelFallbackMessage, this.onRuntimeApplied?.(result);
2924
+ this.detached = !1, this._session = result.session, this._services = result.services, this._diagnostics = result.diagnostics, this._modelFallbackMessage = result.modelFallbackMessage, this.onRuntimeApplied?.(result);
5663
2925
  }
5664
2926
  async finishSessionReplacement(withSession) {
5665
2927
  this.rebindSession && await this.rebindSession(this.session), withSession && await withSession(this.session.createReplacedSessionContext());
5666
2928
  }
5667
2929
  async switchSession(sessionPath, options) {
5668
- let beforeResult = await this.emitBeforeSwitch("resume", sessionPath);
2930
+ if (!this.detached && this.session.sessionFile && canonicalSessionPath(sessionPath) === canonicalSessionPath(this.session.sessionFile))
2931
+ return { cancelled: !1 };
2932
+ let beforeResult = this.detached ? { cancelled: !1 } : await this.emitBeforeSwitch("resume", sessionPath);
5669
2933
  if (beforeResult.cancelled)
5670
2934
  return beforeResult;
5671
2935
  let previousSessionFile = this.session.sessionFile, sessionManager = SessionManager.open(sessionPath, void 0, options?.cwdOverride);
5672
- return assertSessionCwdExists(sessionManager, this.cwd), await this.teardownCurrent("resume", sessionManager.getSessionFile()), this.apply(await this.createRuntime({
2936
+ try {
2937
+ assertSessionCwdExists(sessionManager, this.cwd);
2938
+ } catch (error) {
2939
+ throw sessionManager.dispose(), error;
2940
+ }
2941
+ return await this.teardownForReplacement("resume", sessionManager), this.apply(await this.createOwnedRuntime({
5673
2942
  cwd: sessionManager.getCwd(),
5674
2943
  agentDir: this.services.agentDir,
5675
2944
  sessionManager,
@@ -5682,7 +2951,7 @@ var AgentSessionRuntime = class {
5682
2951
  if (beforeResult.cancelled)
5683
2952
  return beforeResult;
5684
2953
  let previousSessionFile = this.session.sessionFile, sessionDir = this.session.sessionManager.getSessionDir(), sessionManager = this.session.sessionManager.isPersisted() ? SessionManager.create(this.cwd, sessionDir) : SessionManager.inMemory(this.cwd);
5685
- return options?.parentSession && sessionManager.newSession({ parentSession: options.parentSession }), await this.teardownCurrent("new", sessionManager.getSessionFile()), this.apply(await this.createRuntime({
2954
+ return options?.parentSession && sessionManager.newSession({ parentSession: options.parentSession }), await this.teardownForReplacement("new", sessionManager), this.apply(await this.createOwnedRuntime({
5686
2955
  cwd: this.cwd,
5687
2956
  agentDir: this.services.agentDir,
5688
2957
  sessionManager,
@@ -5711,27 +2980,27 @@ var AgentSessionRuntime = class {
5711
2980
  let sessionDir = this.session.sessionManager.getSessionDir();
5712
2981
  if (!targetLeafId) {
5713
2982
  let sessionManager3 = SessionManager.create(this.cwd, sessionDir);
5714
- return sessionManager3.newSession({ parentSession: currentSessionFile }), await this.teardownCurrent("fork", sessionManager3.getSessionFile()), this.apply(await this.createRuntime({
2983
+ return sessionManager3.newSession({ parentSession: currentSessionFile }), await this.teardownForReplacement("fork", sessionManager3), this.apply(await this.createOwnedRuntime({
5715
2984
  cwd: this.cwd,
5716
2985
  agentDir: this.services.agentDir,
5717
2986
  sessionManager: sessionManager3,
5718
2987
  sessionStartEvent: { type: "session_start", reason: "fork", previousSessionFile }
5719
2988
  })), await this.finishSessionReplacement(options?.withSession), { cancelled: !1, selectedText };
5720
2989
  }
5721
- if (!existsSync8(currentSessionFile))
2990
+ if (!existsSync4(currentSessionFile))
5722
2991
  throw new Error("This session has not been saved yet. Wait for the first assistant response before cloning or forking it.");
5723
- let sessionManager2 = SessionManager.open(currentSessionFile, sessionDir);
5724
- if (!sessionManager2.createBranchedSession(targetLeafId))
2992
+ let sessionManager2 = SessionManager.forkBranch(currentSessionFile, targetLeafId, sessionDir);
2993
+ if (!sessionManager2.getSessionFile())
5725
2994
  throw new Error("Failed to create forked session");
5726
- return await this.teardownCurrent("fork", sessionManager2.getSessionFile()), this.apply(await this.createRuntime({
2995
+ return await this.teardownForReplacement("fork", sessionManager2), this.apply(await this.createOwnedRuntime({
5727
2996
  cwd: sessionManager2.getCwd(),
5728
2997
  agentDir: this.services.agentDir,
5729
2998
  sessionManager: sessionManager2,
5730
2999
  sessionStartEvent: { type: "session_start", reason: "fork", previousSessionFile }
5731
3000
  })), await this.finishSessionReplacement(options?.withSession), { cancelled: !1, selectedText };
5732
3001
  }
5733
- let sessionManager = this.session.sessionManager;
5734
- return targetLeafId ? sessionManager.createBranchedSession(targetLeafId) : sessionManager.newSession({ parentSession: this.session.sessionFile }), await this.teardownCurrent("fork", sessionManager.getSessionFile()), this.apply(await this.createRuntime({
3002
+ let sessionManager = this.session.sessionManager.copyInMemory();
3003
+ return targetLeafId ? sessionManager.createBranchedSession(targetLeafId) : sessionManager.newSession({ parentSession: this.session.sessionFile }), await this.teardownForReplacement("fork", sessionManager), this.apply(await this.createOwnedRuntime({
5735
3004
  cwd: this.cwd,
5736
3005
  agentDir: this.services.agentDir,
5737
3006
  sessionManager,
@@ -5747,17 +3016,29 @@ var AgentSessionRuntime = class {
5747
3016
  */
5748
3017
  async importFromJsonl(inputPath, cwdOverride) {
5749
3018
  let resolvedPath = resolvePath(inputPath);
5750
- if (!existsSync8(resolvedPath))
3019
+ if (!existsSync4(resolvedPath))
5751
3020
  throw new SessionImportFileNotFoundError(resolvedPath);
5752
3021
  let sessionDir = this.session.sessionManager.getSessionDir();
5753
- existsSync8(sessionDir) || mkdirSync7(sessionDir, { recursive: !0 });
5754
- let destinationPath = join12(sessionDir, basename2(resolvedPath)), beforeResult = await this.emitBeforeSwitch("resume", destinationPath);
3022
+ existsSync4(sessionDir) || mkdirSync3(sessionDir, { recursive: !0 });
3023
+ let destinationPath = join5(sessionDir, basename2(resolvedPath)), beforeResult = await this.emitBeforeSwitch("resume", destinationPath);
5755
3024
  if (beforeResult.cancelled)
5756
3025
  return beforeResult;
5757
3026
  let previousSessionFile = this.session.sessionFile;
5758
- resolve3(destinationPath) !== resolvedPath && copyFileSync(resolvedPath, destinationPath);
3027
+ if (canonicalSessionPath(destinationPath) !== canonicalSessionPath(resolvedPath)) {
3028
+ let ownership = new SessionOwnership(destinationPath);
3029
+ try {
3030
+ copyFileSync(resolvedPath, destinationPath);
3031
+ } finally {
3032
+ ownership.release();
3033
+ }
3034
+ }
5759
3035
  let sessionManager = SessionManager.open(destinationPath, sessionDir, cwdOverride);
5760
- return assertSessionCwdExists(sessionManager, this.cwd), await this.teardownCurrent("resume", sessionManager.getSessionFile()), this.apply(await this.createRuntime({
3036
+ try {
3037
+ assertSessionCwdExists(sessionManager, this.cwd);
3038
+ } catch (error) {
3039
+ throw sessionManager.dispose(), error;
3040
+ }
3041
+ return await this.teardownForReplacement("resume", sessionManager), this.apply(await this.createOwnedRuntime({
5761
3042
  cwd: sessionManager.getCwd(),
5762
3043
  agentDir: this.services.agentDir,
5763
3044
  sessionManager,
@@ -5765,15 +3046,17 @@ var AgentSessionRuntime = class {
5765
3046
  })), await this.finishSessionReplacement(), { cancelled: !1 };
5766
3047
  }
5767
3048
  async dispose() {
5768
- await emitSessionShutdownEvent(this.session.extensionRunner, {
5769
- type: "session_shutdown",
5770
- reason: "quit"
5771
- }), this.beforeSessionInvalidate?.("quit"), this.session.dispose();
3049
+ await this.teardownCurrent("quit");
5772
3050
  }
5773
3051
  };
5774
3052
  async function createAgentSessionRuntime(createRuntime, options) {
5775
- assertSessionCwdExists(options.sessionManager, options.cwd);
5776
- let result = await createRuntime(options), runtime = new AgentSessionRuntime(result.session, result.services, createRuntime, result.diagnostics, result.modelFallbackMessage, options.onRuntimeApplied);
3053
+ let result;
3054
+ try {
3055
+ assertSessionCwdExists(options.sessionManager, options.cwd), result = await createRuntime(options);
3056
+ } catch (error) {
3057
+ throw options.sessionManager.dispose(), error;
3058
+ }
3059
+ let runtime = new AgentSessionRuntime(result.session, result.services, createRuntime, result.diagnostics, result.modelFallbackMessage, options.onRuntimeApplied);
5777
3060
  return options.onRuntimeApplied?.(result), runtime;
5778
3061
  }
5779
3062
 
@@ -5782,7 +3065,15 @@ function getDefaultAgentDir() {
5782
3065
  return getAgentDir();
5783
3066
  }
5784
3067
  async function createAgentSession(options = {}) {
5785
- let cwd = resolvePath(options.cwd ?? options.sessionManager?.getCwd() ?? process.cwd()), agentDir = options.agentDir ? resolvePath(options.agentDir) : getDefaultAgentDir(), resourceLoader = options.resourceLoader, authPath = options.agentDir ? join13(agentDir, "auth.json") : void 0, modelsPath = options.agentDir ? join13(agentDir, "models.json") : void 0, modelRuntime = options.modelRuntime ?? await ModelRuntime.create({ authPath, modelsPath }), settingsManager = options.settingsManager ?? SettingsManager.create(cwd, agentDir), sessionManager = options.sessionManager ?? SessionManager.create(cwd, getDefaultSessionDir(cwd, agentDir));
3068
+ let cwd = resolvePath(options.cwd ?? options.sessionManager?.getCwd() ?? process.cwd()), agentDir = options.agentDir ? resolvePath(options.agentDir) : getDefaultAgentDir(), sessionManager = options.sessionManager ?? SessionManager.create(cwd, getDefaultSessionDir(cwd, agentDir));
3069
+ try {
3070
+ return sessionManager.assertWritable(), await createOwnedAgentSession({ ...options, sessionManager });
3071
+ } catch (error) {
3072
+ throw sessionManager.dispose(), error;
3073
+ }
3074
+ }
3075
+ async function createOwnedAgentSession(options) {
3076
+ let cwd = resolvePath(options.cwd ?? options.sessionManager?.getCwd() ?? process.cwd()), agentDir = options.agentDir ? resolvePath(options.agentDir) : getDefaultAgentDir(), resourceLoader = options.resourceLoader, authPath = options.agentDir ? join6(agentDir, "auth.json") : void 0, modelsPath = options.agentDir ? join6(agentDir, "models.json") : void 0, modelRuntime = options.modelRuntime ?? await ModelRuntime.create({ authPath, modelsPath }), settingsManager = options.settingsManager ?? SettingsManager.create(cwd, agentDir), sessionManager = options.sessionManager ?? SessionManager.create(cwd, getDefaultSessionDir(cwd, agentDir));
5786
3077
  resourceLoader || (resourceLoader = new DefaultResourceLoader({ cwd, agentDir, settingsManager }), await resourceLoader.reload(), time("resourceLoader.reload"));
5787
3078
  let existingSession = sessionManager.buildSessionContext(), hasExistingSession = existingSession.messages.length > 0, hasThinkingEntry = sessionManager.getBranch().some((entry) => entry.type === "thinking_level_change"), model = options.model, modelFallbackMessage;
5788
3079
  if (!model && hasExistingSession && existingSession.model) {
@@ -5921,8 +3212,8 @@ function applyExtensionFlagValues(resourceLoader, extensionFlagValues) {
5921
3212
  }
5922
3213
  async function createAgentSessionServices(options) {
5923
3214
  let cwd = resolvePath(options.cwd), agentDir = options.agentDir ? resolvePath(options.agentDir) : getAgentDir(), modelRuntime = options.modelRuntime ?? await ModelRuntime.create({
5924
- authPath: join14(agentDir, "auth.json"),
5925
- modelsPath: join14(agentDir, "models.json")
3215
+ authPath: join7(agentDir, "auth.json"),
3216
+ modelsPath: join7(agentDir, "models.json")
5926
3217
  });
5927
3218
  time("ModelRuntime.create");
5928
3219
  let settingsManager = options.settingsManager ?? SettingsManager.create(cwd, agentDir), resourceLoader = new DefaultResourceLoader({
@@ -5972,13 +3263,6 @@ async function createAgentSessionFromServices(options) {
5972
3263
  }
5973
3264
 
5974
3265
  export {
5975
- AuthStorage,
5976
- readStoredCredential,
5977
- formatCatalogRefreshSummary,
5978
- hasGrokCliXaiAuth,
5979
- stripJsonComments,
5980
- ModelRuntime,
5981
- refreshModelCandidatesForInit,
5982
3266
  formatNoModelsAvailableMessage,
5983
3267
  wrapRegisteredTool,
5984
3268
  wrapRegisteredTools,