@ashx-j/lunr-dev 0.2.13-dev.7.1 → 0.2.16-dev.9.1

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 (384) hide show
  1. package/CHANGELOG.md +29 -1
  2. package/dist/builtin-extensions/ashxj-tui.d.ts +14 -0
  3. package/dist/builtin-extensions/ashxj-tui.d.ts.map +1 -1
  4. package/dist/builtin-extensions/ashxj-tui.js +37 -3
  5. package/dist/builtin-extensions/ashxj-tui.js.map +1 -1
  6. package/dist/builtin-extensions/index.d.ts +1 -15
  7. package/dist/builtin-extensions/index.d.ts.map +1 -1
  8. package/dist/builtin-extensions/index.js +7 -21
  9. package/dist/builtin-extensions/index.js.map +1 -1
  10. package/dist/builtin-extensions/narumiruna-pi-goal/src/goal.d.ts.map +1 -1
  11. package/dist/builtin-extensions/narumiruna-pi-goal/src/goal.js +6 -2
  12. package/dist/builtin-extensions/narumiruna-pi-goal/src/goal.js.map +1 -1
  13. package/dist/builtin-extensions/pi-lsp-extension/src/index.d.ts +4 -0
  14. package/dist/builtin-extensions/pi-lsp-extension/src/index.d.ts.map +1 -1
  15. package/dist/builtin-extensions/pi-lsp-extension/src/index.js +163 -169
  16. package/dist/builtin-extensions/pi-lsp-extension/src/index.js.map +1 -1
  17. package/dist/builtin-extensions/pi-lsp-extension/src/runtime.d.ts +46 -0
  18. package/dist/builtin-extensions/pi-lsp-extension/src/runtime.d.ts.map +1 -0
  19. package/dist/builtin-extensions/pi-lsp-extension/src/runtime.js +109 -0
  20. package/dist/builtin-extensions/pi-lsp-extension/src/runtime.js.map +1 -0
  21. package/dist/builtin-extensions/pi-mcp-adapter/direct-tool-executor.d.ts +7 -0
  22. package/dist/builtin-extensions/pi-mcp-adapter/direct-tool-executor.d.ts.map +1 -0
  23. package/dist/builtin-extensions/pi-mcp-adapter/direct-tool-executor.js +211 -0
  24. package/dist/builtin-extensions/pi-mcp-adapter/direct-tool-executor.js.map +1 -0
  25. package/dist/builtin-extensions/pi-mcp-adapter/direct-tools.d.ts +0 -5
  26. package/dist/builtin-extensions/pi-mcp-adapter/direct-tools.d.ts.map +1 -1
  27. package/dist/builtin-extensions/pi-mcp-adapter/direct-tools.js +0 -202
  28. package/dist/builtin-extensions/pi-mcp-adapter/direct-tools.js.map +1 -1
  29. package/dist/builtin-extensions/pi-mcp-adapter/index.d.ts.map +1 -1
  30. package/dist/builtin-extensions/pi-mcp-adapter/index.js +251 -94
  31. package/dist/builtin-extensions/pi-mcp-adapter/index.js.map +1 -1
  32. package/dist/builtin-extensions/pi-mcp-adapter/init.d.ts +4 -1
  33. package/dist/builtin-extensions/pi-mcp-adapter/init.d.ts.map +1 -1
  34. package/dist/builtin-extensions/pi-mcp-adapter/init.js +10 -3
  35. package/dist/builtin-extensions/pi-mcp-adapter/init.js.map +1 -1
  36. package/dist/builtin-extensions/pi-mcp-adapter/metadata-cache.d.ts.map +1 -1
  37. package/dist/builtin-extensions/pi-mcp-adapter/metadata-cache.js +6 -1
  38. package/dist/builtin-extensions/pi-mcp-adapter/metadata-cache.js.map +1 -1
  39. package/dist/builtin-extensions/pi-prompt-template-model/prompt-loader.d.ts.map +1 -1
  40. package/dist/builtin-extensions/pi-prompt-template-model/prompt-loader.js +2 -1
  41. package/dist/builtin-extensions/pi-prompt-template-model/prompt-loader.js.map +1 -1
  42. package/dist/builtin-extensions/pi-prompt-template-model/tool-manager.d.ts +1 -1
  43. package/dist/builtin-extensions/pi-prompt-template-model/tool-manager.d.ts.map +1 -1
  44. package/dist/builtin-extensions/pi-prompt-template-model/tool-manager.js +1 -1
  45. package/dist/builtin-extensions/pi-prompt-template-model/tool-manager.js.map +1 -1
  46. package/dist/builtin-extensions/pi-subagents/src/extension/index.d.ts +1 -1
  47. package/dist/builtin-extensions/pi-subagents/src/extension/index.d.ts.map +1 -1
  48. package/dist/builtin-extensions/pi-subagents/src/extension/index.js +38 -14
  49. package/dist/builtin-extensions/pi-subagents/src/extension/index.js.map +1 -1
  50. package/dist/builtin-extensions/pi-subagents/src/shared/fork-context.d.ts.map +1 -1
  51. package/dist/builtin-extensions/pi-subagents/src/shared/fork-context.js +1 -1
  52. package/dist/builtin-extensions/pi-subagents/src/shared/fork-context.js.map +1 -1
  53. package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.d.ts +1 -1
  54. package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.d.ts.map +1 -1
  55. package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.js +1 -1
  56. package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.js.map +1 -1
  57. package/dist/builtin-extensions/pi-subagents/src/tui/render.d.ts +1 -1
  58. package/dist/builtin-extensions/pi-subagents/src/tui/render.d.ts.map +1 -1
  59. package/dist/builtin-extensions/pi-subagents/src/tui/render.js +2 -1
  60. package/dist/builtin-extensions/pi-subagents/src/tui/render.js.map +1 -1
  61. package/dist/builtin-extensions/pi-subagents/src/watchdog/review.d.ts +1 -1
  62. package/dist/builtin-extensions/pi-subagents/src/watchdog/review.d.ts.map +1 -1
  63. package/dist/builtin-extensions/pi-subagents/src/watchdog/review.js +2 -1
  64. package/dist/builtin-extensions/pi-subagents/src/watchdog/review.js.map +1 -1
  65. package/dist/builtin-extensions/pi-web-access/extract.d.ts.map +1 -1
  66. package/dist/builtin-extensions/pi-web-access/extract.js +105 -54
  67. package/dist/builtin-extensions/pi-web-access/extract.js.map +1 -1
  68. package/dist/builtin-extensions/pi-web-access/gemini-search.d.ts +1 -1
  69. package/dist/builtin-extensions/pi-web-access/gemini-search.d.ts.map +1 -1
  70. package/dist/builtin-extensions/pi-web-access/gemini-search.js +82 -65
  71. package/dist/builtin-extensions/pi-web-access/gemini-search.js.map +1 -1
  72. package/dist/builtin-extensions/pi-web-access/github-extract.d.ts.map +1 -1
  73. package/dist/builtin-extensions/pi-web-access/github-extract.js +2 -0
  74. package/dist/builtin-extensions/pi-web-access/github-extract.js.map +1 -1
  75. package/dist/builtin-extensions/pi-web-access/index.d.ts.map +1 -1
  76. package/dist/builtin-extensions/pi-web-access/index.js +167 -77
  77. package/dist/builtin-extensions/pi-web-access/index.js.map +1 -1
  78. package/dist/builtin-extensions/pi-web-access/lazy.d.ts +18 -0
  79. package/dist/builtin-extensions/pi-web-access/lazy.d.ts.map +1 -0
  80. package/dist/builtin-extensions/pi-web-access/lazy.js +19 -0
  81. package/dist/builtin-extensions/pi-web-access/lazy.js.map +1 -0
  82. package/dist/builtin-extensions/pi-web-access/session-cleanup.d.ts +6 -0
  83. package/dist/builtin-extensions/pi-web-access/session-cleanup.d.ts.map +1 -0
  84. package/dist/builtin-extensions/pi-web-access/session-cleanup.js +17 -0
  85. package/dist/builtin-extensions/pi-web-access/session-cleanup.js.map +1 -0
  86. package/dist/catalog/models.json +1 -1
  87. package/dist/catalog/providers/amazon-bedrock.json +1 -1
  88. package/dist/catalog/providers/azure-openai-responses.json +1 -1
  89. package/dist/catalog/providers/fireworks.json +1 -1
  90. package/dist/catalog/providers/github-copilot.json +1 -1
  91. package/dist/catalog/providers/openai-codex.json +1 -1
  92. package/dist/catalog/providers/openai.json +1 -1
  93. package/dist/catalog/providers/opencode.json +1 -1
  94. package/dist/catalog/providers/openrouter.json +1 -1
  95. package/dist/catalog/providers/vercel-ai-gateway.json +1 -1
  96. package/dist/catalog/publication.json +131 -3
  97. package/dist/cli/list-models.d.ts.map +1 -1
  98. package/dist/cli/list-models.js +1 -0
  99. package/dist/cli/list-models.js.map +1 -1
  100. package/dist/cli-runtime.d.ts +3 -0
  101. package/dist/cli-runtime.d.ts.map +1 -0
  102. package/dist/cli-runtime.js +73 -0
  103. package/dist/cli-runtime.js.map +1 -0
  104. package/dist/cli.d.ts.map +1 -1
  105. package/dist/cli.js +14 -53
  106. package/dist/cli.js.map +1 -1
  107. package/dist/config.d.ts +1 -0
  108. package/dist/config.d.ts.map +1 -1
  109. package/dist/config.js +1 -0
  110. package/dist/config.js.map +1 -1
  111. package/dist/core/agent-session.d.ts +3 -0
  112. package/dist/core/agent-session.d.ts.map +1 -1
  113. package/dist/core/agent-session.js +56 -12
  114. package/dist/core/agent-session.js.map +1 -1
  115. package/dist/core/catalog-cache-scope.d.ts +3 -0
  116. package/dist/core/catalog-cache-scope.d.ts.map +1 -0
  117. package/dist/core/catalog-cache-scope.js +12 -0
  118. package/dist/core/catalog-cache-scope.js.map +1 -0
  119. package/dist/core/catalog-merge.d.ts +2 -0
  120. package/dist/core/catalog-merge.d.ts.map +1 -1
  121. package/dist/core/catalog-merge.js +29 -2
  122. package/dist/core/catalog-merge.js.map +1 -1
  123. package/dist/core/catalog-refresh-polling.d.ts +8 -0
  124. package/dist/core/catalog-refresh-polling.d.ts.map +1 -0
  125. package/dist/core/catalog-refresh-polling.js +30 -0
  126. package/dist/core/catalog-refresh-polling.js.map +1 -0
  127. package/dist/core/codex-catalog.d.ts +3 -0
  128. package/dist/core/codex-catalog.d.ts.map +1 -0
  129. package/dist/core/codex-catalog.js +15 -0
  130. package/dist/core/codex-catalog.js.map +1 -0
  131. package/dist/core/compaction/compaction.d.ts.map +1 -1
  132. package/dist/core/compaction/compaction.js +10 -5
  133. package/dist/core/compaction/compaction.js.map +1 -1
  134. package/dist/core/extensions/host-static.d.ts.map +1 -1
  135. package/dist/core/extensions/host-static.js +34 -12
  136. package/dist/core/extensions/host-static.js.map +1 -1
  137. package/dist/core/extensions/loader.d.ts +1 -2
  138. package/dist/core/extensions/loader.d.ts.map +1 -1
  139. package/dist/core/extensions/loader.js +10 -64
  140. package/dist/core/extensions/loader.js.map +1 -1
  141. package/dist/core/extensions/types.d.ts +2 -2
  142. package/dist/core/extensions/types.d.ts.map +1 -1
  143. package/dist/core/extensions/types.js.map +1 -1
  144. package/dist/core/footer-data-provider.d.ts.map +1 -1
  145. package/dist/core/footer-data-provider.js +2 -0
  146. package/dist/core/footer-data-provider.js.map +1 -1
  147. package/dist/core/live-catalog.d.ts +5 -2
  148. package/dist/core/live-catalog.d.ts.map +1 -1
  149. package/dist/core/live-catalog.js +108 -27
  150. package/dist/core/live-catalog.js.map +1 -1
  151. package/dist/core/model-runtime.d.ts +8 -0
  152. package/dist/core/model-runtime.d.ts.map +1 -1
  153. package/dist/core/model-runtime.js +64 -12
  154. package/dist/core/model-runtime.js.map +1 -1
  155. package/dist/core/official-catalog.d.ts +4 -0
  156. package/dist/core/official-catalog.d.ts.map +1 -1
  157. package/dist/core/official-catalog.js +86 -21
  158. package/dist/core/official-catalog.js.map +1 -1
  159. package/dist/core/permissions.d.ts +0 -2
  160. package/dist/core/permissions.d.ts.map +1 -1
  161. package/dist/core/permissions.js +10 -18
  162. package/dist/core/permissions.js.map +1 -1
  163. package/dist/core/sdk.d.ts +1 -1
  164. package/dist/core/sdk.d.ts.map +1 -1
  165. package/dist/core/sdk.js +1 -1
  166. package/dist/core/sdk.js.map +1 -1
  167. package/dist/core/slash-commands.d.ts.map +1 -1
  168. package/dist/core/slash-commands.js +0 -1
  169. package/dist/core/slash-commands.js.map +1 -1
  170. package/dist/core/timings.d.ts +2 -1
  171. package/dist/core/timings.d.ts.map +1 -1
  172. package/dist/core/timings.js +17 -2
  173. package/dist/core/timings.js.map +1 -1
  174. package/dist/gateway/commands.d.ts +1 -1
  175. package/dist/gateway/commands.d.ts.map +1 -1
  176. package/dist/gateway/commands.js +1 -18
  177. package/dist/gateway/commands.js.map +1 -1
  178. package/dist/main.d.ts +2 -2
  179. package/dist/main.d.ts.map +1 -1
  180. package/dist/main.js +66 -48
  181. package/dist/main.js.map +1 -1
  182. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  183. package/dist/modes/interactive/components/model-selector.js +4 -1
  184. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  185. package/dist/modes/interactive/interactive-mode.d.ts +13 -22
  186. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  187. package/dist/modes/interactive/interactive-mode.js +141 -207
  188. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  189. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  190. package/dist/modes/interactive/theme/theme.js +95 -84
  191. package/dist/modes/interactive/theme/theme.js.map +1 -1
  192. package/dist/node-runtime/agent-session-services-IFJMSX7Z.js +36 -0
  193. package/dist/node-runtime/benchmark-request-UC7PD3V3.js +57 -0
  194. package/dist/node-runtime/brave-UWDA3I22.js +143 -0
  195. package/dist/node-runtime/builtin-extensions-LYZ3BFWQ.js +28 -0
  196. package/dist/node-runtime/chunk-2QKLKMKC.js +173 -0
  197. package/dist/node-runtime/chunk-3GHXVUAK.js +21 -0
  198. package/dist/node-runtime/chunk-3RCWXWAY.js +466 -0
  199. package/dist/node-runtime/chunk-3WFAEVKS.js +115 -0
  200. package/dist/node-runtime/chunk-3X3KZKMI.js +49 -0
  201. package/dist/node-runtime/chunk-4HXHDDCF.js +16 -0
  202. package/dist/node-runtime/chunk-4TLO4PO2.js +3427 -0
  203. package/dist/node-runtime/chunk-4ZWGEEAS.js +69 -0
  204. package/dist/node-runtime/chunk-53YJI7JU.js +137 -0
  205. package/dist/node-runtime/chunk-5P7PZMRU.js +610 -0
  206. package/dist/node-runtime/chunk-7N3YHTYF.js +26 -0
  207. package/dist/node-runtime/chunk-7NBZ5P7I.js +24 -0
  208. package/dist/node-runtime/chunk-A2KQXUJD.js +105 -0
  209. package/dist/node-runtime/chunk-AD6VXAO7.js +342 -0
  210. package/dist/node-runtime/chunk-AHSTJBIB.js +64 -0
  211. package/dist/node-runtime/chunk-AJX357CL.js +20211 -0
  212. package/dist/node-runtime/chunk-ARC4KOTI.js +11178 -0
  213. package/dist/node-runtime/chunk-AUXVGBO4.js +19 -0
  214. package/dist/node-runtime/chunk-AY6CAJSL.js +30 -0
  215. package/dist/node-runtime/chunk-BHO7O6E5.js +296 -0
  216. package/dist/node-runtime/chunk-BI3DHYCN.js +8845 -0
  217. package/dist/node-runtime/chunk-BR7YDUKA.js +109 -0
  218. package/dist/node-runtime/chunk-BRJX2PRC.js +53 -0
  219. package/dist/node-runtime/chunk-C4O2RSQQ.js +37 -0
  220. package/dist/node-runtime/chunk-CCZJ3PYY.js +17 -0
  221. package/dist/node-runtime/chunk-CDFZEWPU.js +8388 -0
  222. package/dist/node-runtime/chunk-CGBXPL3E.js +1171 -0
  223. package/dist/node-runtime/chunk-CJECDQKP.js +19 -0
  224. package/dist/node-runtime/chunk-DAPBPCBP.js +53 -0
  225. package/dist/node-runtime/chunk-DDGMHUOW.js +305 -0
  226. package/dist/node-runtime/chunk-DMMTJQMQ.js +43 -0
  227. package/dist/node-runtime/chunk-DVGWF6A2.js +1180 -0
  228. package/dist/node-runtime/chunk-ECD5L7YI.js +1369 -0
  229. package/dist/node-runtime/chunk-EDBJNRSM.js +46 -0
  230. package/dist/node-runtime/chunk-F4VQFJI2.js +1269 -0
  231. package/dist/node-runtime/chunk-FVDOXRUD.js +96 -0
  232. package/dist/node-runtime/chunk-GZQHMEWL.js +126 -0
  233. package/dist/node-runtime/chunk-H2EOZYMP.js +57 -0
  234. package/dist/node-runtime/chunk-HQCKFM2O.js +56 -0
  235. package/dist/node-runtime/chunk-HYHJIRDW.js +19 -0
  236. package/dist/node-runtime/chunk-I6R76AG7.js +22 -0
  237. package/dist/node-runtime/chunk-IPA627GP.js +296 -0
  238. package/dist/node-runtime/chunk-JHYKXIMM.js +378 -0
  239. package/dist/node-runtime/chunk-KKSIVROT.js +88 -0
  240. package/dist/node-runtime/chunk-LZAW4ZX3.js +633 -0
  241. package/dist/node-runtime/chunk-M3LZLQW2.js +98 -0
  242. package/dist/node-runtime/chunk-MGWCVY6Y.js +47 -0
  243. package/dist/node-runtime/chunk-MJQDX3BA.js +72 -0
  244. package/dist/node-runtime/chunk-MKKH27PH.js +8956 -0
  245. package/dist/node-runtime/chunk-MX3GJNXJ.js +986 -0
  246. package/dist/node-runtime/chunk-N77MY65L.js +966 -0
  247. package/dist/node-runtime/chunk-NUIFPZWX.js +209 -0
  248. package/dist/node-runtime/chunk-OBMWP3I5.js +68 -0
  249. package/dist/node-runtime/chunk-OR4L3IB2.js +42 -0
  250. package/dist/node-runtime/chunk-PBC2Y6GS.js +903 -0
  251. package/dist/node-runtime/chunk-PCGNAY2O.js +1324 -0
  252. package/dist/node-runtime/chunk-PCIGF2XK.js +250 -0
  253. package/dist/node-runtime/chunk-PGAJ5MO5.js +7558 -0
  254. package/dist/node-runtime/chunk-PL6JKXWI.js +3622 -0
  255. package/dist/node-runtime/chunk-PVCDKGR6.js +55 -0
  256. package/dist/node-runtime/chunk-Q4Q6D4IY.js +364 -0
  257. package/dist/node-runtime/chunk-Q5ZU2VRT.js +83 -0
  258. package/dist/node-runtime/chunk-QFWG2RVL.js +5477 -0
  259. package/dist/node-runtime/chunk-QH42CDX3.js +9451 -0
  260. package/dist/node-runtime/chunk-RQ2Q5IYR.js +72 -0
  261. package/dist/node-runtime/chunk-RQ5DNUNG.js +429 -0
  262. package/dist/node-runtime/chunk-RRIZE6QQ.js +17 -0
  263. package/dist/node-runtime/chunk-SN6G4OU6.js +4753 -0
  264. package/dist/node-runtime/chunk-SWSN6HAB.js +53 -0
  265. package/dist/node-runtime/chunk-TQNSPERU.js +949 -0
  266. package/dist/node-runtime/chunk-VRB2IYGG.js +53 -0
  267. package/dist/node-runtime/chunk-VSELYKWU.js +772 -0
  268. package/dist/node-runtime/chunk-W3CVH5RX.js +62 -0
  269. package/dist/node-runtime/chunk-WJVFOIB5.js +24921 -0
  270. package/dist/node-runtime/chunk-WOVTOV5P.js +5653 -0
  271. package/dist/node-runtime/chunk-XBWPBZBN.js +125 -0
  272. package/dist/node-runtime/chunk-XTHQ7XR7.js +509 -0
  273. package/dist/node-runtime/chunk-YF63P5ZT.js +864 -0
  274. package/dist/node-runtime/chunk-YSKSB3BJ.js +295 -0
  275. package/dist/node-runtime/chunk-ZCHMJ34K.js +130 -0
  276. package/dist/node-runtime/chunk-ZKMFUD3Q.js +2834 -0
  277. package/dist/node-runtime/cli-runtime.js +81 -0
  278. package/dist/node-runtime/clipboard-OZ63BBC6.js +12 -0
  279. package/dist/node-runtime/clipboard-image-7QR6GXVA.js +13 -0
  280. package/dist/node-runtime/command-L3LAHDIH.js +13 -0
  281. package/dist/node-runtime/commands-RL5YBW5I.js +291 -0
  282. package/dist/node-runtime/config-FMEOZSWE.js +77 -0
  283. package/dist/node-runtime/curator-server-XCM43VEF.js +3816 -0
  284. package/dist/node-runtime/customize-XEXL2DGQ.js +12 -0
  285. package/dist/node-runtime/direct-tool-executor-JVDXTO7A.js +188 -0
  286. package/dist/node-runtime/exa-LL64QZR2.js +329 -0
  287. package/dist/node-runtime/export-html-KR26FOUZ.js +150 -0
  288. package/dist/node-runtime/extension-input-RV5N6APL.js +14 -0
  289. package/dist/node-runtime/extension-selector-CPD5LWDD.js +14 -0
  290. package/dist/node-runtime/extract-XLQSJN4V.js +17 -0
  291. package/dist/node-runtime/file-sync-HCOP2QVF.js +117 -0
  292. package/dist/node-runtime/gateway-X2TI5X7F.js +2484 -0
  293. package/dist/node-runtime/gemini-api-QE7ANVDZ.js +29 -0
  294. package/dist/node-runtime/gemini-search-U7SUMPQA.js +330 -0
  295. package/dist/node-runtime/gemini-url-context-PXWCBQHK.js +103 -0
  296. package/dist/node-runtime/gemini-web-MM446SEH.js +14 -0
  297. package/dist/node-runtime/github-extract-F64RZOEA.js +619 -0
  298. package/dist/node-runtime/goal-CZQ7FFQJ.js +1831 -0
  299. package/dist/node-runtime/index.js +859 -0
  300. package/dist/node-runtime/init-NJV2T55N.js +28 -0
  301. package/dist/node-runtime/install-cli-TH7IJJQQ.js +308 -0
  302. package/dist/node-runtime/interactive-mode-KOM35YF2.js +56 -0
  303. package/dist/node-runtime/interactive-view-U6OILKF3.js +249 -0
  304. package/dist/node-runtime/lsp-manager-3ASUSO4T.js +1104 -0
  305. package/dist/node-runtime/lunr-cron-YJ5UHYRD.js +268 -0
  306. package/dist/node-runtime/main.js +54 -0
  307. package/dist/node-runtime/mcp-auth-flow-QIXHW6QN.js +32 -0
  308. package/dist/node-runtime/mcp-panel-IIGMXQGP.js +501 -0
  309. package/dist/node-runtime/mcp-setup-panel-FEK7663I.js +355 -0
  310. package/dist/node-runtime/memory-cap-3S4XRLNP.js +20 -0
  311. package/dist/node-runtime/model-tiers-NJLHUEGK.js +20 -0
  312. package/dist/node-runtime/openai-search-B3MSNCQA.js +288 -0
  313. package/dist/node-runtime/package-manager-cli-TZZHJCVI.js +749 -0
  314. package/dist/node-runtime/parallel-AI2MNSCU.js +265 -0
  315. package/dist/node-runtime/parser-manager-TQHWYDH7.js +152 -0
  316. package/dist/node-runtime/pdf-extract-IPE6H4HP.js +57 -0
  317. package/dist/node-runtime/perplexity-QVJW3I35.js +12 -0
  318. package/dist/node-runtime/pi-intercom-EEMBGQID.js +2215 -0
  319. package/dist/node-runtime/pi-mcp-adapter-QFB37AVN.js +422 -0
  320. package/dist/node-runtime/pi-ollama-cloud-4VZRMULP.js +1440 -0
  321. package/dist/node-runtime/pi-prompt-template-model-4QT4LLXF.js +3946 -0
  322. package/dist/node-runtime/pi-subagents-7XJ4H53P.js +6023 -0
  323. package/dist/node-runtime/pi-web-access-DPGAVKOA.js +1864 -0
  324. package/dist/node-runtime/print-mode-VWIRFDAC.js +12 -0
  325. package/dist/node-runtime/proxy-modes-HEEFK4KC.js +685 -0
  326. package/dist/node-runtime/rpc-entry.js +62 -0
  327. package/dist/node-runtime/rpc-mode-SJNSOA4G.js +13 -0
  328. package/dist/node-runtime/runtime-bridges-PPHNBFWL.js +14 -0
  329. package/dist/node-runtime/session-manager-MQNBYACL.js +35 -0
  330. package/dist/node-runtime/session-selector-5AZLJS6U.js +14 -0
  331. package/dist/node-runtime/settings-manager-5LF2VQWC.js +21 -0
  332. package/dist/node-runtime/src-Y7JSCK64.js +2407 -0
  333. package/dist/node-runtime/subagent-executor-5RNDEPIJ.js +8483 -0
  334. package/dist/node-runtime/summary-review-YSMXKITO.js +228 -0
  335. package/dist/node-runtime/tavily-WEZFVFP7.js +154 -0
  336. package/dist/node-runtime/timings-UAD5BEAS.js +16 -0
  337. package/dist/node-runtime/tool-renderer-MV5O452K.js +204 -0
  338. package/dist/node-runtime/update-cli-A253SZ7P.js +73 -0
  339. package/dist/node-runtime/v4-5MNC3H7G.js +424 -0
  340. package/dist/node-runtime/video-extract-OYT5WKS5.js +304 -0
  341. package/dist/node-runtime/workspace-index-6DBXSTJ6.js +163 -0
  342. package/dist/node-runtime/youtube-extract-TQYKGFGS.js +264 -0
  343. package/dist/startup/benchmark-request.d.ts +3 -0
  344. package/dist/startup/benchmark-request.d.ts.map +1 -0
  345. package/dist/startup/benchmark-request.js +65 -0
  346. package/dist/startup/benchmark-request.js.map +1 -0
  347. package/dist/startup/interactive-view.d.ts +55 -0
  348. package/dist/startup/interactive-view.d.ts.map +1 -0
  349. package/dist/startup/interactive-view.js +332 -0
  350. package/dist/startup/interactive-view.js.map +1 -0
  351. package/dist/startup/launch-routing.d.ts.map +1 -1
  352. package/dist/startup/launch-routing.js +9 -10
  353. package/dist/startup/launch-routing.js.map +1 -1
  354. package/dist/startup/startup-milestones.d.ts +1 -1
  355. package/dist/startup/startup-milestones.d.ts.map +1 -1
  356. package/dist/startup/startup-milestones.js +3 -2
  357. package/dist/startup/startup-milestones.js.map +1 -1
  358. package/dist/utils/await-with-abort.d.ts +2 -0
  359. package/dist/utils/await-with-abort.d.ts.map +1 -0
  360. package/dist/utils/await-with-abort.js +19 -0
  361. package/dist/utils/await-with-abort.js.map +1 -0
  362. package/dist/utils/syntax-highlight.d.ts.map +1 -1
  363. package/dist/utils/syntax-highlight.js +10 -4
  364. package/dist/utils/syntax-highlight.js.map +1 -1
  365. package/docs/compaction.md +5 -3
  366. package/docs/development.md +5 -1
  367. package/docs/features.md +0 -1
  368. package/docs/interactive-startup.md +98 -0
  369. package/docs/model-catalog.md +29 -0
  370. package/docs/usage.md +0 -1
  371. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  372. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  373. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  374. package/examples/extensions/gondolin/package-lock.json +2 -2
  375. package/examples/extensions/gondolin/package.json +1 -1
  376. package/examples/extensions/sandbox/package-lock.json +2 -2
  377. package/examples/extensions/sandbox/package.json +1 -1
  378. package/examples/extensions/with-deps/package-lock.json +2 -2
  379. package/examples/extensions/with-deps/package.json +1 -1
  380. package/package.json +20 -20
  381. package/dist/core/swarm.d.ts +0 -23
  382. package/dist/core/swarm.d.ts.map +0 -1
  383. package/dist/core/swarm.js +0 -45
  384. package/dist/core/swarm.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"live-catalog.d.ts","sourceRoot":"","sources":["../../src/core/live-catalog.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Api, Credential, Model } from \"@ashx-j/lunr-ai\";\nimport { VERSION } from \"../config.ts\";\nimport { getPiUserAgent } from \"../utils/pi-user-agent.ts\";\nimport { modelKey } from \"./official-catalog.ts\";\n\nexport const LIVE_CATALOG_TIMEOUT_MS = 4000;\nexport const INCOMPLETE_PROMPT_CAP = 8;\nexport const DEFAULT_CONTEXT_WINDOW = 128000;\nexport const DEFAULT_MAX_TOKENS = 8192;\n\nexport const LIVE_LIST_PROVIDER_IDS = [\n\t\"xai\",\n\t\"openrouter\",\n\t\"qwen-cloud\",\n\t\"qwen-cloud-cn\",\n\t\"groq\",\n\t\"openai\",\n\t\"deepseek\",\n] as const;\n\nexport type LiveListProviderId = (typeof LIVE_LIST_PROVIDER_IDS)[number];\n\nconst LIVE_LIST_PROVIDER_SET = new Set<string>(LIVE_LIST_PROVIDER_IDS);\n\nexport function isLiveListProvider(providerId: string): providerId is LiveListProviderId {\n\treturn LIVE_LIST_PROVIDER_SET.has(providerId);\n}\n\nexport interface LiveFieldSupply {\n\tcontextWindow: boolean;\n\tmaxTokens: boolean;\n\tinput: boolean;\n\tname: boolean;\n\tcost: boolean;\n\treasoning: boolean;\n}\n\nexport interface LiveModelDiscovery {\n\tmodel: Model<Api>;\n\tsupplied: LiveFieldSupply;\n}\n\nexport interface IncompleteLiveModel {\n\tprovider: string;\n\tid: string;\n\tname: string;\n\tmissing: Array<\"contextWindow\" | \"maxTokens\" | \"input\">;\n\tdraft: Model<Api>;\n\tavailableApis: Api[];\n}\n\nexport type LiveCatalogStatus = \"ok\" | \"timeout\" | \"error\" | \"skipped\";\n\nexport interface LiveCatalogResult {\n\tproviderId: string;\n\tstatus: LiveCatalogStatus;\n\tdiscoveries: LiveModelDiscovery[];\n\tadded: number;\n\ttotal: number;\n\tincomplete: IncompleteLiveModel[];\n\terror?: string;\n}\n\nconst ZERO_COST = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };\nconst NONE_SUPPLIED: LiveFieldSupply = {\n\tcontextWindow: false,\n\tmaxTokens: false,\n\tinput: false,\n\tname: false,\n\tcost: false,\n\treasoning: false,\n};\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction asFiniteNumber(value: unknown): number | undefined {\n\tif (typeof value === \"number\" && Number.isFinite(value)) return value;\n\tif (typeof value === \"string\" && value.trim()) {\n\t\tconst parsed = Number(value);\n\t\tif (Number.isFinite(parsed)) return parsed;\n\t}\n\treturn undefined;\n}\n\nfunction roundCost(value: number): number {\n\treturn Number(value.toFixed(6));\n}\n\nexport function modelsListUrl(baseUrl: string): string {\n\treturn `${baseUrl.replace(/\\/+$/u, \"\")}/models`;\n}\n\nexport function credentialAuthHeaders(credential: Credential | undefined): Record<string, string> {\n\tif (!credential) return {};\n\tif (credential.type === \"api_key\" && credential.key) {\n\t\treturn { Authorization: `Bearer ${credential.key}` };\n\t}\n\tif (credential.type === \"oauth\" && typeof credential.access === \"string\" && credential.access) {\n\t\treturn { Authorization: `Bearer ${credential.access}` };\n\t}\n\treturn {};\n}\n\n/** OpenAI `{ data: [{ id, ... }] }` plus a bare array. */\nexport function parseOpenAIModelsList(value: unknown): Record<string, unknown>[] {\n\tconst entries = isRecord(value) && Array.isArray(value.data) ? value.data : Array.isArray(value) ? value : [];\n\tconst rows: Record<string, unknown>[] = [];\n\tfor (const entry of entries) {\n\t\tif (typeof entry === \"string\" && entry.trim()) {\n\t\t\trows.push({ id: entry.trim() });\n\t\t\tcontinue;\n\t\t}\n\t\tif (isRecord(entry) && typeof entry.id === \"string\" && entry.id.trim()) rows.push(entry);\n\t}\n\treturn rows;\n}\n\nexport function firstBakedInModel(models: readonly Model<Api>[]): Model<Api> | undefined {\n\treturn models[0];\n}\n\nexport function uniqueApis(models: readonly Model<Api>[]): Api[] {\n\tconst seen = new Set<Api>();\n\tconst apis: Api[] = [];\n\tfor (const model of models) {\n\t\tif (seen.has(model.api)) continue;\n\t\tseen.add(model.api);\n\t\tapis.push(model.api);\n\t}\n\treturn apis;\n}\n\nexport function synthesizeLiveModel(\n\tid: string,\n\ttemplate: Model<Api>,\n\traw: Record<string, unknown> = {},\n): LiveModelDiscovery {\n\tconst name = typeof raw.name === \"string\" && raw.name.trim() ? raw.name.trim() : id;\n\treturn {\n\t\tmodel: {\n\t\t\tid,\n\t\t\tname,\n\t\t\tapi: template.api,\n\t\t\tprovider: template.provider,\n\t\t\tbaseUrl: template.baseUrl,\n\t\t\treasoning: template.reasoning,\n\t\t\tinput: template.input ?? [\"text\"],\n\t\t\tcost: ZERO_COST,\n\t\t\tcontextWindow: DEFAULT_CONTEXT_WINDOW,\n\t\t\tmaxTokens: DEFAULT_MAX_TOKENS,\n\t\t\tcompat: template.compat,\n\t\t\tthinkingLevelMap: template.thinkingLevelMap,\n\t\t},\n\t\tsupplied: {\n\t\t\t...NONE_SUPPLIED,\n\t\t\tname: typeof raw.name === \"string\" && raw.name.trim().length > 0,\n\t\t},\n\t};\n}\n\n/** OpenRouter field mapping (tools filter, pricing × 1e6, context) from generate-models. */\nexport function mapOpenRouterModel(raw: Record<string, unknown>, template: Model<Api>): LiveModelDiscovery | undefined {\n\tconst id = typeof raw.id === \"string\" ? raw.id.trim() : \"\";\n\tif (!id) return undefined;\n\tconst supported = Array.isArray(raw.supported_parameters) ? raw.supported_parameters : [];\n\tif (!supported.includes(\"tools\")) return undefined;\n\n\tconst architecture = isRecord(raw.architecture) ? raw.architecture : undefined;\n\tconst modality = typeof architecture?.modality === \"string\" ? architecture.modality : \"\";\n\tconst input: (\"text\" | \"image\")[] = [\"text\"];\n\tif (modality.includes(\"image\")) input.push(\"image\");\n\n\tconst pricing = isRecord(raw.pricing) ? raw.pricing : undefined;\n\tconst inputCost = roundCost((asFiniteNumber(pricing?.prompt) ?? 0) * 1_000_000);\n\tconst outputCost = roundCost((asFiniteNumber(pricing?.completion) ?? 0) * 1_000_000);\n\tconst cacheReadCost = roundCost((asFiniteNumber(pricing?.input_cache_read) ?? 0) * 1_000_000);\n\tconst cacheWriteCost = roundCost((asFiniteNumber(pricing?.input_cache_write) ?? 0) * 1_000_000);\n\n\tconst topProvider = isRecord(raw.top_provider) ? raw.top_provider : undefined;\n\tconst contextWindow = asFiniteNumber(topProvider?.context_length) ?? asFiniteNumber(raw.context_length);\n\tconst maxTokens = asFiniteNumber(topProvider?.max_completion_tokens) ?? asFiniteNumber(raw.max_completion_tokens);\n\n\tconst name = typeof raw.name === \"string\" && raw.name.trim() ? raw.name.trim() : id;\n\treturn {\n\t\tmodel: {\n\t\t\tid,\n\t\t\tname,\n\t\t\tapi: template.api,\n\t\t\tprovider: template.provider,\n\t\t\tbaseUrl: template.baseUrl,\n\t\t\treasoning: supported.includes(\"reasoning\") || template.reasoning,\n\t\t\tinput,\n\t\t\tcost: {\n\t\t\t\tinput: inputCost,\n\t\t\t\toutput: outputCost,\n\t\t\t\tcacheRead: cacheReadCost,\n\t\t\t\tcacheWrite: cacheWriteCost,\n\t\t\t},\n\t\t\tcontextWindow: contextWindow ?? DEFAULT_CONTEXT_WINDOW,\n\t\t\tmaxTokens: maxTokens ?? DEFAULT_MAX_TOKENS,\n\t\t\tcompat: template.compat,\n\t\t\tthinkingLevelMap: template.thinkingLevelMap,\n\t\t},\n\t\tsupplied: {\n\t\t\tcontextWindow: contextWindow !== undefined,\n\t\t\tmaxTokens: maxTokens !== undefined,\n\t\t\tinput: true,\n\t\t\tname: typeof raw.name === \"string\" && raw.name.trim().length > 0,\n\t\t\tcost: pricing !== undefined,\n\t\t\treasoning: supported.includes(\"reasoning\"),\n\t\t},\n\t};\n}\n\nexport function discoverLiveModels(\n\tproviderId: string,\n\tpayload: unknown,\n\tbakedIn: readonly Model<Api>[],\n): LiveModelDiscovery[] {\n\tconst template = firstBakedInModel(bakedIn);\n\tif (!template) return [];\n\tconst rows = parseOpenAIModelsList(payload);\n\tconst discoveries: LiveModelDiscovery[] = [];\n\tfor (const raw of rows) {\n\t\tconst id = typeof raw.id === \"string\" ? raw.id.trim() : \"\";\n\t\tif (!id) continue;\n\t\tif (providerId === \"openrouter\") {\n\t\t\tconst mapped = mapOpenRouterModel(raw, { ...template, provider: providerId });\n\t\t\tif (mapped) discoveries.push(mapped);\n\t\t\tcontinue;\n\t\t}\n\t\tdiscoveries.push(synthesizeLiveModel(id, { ...template, provider: providerId }, raw));\n\t}\n\treturn discoveries;\n}\n\nexport function missingLiveFields(supplied: LiveFieldSupply): Array<\"contextWindow\" | \"maxTokens\" | \"input\"> {\n\tconst missing: Array<\"contextWindow\" | \"maxTokens\" | \"input\"> = [];\n\tif (!supplied.contextWindow) missing.push(\"contextWindow\");\n\tif (!supplied.maxTokens) missing.push(\"maxTokens\");\n\tif (!supplied.input) missing.push(\"input\");\n\treturn missing;\n}\n\nexport function isLiveModelIncomplete(discovery: LiveModelDiscovery, knownKeys: Set<string>): boolean {\n\tif (knownKeys.has(modelKey(discovery.model.provider, discovery.model.id))) return false;\n\treturn missingLiveFields(discovery.supplied).length > 0;\n}\n\nexport function collectIncompleteLiveModels(\n\tdiscoveries: readonly LiveModelDiscovery[],\n\tbakedIn: readonly Model<Api>[],\n\tknownKeys: Set<string>,\n): IncompleteLiveModel[] {\n\tconst apis = uniqueApis(bakedIn);\n\tconst incomplete: IncompleteLiveModel[] = [];\n\tfor (const discovery of discoveries) {\n\t\tif (!isLiveModelIncomplete(discovery, knownKeys)) continue;\n\t\tincomplete.push({\n\t\t\tprovider: discovery.model.provider,\n\t\t\tid: discovery.model.id,\n\t\t\tname: discovery.model.name,\n\t\t\tmissing: missingLiveFields(discovery.supplied),\n\t\t\tdraft: discovery.model,\n\t\t\tavailableApis: apis,\n\t\t});\n\t}\n\treturn incomplete;\n}\n\nexport function buildLiveOverlay(\n\tbakedIn: readonly Model<Api>[],\n\tdiscoveries: readonly LiveModelDiscovery[],\n): Model<Api>[] {\n\tconst bakedById = new Map(bakedIn.map((model) => [model.id, model]));\n\tconst overlay: Model<Api>[] = [];\n\tfor (const discovery of discoveries) {\n\t\tconst baked = bakedById.get(discovery.model.id);\n\t\tif (!baked) {\n\t\t\toverlay.push(discovery.model);\n\t\t\tcontinue;\n\t\t}\n\t\toverlay.push({\n\t\t\t...baked,\n\t\t\tname: discovery.supplied.name ? discovery.model.name : baked.name,\n\t\t\tcontextWindow: discovery.supplied.contextWindow ? discovery.model.contextWindow : baked.contextWindow,\n\t\t\tmaxTokens: discovery.supplied.maxTokens ? discovery.model.maxTokens : baked.maxTokens,\n\t\t\tinput: discovery.supplied.input ? discovery.model.input : baked.input,\n\t\t\tcost: discovery.supplied.cost ? discovery.model.cost : baked.cost,\n\t\t\treasoning: discovery.supplied.reasoning ? discovery.model.reasoning : baked.reasoning,\n\t\t});\n\t}\n\treturn overlay;\n}\n\nexport function describeIncomplete(model: IncompleteLiveModel): string {\n\tconst labels: string[] = [];\n\tfor (const field of model.missing) {\n\t\tif (field === \"contextWindow\") labels.push(\"context window\");\n\t\telse if (field === \"maxTokens\") labels.push(\"max tokens\");\n\t\telse labels.push(\"input types\");\n\t}\n\tlet missingText = \"metadata\";\n\tif (labels.length === 1) missingText = labels[0] ?? missingText;\n\telse if (labels.length === 2) missingText = `${labels[0]} and ${labels[1]}`;\n\telse if (labels.length > 2) missingText = `${labels.slice(0, -1).join(\", \")}, and ${labels[labels.length - 1]}`;\n\treturn `New model ${model.provider}/${model.id} — missing ${missingText}.`;\n}\n\nexport function parsePositiveInt(value: string | undefined, fallback: number): number {\n\tif (!value?.trim()) return fallback;\n\tconst parsed = Number(value.trim());\n\tif (!Number.isInteger(parsed) || parsed <= 0) return fallback;\n\treturn parsed;\n}\n\nexport interface IncompleteModelAnswers {\n\tcontextWindow?: number;\n\tmaxTokens?: number;\n\tinput?: (\"text\" | \"image\")[];\n\treasoning?: boolean;\n\tapi?: Api;\n}\n\nexport function applyIncompleteAnswers(draft: Model<Api>, answers: IncompleteModelAnswers): Model<Api> {\n\treturn {\n\t\t...draft,\n\t\tcontextWindow: answers.contextWindow ?? draft.contextWindow,\n\t\tmaxTokens: answers.maxTokens ?? draft.maxTokens,\n\t\tinput: answers.input ?? draft.input,\n\t\treasoning: answers.reasoning ?? draft.reasoning,\n\t\tapi: answers.api ?? draft.api,\n\t};\n}\n\nexport interface FetchLiveProviderModelsOptions {\n\tproviderId: string;\n\tbaseUrl: string;\n\tbakedIn: readonly Model<Api>[];\n\tcredential?: Credential;\n\tknownKeys: Set<string>;\n\ttimeoutMs?: number;\n\tsignal?: AbortSignal;\n\tfetchImpl?: typeof fetch;\n}\n\nexport async function fetchLiveProviderModels(options: FetchLiveProviderModelsOptions): Promise<LiveCatalogResult> {\n\tconst empty: LiveCatalogResult = {\n\t\tproviderId: options.providerId,\n\t\tstatus: \"skipped\",\n\t\tdiscoveries: [],\n\t\tadded: 0,\n\t\ttotal: 0,\n\t\tincomplete: [],\n\t};\n\tconst template = firstBakedInModel(options.bakedIn);\n\tif (!template || !options.baseUrl) return empty;\n\n\tconst timeoutMs = options.timeoutMs ?? LIVE_CATALOG_TIMEOUT_MS;\n\tconst controller = new AbortController();\n\tlet timedOut = false;\n\tconst timer = setTimeout(() => {\n\t\ttimedOut = true;\n\t\tcontroller.abort();\n\t}, timeoutMs);\n\tconst onParentAbort = () => controller.abort();\n\toptions.signal?.addEventListener(\"abort\", onParentAbort, { once: true });\n\tif (options.signal?.aborted) controller.abort();\n\n\ttry {\n\t\tconst fetchImpl = options.fetchImpl ?? fetch;\n\t\tconst response = await Promise.race([\n\t\t\tfetchImpl(modelsListUrl(options.baseUrl), {\n\t\t\t\theaders: {\n\t\t\t\t\taccept: \"application/json\",\n\t\t\t\t\t\"User-Agent\": getPiUserAgent(VERSION),\n\t\t\t\t\t...credentialAuthHeaders(options.credential),\n\t\t\t\t},\n\t\t\t\tsignal: controller.signal,\n\t\t\t}),\n\t\t\tnew Promise<never>((_, reject) => {\n\t\t\t\tconst abortError = new Error(\"The operation was aborted\");\n\t\t\t\tabortError.name = \"AbortError\";\n\t\t\t\tcontroller.signal.addEventListener(\"abort\", () => reject(abortError), { once: true });\n\t\t\t\tif (controller.signal.aborted) reject(abortError);\n\t\t\t}),\n\t\t]);\n\t\tif (!response.ok) {\n\t\t\treturn {\n\t\t\t\t...empty,\n\t\t\t\tstatus: \"error\",\n\t\t\t\terror: `HTTP ${response.status}`,\n\t\t\t};\n\t\t}\n\t\tconst discoveries = discoverLiveModels(options.providerId, await response.json(), options.bakedIn);\n\t\tconst bakedIds = new Set(options.bakedIn.map((model) => model.id));\n\t\tconst added = discoveries.filter((discovery) => !bakedIds.has(discovery.model.id)).length;\n\t\treturn {\n\t\t\tproviderId: options.providerId,\n\t\t\tstatus: \"ok\",\n\t\t\tdiscoveries,\n\t\t\tadded,\n\t\t\ttotal: discoveries.length,\n\t\t\tincomplete: collectIncompleteLiveModels(discoveries, options.bakedIn, options.knownKeys),\n\t\t};\n\t} catch (error) {\n\t\tif (options.signal?.aborted && !timedOut) return { ...empty, status: \"skipped\", error: \"aborted\" };\n\t\tif (timedOut || (error instanceof Error && error.name === \"AbortError\")) {\n\t\t\treturn { ...empty, status: \"timeout\", error: \"timed out\" };\n\t\t}\n\t\treturn {\n\t\t\t...empty,\n\t\t\tstatus: \"error\",\n\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t};\n\t} finally {\n\t\tclearTimeout(timer);\n\t\toptions.signal?.removeEventListener(\"abort\", onParentAbort);\n\t}\n}\n"]}
1
+ {"version":3,"file":"live-catalog.d.ts","sourceRoot":"","sources":["../../src/core/live-catalog.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Api, type Credential, isOpenAiChatModel, type Model, parseOpenAiGptVersion } from \"@ashx-j/lunr-ai\";\nimport { codexModelsUrl, resolveCodexCatalogVersion } from \"@ashx-j/lunr-ai/catalog/codex\";\nimport { normalizeCatalogPricing } from \"@ashx-j/lunr-ai/catalog/metadata\";\nimport { VERSION } from \"../config.ts\";\nimport { getPiUserAgent } from \"../utils/pi-user-agent.ts\";\nimport { discoverCodexModels } from \"./codex-catalog.ts\";\nimport { modelKey } from \"./official-catalog.ts\";\n\nexport const LIVE_CATALOG_TIMEOUT_MS = 4000;\nexport const INCOMPLETE_PROMPT_CAP = 8;\nexport const DEFAULT_CONTEXT_WINDOW = 128000;\nexport const DEFAULT_MAX_TOKENS = 8192;\n\nexport const LIVE_LIST_PROVIDER_IDS = [\n\t\"openai-codex\",\n\t\"xai\",\n\t\"openrouter\",\n\t\"qwen-cloud\",\n\t\"qwen-cloud-cn\",\n\t\"groq\",\n\t\"openai\",\n\t\"deepseek\",\n] as const;\n\nexport type LiveListProviderId = (typeof LIVE_LIST_PROVIDER_IDS)[number];\n\nconst LIVE_LIST_PROVIDER_SET = new Set<string>(LIVE_LIST_PROVIDER_IDS);\n\nexport function isLiveListProvider(providerId: string): providerId is LiveListProviderId {\n\treturn LIVE_LIST_PROVIDER_SET.has(providerId);\n}\n\nexport interface LiveFieldSupply {\n\tcontextWindow: boolean;\n\tmaxTokens: boolean;\n\tinput: boolean;\n\tname: boolean;\n\tcost: boolean;\n\treasoning: boolean;\n}\n\nexport interface LiveModelDiscovery {\n\tmodel: Model<Api>;\n\tsupplied: LiveFieldSupply;\n}\n\nexport interface IncompleteLiveModel {\n\tprovider: string;\n\tid: string;\n\tname: string;\n\tmissing: Array<\"contextWindow\" | \"maxTokens\" | \"input\">;\n\tdraft: Model<Api>;\n\tavailableApis: Api[];\n}\n\nexport type LiveCatalogStatus = \"ok\" | \"timeout\" | \"error\" | \"skipped\";\n\nexport interface LiveCatalogResult {\n\tdiscoveryClientVersion?: string;\n\tproviderId: string;\n\tstatus: LiveCatalogStatus;\n\tdiscoveries: LiveModelDiscovery[];\n\tadded: number;\n\ttotal: number;\n\tincomplete: IncompleteLiveModel[];\n\terror?: string;\n}\n\nconst ZERO_COST = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };\nconst NONE_SUPPLIED: LiveFieldSupply = {\n\tcontextWindow: false,\n\tmaxTokens: false,\n\tinput: false,\n\tname: false,\n\tcost: false,\n\treasoning: false,\n};\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction asFiniteNumber(value: unknown): number | undefined {\n\tif (typeof value === \"number\" && Number.isFinite(value)) return value;\n\tif (typeof value === \"string\" && value.trim()) {\n\t\tconst parsed = Number(value);\n\t\tif (Number.isFinite(parsed)) return parsed;\n\t}\n\treturn undefined;\n}\n\nfunction roundCost(value: number): number {\n\treturn Number(value.toFixed(6));\n}\n\nexport function modelsListUrl(baseUrl: string): string {\n\treturn `${baseUrl.replace(/\\/+$/u, \"\")}/models`;\n}\n\nexport function credentialAuthHeaders(credential: Credential | undefined): Record<string, string> {\n\tif (!credential) return {};\n\tif (credential.type === \"api_key\" && credential.key) {\n\t\treturn { Authorization: `Bearer ${credential.key}` };\n\t}\n\tif (credential.type === \"oauth\" && typeof credential.access === \"string\" && credential.access) {\n\t\treturn { Authorization: `Bearer ${credential.access}` };\n\t}\n\treturn {};\n}\n\n/** OpenAI `{ data: [{ id, ... }] }` plus a bare array. */\nexport function parseOpenAIModelsList(value: unknown): Record<string, unknown>[] {\n\tconst entries = isRecord(value) && Array.isArray(value.data) ? value.data : Array.isArray(value) ? value : [];\n\tconst rows: Record<string, unknown>[] = [];\n\tfor (const entry of entries) {\n\t\tif (typeof entry === \"string\" && entry.trim()) {\n\t\t\trows.push({ id: entry.trim() });\n\t\t\tcontinue;\n\t\t}\n\t\tif (isRecord(entry) && typeof entry.id === \"string\" && entry.id.trim()) rows.push(entry);\n\t}\n\treturn rows;\n}\n\nexport function firstBakedInModel(models: readonly Model<Api>[]): Model<Api> | undefined {\n\treturn models[0];\n}\n\nexport function selectLiveTemplate(\n\tproviderId: string,\n\tid: string,\n\tbakedIn: readonly Model<Api>[],\n): Model<Api> | undefined {\n\tconst exact = bakedIn.find((model) => model.id === id);\n\tif (exact) return exact;\n\tconst version = parseOpenAiGptVersion(id);\n\tif (providerId !== \"openai\" || !version || version.major < 5 || isOpenAiChatModel(id)) {\n\t\treturn firstBakedInModel(bakedIn);\n\t}\n\tlet reasoning: Model<Api> | undefined;\n\tfor (const model of bakedIn) {\n\t\tif (model.reasoning && parseOpenAiGptVersion(model.id)) reasoning = model;\n\t}\n\treturn reasoning ?? firstBakedInModel(bakedIn);\n}\n\nexport function uniqueApis(models: readonly Model<Api>[]): Api[] {\n\tconst seen = new Set<Api>();\n\tconst apis: Api[] = [];\n\tfor (const model of models) {\n\t\tif (seen.has(model.api)) continue;\n\t\tseen.add(model.api);\n\t\tapis.push(model.api);\n\t}\n\treturn apis;\n}\n\nexport function synthesizeLiveModel(\n\tid: string,\n\ttemplate: Model<Api>,\n\traw: Record<string, unknown> = {},\n): LiveModelDiscovery {\n\tconst name = typeof raw.name === \"string\" && raw.name.trim() ? raw.name.trim() : id;\n\tconst exact = id === template.id;\n\tconst discovery: LiveModelDiscovery = {\n\t\tmodel: {\n\t\t\tid,\n\t\t\tname,\n\t\t\tapi: template.api,\n\t\t\tprovider: template.provider,\n\t\t\tbaseUrl: template.baseUrl,\n\t\t\treasoning: template.reasoning,\n\t\t\tinput: exact ? template.input : [\"text\"],\n\t\t\tcost: ZERO_COST,\n\t\t\tcontextWindow: DEFAULT_CONTEXT_WINDOW,\n\t\t\tmaxTokens: DEFAULT_MAX_TOKENS,\n\t\t\tcompat: template.compat,\n\t\t\tthinkingLevelMap: exact ? template.thinkingLevelMap : undefined,\n\t\t\tcatalog: { source: \"provider\", supplied: typeof raw.name === \"string\" ? [\"name\"] : [], pricing: \"unknown\" },\n\t\t},\n\t\tsupplied: {\n\t\t\t...NONE_SUPPLIED,\n\t\t\tname: typeof raw.name === \"string\" && raw.name.trim().length > 0,\n\t\t},\n\t};\n\tconst context = asFiniteNumber(raw.context_window ?? raw.context_length ?? raw.max_context_length);\n\tconst output = asFiniteNumber(raw.max_output_tokens ?? raw.max_completion_tokens);\n\tif (context && context > 0) {\n\t\tdiscovery.model.contextWindow = context;\n\t\tdiscovery.supplied.contextWindow = true;\n\t}\n\tif (output && output > 0) {\n\t\tdiscovery.model.maxTokens = output;\n\t\tdiscovery.supplied.maxTokens = true;\n\t}\n\tif (typeof raw.reasoning === \"boolean\") {\n\t\tdiscovery.model.reasoning = raw.reasoning;\n\t\tdiscovery.supplied.reasoning = true;\n\t}\n\tif (Array.isArray(raw.input_modalities)) {\n\t\tconst input = raw.input_modalities.filter(\n\t\t\t(value): value is \"text\" | \"image\" => value === \"text\" || value === \"image\",\n\t\t);\n\t\tif (input.length) {\n\t\t\tdiscovery.model.input = input;\n\t\t\tdiscovery.supplied.input = true;\n\t\t}\n\t}\n\tdiscovery.model.catalog!.supplied = Object.entries(discovery.supplied)\n\t\t.filter(([, value]) => value)\n\t\t.map(([field]) => field) as NonNullable<Model<Api>[\"catalog\"]>[\"supplied\"];\n\treturn discovery;\n}\n\n/** OpenRouter field mapping (tools filter, pricing × 1e6, context) from generate-models. */\nexport function mapOpenRouterModel(raw: Record<string, unknown>, template: Model<Api>): LiveModelDiscovery | undefined {\n\tconst id = typeof raw.id === \"string\" ? raw.id.trim() : \"\";\n\tif (!id) return undefined;\n\tconst supported = Array.isArray(raw.supported_parameters) ? raw.supported_parameters : [];\n\tif (!supported.includes(\"tools\")) return undefined;\n\n\tconst architecture = isRecord(raw.architecture) ? raw.architecture : undefined;\n\tconst modality = typeof architecture?.modality === \"string\" ? architecture.modality : \"\";\n\tconst input: (\"text\" | \"image\")[] = [\"text\"];\n\tif (modality.includes(\"image\")) input.push(\"image\");\n\n\tconst pricing = isRecord(raw.pricing) ? raw.pricing : undefined;\n\tconst inputCost = roundCost((asFiniteNumber(pricing?.prompt) ?? 0) * 1_000_000);\n\tconst outputCost = roundCost((asFiniteNumber(pricing?.completion) ?? 0) * 1_000_000);\n\tconst cacheReadCost = roundCost((asFiniteNumber(pricing?.input_cache_read) ?? 0) * 1_000_000);\n\tconst cacheWriteCost = roundCost((asFiniteNumber(pricing?.input_cache_write) ?? 0) * 1_000_000);\n\n\tconst topProvider = isRecord(raw.top_provider) ? raw.top_provider : undefined;\n\tconst contextWindow = asFiniteNumber(topProvider?.context_length) ?? asFiniteNumber(raw.context_length);\n\tconst maxTokens = asFiniteNumber(topProvider?.max_completion_tokens) ?? asFiniteNumber(raw.max_completion_tokens);\n\n\tconst name = typeof raw.name === \"string\" && raw.name.trim() ? raw.name.trim() : id;\n\treturn {\n\t\tmodel: {\n\t\t\tid,\n\t\t\tname,\n\t\t\tapi: template.api,\n\t\t\tprovider: template.provider,\n\t\t\tbaseUrl: template.baseUrl,\n\t\t\treasoning: supported.includes(\"reasoning\") || template.reasoning,\n\t\t\tinput,\n\t\t\tcost: {\n\t\t\t\tinput: inputCost,\n\t\t\t\toutput: outputCost,\n\t\t\t\tcacheRead: cacheReadCost,\n\t\t\t\tcacheWrite: cacheWriteCost,\n\t\t\t},\n\t\t\tcontextWindow: contextWindow ?? DEFAULT_CONTEXT_WINDOW,\n\t\t\tmaxTokens: maxTokens ?? DEFAULT_MAX_TOKENS,\n\t\t\tcompat: template.compat,\n\t\t\tthinkingLevelMap: template.thinkingLevelMap,\n\t\t},\n\t\tsupplied: {\n\t\t\tcontextWindow: contextWindow !== undefined,\n\t\t\tmaxTokens: maxTokens !== undefined,\n\t\t\tinput: true,\n\t\t\tname: typeof raw.name === \"string\" && raw.name.trim().length > 0,\n\t\t\tcost: asFiniteNumber(pricing?.prompt) !== undefined && asFiniteNumber(pricing?.completion) !== undefined,\n\t\t\treasoning: supported.includes(\"reasoning\"),\n\t\t},\n\t};\n}\n\nexport function discoverLiveModels(\n\tproviderId: string,\n\tpayload: unknown,\n\tbakedIn: readonly Model<Api>[],\n): LiveModelDiscovery[] {\n\tif (providerId === \"openai-codex\")\n\t\treturn discoverCodexModels(payload, bakedIn[0]?.baseUrl ?? \"https://chatgpt.com/backend-api\");\n\tconst fallback = firstBakedInModel(bakedIn);\n\tif (!fallback) return [];\n\tconst rows = parseOpenAIModelsList(payload);\n\tconst discoveries: LiveModelDiscovery[] = [];\n\tfor (const raw of rows) {\n\t\tconst id = typeof raw.id === \"string\" ? raw.id.trim() : \"\";\n\t\tif (!id) continue;\n\t\tif (\n\t\t\traw.tool_call === false ||\n\t\t\traw.type === \"embedding\" ||\n\t\t\t(providerId === \"openai\" &&\n\t\t\t\t/^(?:text-embedding-|tts-|whisper-|dall-e-|gpt-image-|gpt-audio|gpt-realtime|sora-|.*moderation)/i.test(id))\n\t\t)\n\t\t\tcontinue;\n\t\tconst template = { ...(selectLiveTemplate(providerId, id, bakedIn) ?? fallback), provider: providerId };\n\t\tif (providerId === \"openrouter\") {\n\t\t\tconst mapped = mapOpenRouterModel(raw, template);\n\t\t\tif (mapped) {\n\t\t\t\tmapped.model.catalog = {\n\t\t\t\t\tsource: \"provider\",\n\t\t\t\t\t...(!mapped.supplied.cost ? { pricing: \"unknown\" as const } : {}),\n\t\t\t\t\tsupplied: Object.entries(mapped.supplied)\n\t\t\t\t\t\t.filter(([, supplied]) => supplied)\n\t\t\t\t\t\t.map(([key]) => key) as NonNullable<Model<Api>[\"catalog\"]>[\"supplied\"],\n\t\t\t\t};\n\t\t\t\tmapped.model = normalizeCatalogPricing(mapped.model);\n\t\t\t\tif (mapped.model.catalog?.pricing === \"unknown\") mapped.supplied.cost = false;\n\t\t\t\tdiscoveries.push(mapped);\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\tdiscoveries.push(synthesizeLiveModel(id, template, raw));\n\t}\n\treturn discoveries;\n}\n\nexport function missingLiveFields(supplied: LiveFieldSupply): Array<\"contextWindow\" | \"maxTokens\" | \"input\"> {\n\tconst missing: Array<\"contextWindow\" | \"maxTokens\" | \"input\"> = [];\n\tif (!supplied.contextWindow) missing.push(\"contextWindow\");\n\tif (!supplied.maxTokens) missing.push(\"maxTokens\");\n\tif (!supplied.input) missing.push(\"input\");\n\treturn missing;\n}\n\nexport function isLiveModelIncomplete(discovery: LiveModelDiscovery, knownKeys: Set<string>): boolean {\n\tif (knownKeys.has(modelKey(discovery.model.provider, discovery.model.id))) return false;\n\treturn missingLiveFields(discovery.supplied).length > 0;\n}\n\nexport function collectIncompleteLiveModels(\n\tdiscoveries: readonly LiveModelDiscovery[],\n\tbakedIn: readonly Model<Api>[],\n\tknownKeys: Set<string>,\n): IncompleteLiveModel[] {\n\tconst apis = uniqueApis(bakedIn);\n\tconst incomplete: IncompleteLiveModel[] = [];\n\tfor (const discovery of discoveries) {\n\t\tif (!isLiveModelIncomplete(discovery, knownKeys)) continue;\n\t\tincomplete.push({\n\t\t\tprovider: discovery.model.provider,\n\t\t\tid: discovery.model.id,\n\t\t\tname: discovery.model.name,\n\t\t\tmissing: missingLiveFields(discovery.supplied),\n\t\t\tdraft: discovery.model,\n\t\t\tavailableApis: apis,\n\t\t});\n\t}\n\treturn incomplete;\n}\n\nexport function buildLiveOverlay(\n\tbakedIn: readonly Model<Api>[],\n\tdiscoveries: readonly LiveModelDiscovery[],\n): Model<Api>[] {\n\tconst bakedById = new Map(bakedIn.map((model) => [model.id, model]));\n\tconst overlay: Model<Api>[] = [];\n\tfor (const discovery of discoveries) {\n\t\tconst baked = bakedById.get(discovery.model.id);\n\t\tif (!baked) {\n\t\t\toverlay.push(discovery.model);\n\t\t\tcontinue;\n\t\t}\n\t\toverlay.push({\n\t\t\t...baked,\n\t\t\tcatalog: discovery.model.catalog,\n\t\t\tthinkingLevelMap: discovery.model.catalog?.supplied.includes(\"thinkingLevelMap\")\n\t\t\t\t? discovery.model.thinkingLevelMap\n\t\t\t\t: baked.thinkingLevelMap,\n\t\t\tname: discovery.supplied.name ? discovery.model.name : baked.name,\n\t\t\tcontextWindow: discovery.supplied.contextWindow ? discovery.model.contextWindow : baked.contextWindow,\n\t\t\tmaxTokens: discovery.supplied.maxTokens ? discovery.model.maxTokens : baked.maxTokens,\n\t\t\tinput: discovery.supplied.input ? discovery.model.input : baked.input,\n\t\t\tcost: discovery.supplied.cost ? discovery.model.cost : baked.cost,\n\t\t\treasoning: discovery.supplied.reasoning ? discovery.model.reasoning : baked.reasoning,\n\t\t});\n\t}\n\treturn overlay;\n}\n\nexport function describeIncomplete(model: IncompleteLiveModel): string {\n\tconst labels: string[] = [];\n\tfor (const field of model.missing) {\n\t\tif (field === \"contextWindow\") labels.push(\"context window\");\n\t\telse if (field === \"maxTokens\") labels.push(\"max tokens\");\n\t\telse labels.push(\"input types\");\n\t}\n\tlet missingText = \"metadata\";\n\tif (labels.length === 1) missingText = labels[0] ?? missingText;\n\telse if (labels.length === 2) missingText = `${labels[0]} and ${labels[1]}`;\n\telse if (labels.length > 2) missingText = `${labels.slice(0, -1).join(\", \")}, and ${labels[labels.length - 1]}`;\n\treturn `New model ${model.provider}/${model.id} — missing ${missingText}.`;\n}\n\nexport function parsePositiveInt(value: string | undefined, fallback: number): number {\n\tif (!value?.trim()) return fallback;\n\tconst parsed = Number(value.trim());\n\tif (!Number.isInteger(parsed) || parsed <= 0) return fallback;\n\treturn parsed;\n}\n\nexport interface IncompleteModelAnswers {\n\tcontextWindow?: number;\n\tmaxTokens?: number;\n\tinput?: (\"text\" | \"image\")[];\n\treasoning?: boolean;\n\tapi?: Api;\n}\n\nexport function applyIncompleteAnswers(draft: Model<Api>, answers: IncompleteModelAnswers): Model<Api> {\n\treturn {\n\t\t...draft,\n\t\tcontextWindow: answers.contextWindow ?? draft.contextWindow,\n\t\tmaxTokens: answers.maxTokens ?? draft.maxTokens,\n\t\tinput: answers.input ?? draft.input,\n\t\treasoning: answers.reasoning ?? draft.reasoning,\n\t\tapi: answers.api ?? draft.api,\n\t};\n}\n\nexport interface FetchLiveProviderModelsOptions {\n\tdiscoveryClientVersion?: string;\n\tproviderId: string;\n\tbaseUrl: string;\n\tbakedIn: readonly Model<Api>[];\n\tcredential?: Credential;\n\tknownKeys: Set<string>;\n\ttimeoutMs?: number;\n\tsignal?: AbortSignal;\n\tfetchImpl?: typeof fetch;\n}\n\nexport async function fetchLiveProviderModels(options: FetchLiveProviderModelsOptions): Promise<LiveCatalogResult> {\n\tconst empty: LiveCatalogResult = {\n\t\tproviderId: options.providerId,\n\t\tstatus: \"skipped\",\n\t\tdiscoveries: [],\n\t\tadded: 0,\n\t\ttotal: 0,\n\t\tincomplete: [],\n\t};\n\tconst template = firstBakedInModel(options.bakedIn);\n\tif ((!template && options.providerId !== \"openai-codex\") || !options.baseUrl) return empty;\n\n\tconst timeoutMs = options.timeoutMs ?? LIVE_CATALOG_TIMEOUT_MS;\n\tconst controller = new AbortController();\n\tlet timedOut = false;\n\tconst timer = setTimeout(() => {\n\t\ttimedOut = true;\n\t\tcontroller.abort();\n\t}, timeoutMs);\n\tconst onParentAbort = () => controller.abort();\n\toptions.signal?.addEventListener(\"abort\", onParentAbort, { once: true });\n\tif (options.signal?.aborted) controller.abort();\n\n\ttry {\n\t\tconst fetchImpl = options.fetchImpl ?? fetch;\n\t\tconst codex = options.providerId === \"openai-codex\";\n\t\tconst accountId =\n\t\t\toptions.credential?.type === \"oauth\" && typeof options.credential.accountId === \"string\"\n\t\t\t\t? options.credential.accountId\n\t\t\t\t: undefined;\n\t\tlet discoveryClientVersion = options.discoveryClientVersion;\n\t\tconst payload = await Promise.race([\n\t\t\t(async () => {\n\t\t\t\tif (codex)\n\t\t\t\t\tdiscoveryClientVersion = await resolveCodexCatalogVersion(\n\t\t\t\t\t\tfetchImpl,\n\t\t\t\t\t\tcontroller.signal,\n\t\t\t\t\t\tdiscoveryClientVersion,\n\t\t\t\t\t);\n\t\t\t\tconst response = await fetchImpl(\n\t\t\t\t\tcodex ? codexModelsUrl(options.baseUrl, discoveryClientVersion) : modelsListUrl(options.baseUrl),\n\t\t\t\t\t{\n\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\taccept: \"application/json\",\n\t\t\t\t\t\t\t\"User-Agent\": getPiUserAgent(VERSION),\n\t\t\t\t\t\t\t...credentialAuthHeaders(options.credential),\n\t\t\t\t\t\t\t...(accountId ? { \"ChatGPT-Account-ID\": accountId } : {}),\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsignal: controller.signal,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tif (!response.ok) throw new Error(`HTTP ${response.status}`);\n\t\t\t\treturn response.json();\n\t\t\t})(),\n\t\t\tnew Promise<never>((_, reject) => {\n\t\t\t\tconst abortError = new Error(\"The operation was aborted\");\n\t\t\t\tabortError.name = \"AbortError\";\n\t\t\t\tcontroller.signal.addEventListener(\"abort\", () => reject(abortError), { once: true });\n\t\t\t\tif (controller.signal.aborted) reject(abortError);\n\t\t\t}),\n\t\t]);\n\t\tconst discoveries = codex\n\t\t\t? discoverCodexModels(payload, options.baseUrl)\n\t\t\t: discoverLiveModels(options.providerId, payload, options.bakedIn);\n\t\tif (!discoveries.length) throw new Error(\"No usable models returned; retaining cached models\");\n\t\tconst bakedIds = new Set(options.bakedIn.map((model) => model.id));\n\t\tconst added = discoveries.filter((discovery) => !bakedIds.has(discovery.model.id)).length;\n\t\treturn {\n\t\t\tproviderId: options.providerId,\n\t\t\tdiscoveryClientVersion,\n\t\t\tstatus: \"ok\",\n\t\t\tdiscoveries,\n\t\t\tadded,\n\t\t\ttotal: discoveries.length,\n\t\t\tincomplete: collectIncompleteLiveModels(discoveries, options.bakedIn, options.knownKeys),\n\t\t};\n\t} catch (error) {\n\t\tif (options.signal?.aborted && !timedOut) return { ...empty, status: \"skipped\", error: \"aborted\" };\n\t\tif (timedOut || (error instanceof Error && error.name === \"AbortError\")) {\n\t\t\treturn { ...empty, status: \"timeout\", error: \"timed out\" };\n\t\t}\n\t\treturn {\n\t\t\t...empty,\n\t\t\tstatus: \"error\",\n\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t};\n\t} finally {\n\t\tclearTimeout(timer);\n\t\toptions.signal?.removeEventListener(\"abort\", onParentAbort);\n\t}\n}\n"]}
@@ -1,11 +1,16 @@
1
+ import { isOpenAiChatModel, parseOpenAiGptVersion } from "@ashx-j/lunr-ai";
2
+ import { codexModelsUrl, resolveCodexCatalogVersion } from "@ashx-j/lunr-ai/catalog/codex";
3
+ import { normalizeCatalogPricing } from "@ashx-j/lunr-ai/catalog/metadata";
1
4
  import { VERSION } from "../config.js";
2
5
  import { getPiUserAgent } from "../utils/pi-user-agent.js";
6
+ import { discoverCodexModels } from "./codex-catalog.js";
3
7
  import { modelKey } from "./official-catalog.js";
4
8
  export const LIVE_CATALOG_TIMEOUT_MS = 4000;
5
9
  export const INCOMPLETE_PROMPT_CAP = 8;
6
10
  export const DEFAULT_CONTEXT_WINDOW = 128000;
7
11
  export const DEFAULT_MAX_TOKENS = 8192;
8
12
  export const LIVE_LIST_PROVIDER_IDS = [
13
+ "openai-codex",
9
14
  "xai",
10
15
  "openrouter",
11
16
  "qwen-cloud",
@@ -74,6 +79,21 @@ export function parseOpenAIModelsList(value) {
74
79
  export function firstBakedInModel(models) {
75
80
  return models[0];
76
81
  }
82
+ export function selectLiveTemplate(providerId, id, bakedIn) {
83
+ const exact = bakedIn.find((model) => model.id === id);
84
+ if (exact)
85
+ return exact;
86
+ const version = parseOpenAiGptVersion(id);
87
+ if (providerId !== "openai" || !version || version.major < 5 || isOpenAiChatModel(id)) {
88
+ return firstBakedInModel(bakedIn);
89
+ }
90
+ let reasoning;
91
+ for (const model of bakedIn) {
92
+ if (model.reasoning && parseOpenAiGptVersion(model.id))
93
+ reasoning = model;
94
+ }
95
+ return reasoning ?? firstBakedInModel(bakedIn);
96
+ }
77
97
  export function uniqueApis(models) {
78
98
  const seen = new Set();
79
99
  const apis = [];
@@ -87,7 +107,8 @@ export function uniqueApis(models) {
87
107
  }
88
108
  export function synthesizeLiveModel(id, template, raw = {}) {
89
109
  const name = typeof raw.name === "string" && raw.name.trim() ? raw.name.trim() : id;
90
- return {
110
+ const exact = id === template.id;
111
+ const discovery = {
91
112
  model: {
92
113
  id,
93
114
  name,
@@ -95,18 +116,44 @@ export function synthesizeLiveModel(id, template, raw = {}) {
95
116
  provider: template.provider,
96
117
  baseUrl: template.baseUrl,
97
118
  reasoning: template.reasoning,
98
- input: template.input ?? ["text"],
119
+ input: exact ? template.input : ["text"],
99
120
  cost: ZERO_COST,
100
121
  contextWindow: DEFAULT_CONTEXT_WINDOW,
101
122
  maxTokens: DEFAULT_MAX_TOKENS,
102
123
  compat: template.compat,
103
- thinkingLevelMap: template.thinkingLevelMap,
124
+ thinkingLevelMap: exact ? template.thinkingLevelMap : undefined,
125
+ catalog: { source: "provider", supplied: typeof raw.name === "string" ? ["name"] : [], pricing: "unknown" },
104
126
  },
105
127
  supplied: {
106
128
  ...NONE_SUPPLIED,
107
129
  name: typeof raw.name === "string" && raw.name.trim().length > 0,
108
130
  },
109
131
  };
132
+ const context = asFiniteNumber(raw.context_window ?? raw.context_length ?? raw.max_context_length);
133
+ const output = asFiniteNumber(raw.max_output_tokens ?? raw.max_completion_tokens);
134
+ if (context && context > 0) {
135
+ discovery.model.contextWindow = context;
136
+ discovery.supplied.contextWindow = true;
137
+ }
138
+ if (output && output > 0) {
139
+ discovery.model.maxTokens = output;
140
+ discovery.supplied.maxTokens = true;
141
+ }
142
+ if (typeof raw.reasoning === "boolean") {
143
+ discovery.model.reasoning = raw.reasoning;
144
+ discovery.supplied.reasoning = true;
145
+ }
146
+ if (Array.isArray(raw.input_modalities)) {
147
+ const input = raw.input_modalities.filter((value) => value === "text" || value === "image");
148
+ if (input.length) {
149
+ discovery.model.input = input;
150
+ discovery.supplied.input = true;
151
+ }
152
+ }
153
+ discovery.model.catalog.supplied = Object.entries(discovery.supplied)
154
+ .filter(([, value]) => value)
155
+ .map(([field]) => field);
156
+ return discovery;
110
157
  }
111
158
  /** OpenRouter field mapping (tools filter, pricing × 1e6, context) from generate-models. */
112
159
  export function mapOpenRouterModel(raw, template) {
@@ -155,14 +202,16 @@ export function mapOpenRouterModel(raw, template) {
155
202
  maxTokens: maxTokens !== undefined,
156
203
  input: true,
157
204
  name: typeof raw.name === "string" && raw.name.trim().length > 0,
158
- cost: pricing !== undefined,
205
+ cost: asFiniteNumber(pricing?.prompt) !== undefined && asFiniteNumber(pricing?.completion) !== undefined,
159
206
  reasoning: supported.includes("reasoning"),
160
207
  },
161
208
  };
162
209
  }
163
210
  export function discoverLiveModels(providerId, payload, bakedIn) {
164
- const template = firstBakedInModel(bakedIn);
165
- if (!template)
211
+ if (providerId === "openai-codex")
212
+ return discoverCodexModels(payload, bakedIn[0]?.baseUrl ?? "https://chatgpt.com/backend-api");
213
+ const fallback = firstBakedInModel(bakedIn);
214
+ if (!fallback)
166
215
  return [];
167
216
  const rows = parseOpenAIModelsList(payload);
168
217
  const discoveries = [];
@@ -170,13 +219,30 @@ export function discoverLiveModels(providerId, payload, bakedIn) {
170
219
  const id = typeof raw.id === "string" ? raw.id.trim() : "";
171
220
  if (!id)
172
221
  continue;
222
+ if (raw.tool_call === false ||
223
+ raw.type === "embedding" ||
224
+ (providerId === "openai" &&
225
+ /^(?:text-embedding-|tts-|whisper-|dall-e-|gpt-image-|gpt-audio|gpt-realtime|sora-|.*moderation)/i.test(id)))
226
+ continue;
227
+ const template = { ...(selectLiveTemplate(providerId, id, bakedIn) ?? fallback), provider: providerId };
173
228
  if (providerId === "openrouter") {
174
- const mapped = mapOpenRouterModel(raw, { ...template, provider: providerId });
175
- if (mapped)
229
+ const mapped = mapOpenRouterModel(raw, template);
230
+ if (mapped) {
231
+ mapped.model.catalog = {
232
+ source: "provider",
233
+ ...(!mapped.supplied.cost ? { pricing: "unknown" } : {}),
234
+ supplied: Object.entries(mapped.supplied)
235
+ .filter(([, supplied]) => supplied)
236
+ .map(([key]) => key),
237
+ };
238
+ mapped.model = normalizeCatalogPricing(mapped.model);
239
+ if (mapped.model.catalog?.pricing === "unknown")
240
+ mapped.supplied.cost = false;
176
241
  discoveries.push(mapped);
242
+ }
177
243
  continue;
178
244
  }
179
- discoveries.push(synthesizeLiveModel(id, { ...template, provider: providerId }, raw));
245
+ discoveries.push(synthesizeLiveModel(id, template, raw));
180
246
  }
181
247
  return discoveries;
182
248
  }
@@ -223,6 +289,10 @@ export function buildLiveOverlay(bakedIn, discoveries) {
223
289
  }
224
290
  overlay.push({
225
291
  ...baked,
292
+ catalog: discovery.model.catalog,
293
+ thinkingLevelMap: discovery.model.catalog?.supplied.includes("thinkingLevelMap")
294
+ ? discovery.model.thinkingLevelMap
295
+ : baked.thinkingLevelMap,
226
296
  name: discovery.supplied.name ? discovery.model.name : baked.name,
227
297
  contextWindow: discovery.supplied.contextWindow ? discovery.model.contextWindow : baked.contextWindow,
228
298
  maxTokens: discovery.supplied.maxTokens ? discovery.model.maxTokens : baked.maxTokens,
@@ -280,7 +350,7 @@ export async function fetchLiveProviderModels(options) {
280
350
  incomplete: [],
281
351
  };
282
352
  const template = firstBakedInModel(options.bakedIn);
283
- if (!template || !options.baseUrl)
353
+ if ((!template && options.providerId !== "openai-codex") || !options.baseUrl)
284
354
  return empty;
285
355
  const timeoutMs = options.timeoutMs ?? LIVE_CATALOG_TIMEOUT_MS;
286
356
  const controller = new AbortController();
@@ -295,15 +365,28 @@ export async function fetchLiveProviderModels(options) {
295
365
  controller.abort();
296
366
  try {
297
367
  const fetchImpl = options.fetchImpl ?? fetch;
298
- const response = await Promise.race([
299
- fetchImpl(modelsListUrl(options.baseUrl), {
300
- headers: {
301
- accept: "application/json",
302
- "User-Agent": getPiUserAgent(VERSION),
303
- ...credentialAuthHeaders(options.credential),
304
- },
305
- signal: controller.signal,
306
- }),
368
+ const codex = options.providerId === "openai-codex";
369
+ const accountId = options.credential?.type === "oauth" && typeof options.credential.accountId === "string"
370
+ ? options.credential.accountId
371
+ : undefined;
372
+ let discoveryClientVersion = options.discoveryClientVersion;
373
+ const payload = await Promise.race([
374
+ (async () => {
375
+ if (codex)
376
+ discoveryClientVersion = await resolveCodexCatalogVersion(fetchImpl, controller.signal, discoveryClientVersion);
377
+ const response = await fetchImpl(codex ? codexModelsUrl(options.baseUrl, discoveryClientVersion) : modelsListUrl(options.baseUrl), {
378
+ headers: {
379
+ accept: "application/json",
380
+ "User-Agent": getPiUserAgent(VERSION),
381
+ ...credentialAuthHeaders(options.credential),
382
+ ...(accountId ? { "ChatGPT-Account-ID": accountId } : {}),
383
+ },
384
+ signal: controller.signal,
385
+ });
386
+ if (!response.ok)
387
+ throw new Error(`HTTP ${response.status}`);
388
+ return response.json();
389
+ })(),
307
390
  new Promise((_, reject) => {
308
391
  const abortError = new Error("The operation was aborted");
309
392
  abortError.name = "AbortError";
@@ -312,18 +395,16 @@ export async function fetchLiveProviderModels(options) {
312
395
  reject(abortError);
313
396
  }),
314
397
  ]);
315
- if (!response.ok) {
316
- return {
317
- ...empty,
318
- status: "error",
319
- error: `HTTP ${response.status}`,
320
- };
321
- }
322
- const discoveries = discoverLiveModels(options.providerId, await response.json(), options.bakedIn);
398
+ const discoveries = codex
399
+ ? discoverCodexModels(payload, options.baseUrl)
400
+ : discoverLiveModels(options.providerId, payload, options.bakedIn);
401
+ if (!discoveries.length)
402
+ throw new Error("No usable models returned; retaining cached models");
323
403
  const bakedIds = new Set(options.bakedIn.map((model) => model.id));
324
404
  const added = discoveries.filter((discovery) => !bakedIds.has(discovery.model.id)).length;
325
405
  return {
326
406
  providerId: options.providerId,
407
+ discoveryClientVersion,
327
408
  status: "ok",
328
409
  discoveries,
329
410
  added,
@@ -1 +1 @@
1
- {"version":3,"file":"live-catalog.js","sourceRoot":"","sources":["../../src/core/live-catalog.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Api, Credential, Model } from \"@ashx-j/lunr-ai\";\nimport { VERSION } from \"../config.ts\";\nimport { getPiUserAgent } from \"../utils/pi-user-agent.ts\";\nimport { modelKey } from \"./official-catalog.ts\";\n\nexport const LIVE_CATALOG_TIMEOUT_MS = 4000;\nexport const INCOMPLETE_PROMPT_CAP = 8;\nexport const DEFAULT_CONTEXT_WINDOW = 128000;\nexport const DEFAULT_MAX_TOKENS = 8192;\n\nexport const LIVE_LIST_PROVIDER_IDS = [\n\t\"xai\",\n\t\"openrouter\",\n\t\"qwen-cloud\",\n\t\"qwen-cloud-cn\",\n\t\"groq\",\n\t\"openai\",\n\t\"deepseek\",\n] as const;\n\nexport type LiveListProviderId = (typeof LIVE_LIST_PROVIDER_IDS)[number];\n\nconst LIVE_LIST_PROVIDER_SET = new Set<string>(LIVE_LIST_PROVIDER_IDS);\n\nexport function isLiveListProvider(providerId: string): providerId is LiveListProviderId {\n\treturn LIVE_LIST_PROVIDER_SET.has(providerId);\n}\n\nexport interface LiveFieldSupply {\n\tcontextWindow: boolean;\n\tmaxTokens: boolean;\n\tinput: boolean;\n\tname: boolean;\n\tcost: boolean;\n\treasoning: boolean;\n}\n\nexport interface LiveModelDiscovery {\n\tmodel: Model<Api>;\n\tsupplied: LiveFieldSupply;\n}\n\nexport interface IncompleteLiveModel {\n\tprovider: string;\n\tid: string;\n\tname: string;\n\tmissing: Array<\"contextWindow\" | \"maxTokens\" | \"input\">;\n\tdraft: Model<Api>;\n\tavailableApis: Api[];\n}\n\nexport type LiveCatalogStatus = \"ok\" | \"timeout\" | \"error\" | \"skipped\";\n\nexport interface LiveCatalogResult {\n\tproviderId: string;\n\tstatus: LiveCatalogStatus;\n\tdiscoveries: LiveModelDiscovery[];\n\tadded: number;\n\ttotal: number;\n\tincomplete: IncompleteLiveModel[];\n\terror?: string;\n}\n\nconst ZERO_COST = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };\nconst NONE_SUPPLIED: LiveFieldSupply = {\n\tcontextWindow: false,\n\tmaxTokens: false,\n\tinput: false,\n\tname: false,\n\tcost: false,\n\treasoning: false,\n};\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction asFiniteNumber(value: unknown): number | undefined {\n\tif (typeof value === \"number\" && Number.isFinite(value)) return value;\n\tif (typeof value === \"string\" && value.trim()) {\n\t\tconst parsed = Number(value);\n\t\tif (Number.isFinite(parsed)) return parsed;\n\t}\n\treturn undefined;\n}\n\nfunction roundCost(value: number): number {\n\treturn Number(value.toFixed(6));\n}\n\nexport function modelsListUrl(baseUrl: string): string {\n\treturn `${baseUrl.replace(/\\/+$/u, \"\")}/models`;\n}\n\nexport function credentialAuthHeaders(credential: Credential | undefined): Record<string, string> {\n\tif (!credential) return {};\n\tif (credential.type === \"api_key\" && credential.key) {\n\t\treturn { Authorization: `Bearer ${credential.key}` };\n\t}\n\tif (credential.type === \"oauth\" && typeof credential.access === \"string\" && credential.access) {\n\t\treturn { Authorization: `Bearer ${credential.access}` };\n\t}\n\treturn {};\n}\n\n/** OpenAI `{ data: [{ id, ... }] }` plus a bare array. */\nexport function parseOpenAIModelsList(value: unknown): Record<string, unknown>[] {\n\tconst entries = isRecord(value) && Array.isArray(value.data) ? value.data : Array.isArray(value) ? value : [];\n\tconst rows: Record<string, unknown>[] = [];\n\tfor (const entry of entries) {\n\t\tif (typeof entry === \"string\" && entry.trim()) {\n\t\t\trows.push({ id: entry.trim() });\n\t\t\tcontinue;\n\t\t}\n\t\tif (isRecord(entry) && typeof entry.id === \"string\" && entry.id.trim()) rows.push(entry);\n\t}\n\treturn rows;\n}\n\nexport function firstBakedInModel(models: readonly Model<Api>[]): Model<Api> | undefined {\n\treturn models[0];\n}\n\nexport function uniqueApis(models: readonly Model<Api>[]): Api[] {\n\tconst seen = new Set<Api>();\n\tconst apis: Api[] = [];\n\tfor (const model of models) {\n\t\tif (seen.has(model.api)) continue;\n\t\tseen.add(model.api);\n\t\tapis.push(model.api);\n\t}\n\treturn apis;\n}\n\nexport function synthesizeLiveModel(\n\tid: string,\n\ttemplate: Model<Api>,\n\traw: Record<string, unknown> = {},\n): LiveModelDiscovery {\n\tconst name = typeof raw.name === \"string\" && raw.name.trim() ? raw.name.trim() : id;\n\treturn {\n\t\tmodel: {\n\t\t\tid,\n\t\t\tname,\n\t\t\tapi: template.api,\n\t\t\tprovider: template.provider,\n\t\t\tbaseUrl: template.baseUrl,\n\t\t\treasoning: template.reasoning,\n\t\t\tinput: template.input ?? [\"text\"],\n\t\t\tcost: ZERO_COST,\n\t\t\tcontextWindow: DEFAULT_CONTEXT_WINDOW,\n\t\t\tmaxTokens: DEFAULT_MAX_TOKENS,\n\t\t\tcompat: template.compat,\n\t\t\tthinkingLevelMap: template.thinkingLevelMap,\n\t\t},\n\t\tsupplied: {\n\t\t\t...NONE_SUPPLIED,\n\t\t\tname: typeof raw.name === \"string\" && raw.name.trim().length > 0,\n\t\t},\n\t};\n}\n\n/** OpenRouter field mapping (tools filter, pricing × 1e6, context) from generate-models. */\nexport function mapOpenRouterModel(raw: Record<string, unknown>, template: Model<Api>): LiveModelDiscovery | undefined {\n\tconst id = typeof raw.id === \"string\" ? raw.id.trim() : \"\";\n\tif (!id) return undefined;\n\tconst supported = Array.isArray(raw.supported_parameters) ? raw.supported_parameters : [];\n\tif (!supported.includes(\"tools\")) return undefined;\n\n\tconst architecture = isRecord(raw.architecture) ? raw.architecture : undefined;\n\tconst modality = typeof architecture?.modality === \"string\" ? architecture.modality : \"\";\n\tconst input: (\"text\" | \"image\")[] = [\"text\"];\n\tif (modality.includes(\"image\")) input.push(\"image\");\n\n\tconst pricing = isRecord(raw.pricing) ? raw.pricing : undefined;\n\tconst inputCost = roundCost((asFiniteNumber(pricing?.prompt) ?? 0) * 1_000_000);\n\tconst outputCost = roundCost((asFiniteNumber(pricing?.completion) ?? 0) * 1_000_000);\n\tconst cacheReadCost = roundCost((asFiniteNumber(pricing?.input_cache_read) ?? 0) * 1_000_000);\n\tconst cacheWriteCost = roundCost((asFiniteNumber(pricing?.input_cache_write) ?? 0) * 1_000_000);\n\n\tconst topProvider = isRecord(raw.top_provider) ? raw.top_provider : undefined;\n\tconst contextWindow = asFiniteNumber(topProvider?.context_length) ?? asFiniteNumber(raw.context_length);\n\tconst maxTokens = asFiniteNumber(topProvider?.max_completion_tokens) ?? asFiniteNumber(raw.max_completion_tokens);\n\n\tconst name = typeof raw.name === \"string\" && raw.name.trim() ? raw.name.trim() : id;\n\treturn {\n\t\tmodel: {\n\t\t\tid,\n\t\t\tname,\n\t\t\tapi: template.api,\n\t\t\tprovider: template.provider,\n\t\t\tbaseUrl: template.baseUrl,\n\t\t\treasoning: supported.includes(\"reasoning\") || template.reasoning,\n\t\t\tinput,\n\t\t\tcost: {\n\t\t\t\tinput: inputCost,\n\t\t\t\toutput: outputCost,\n\t\t\t\tcacheRead: cacheReadCost,\n\t\t\t\tcacheWrite: cacheWriteCost,\n\t\t\t},\n\t\t\tcontextWindow: contextWindow ?? DEFAULT_CONTEXT_WINDOW,\n\t\t\tmaxTokens: maxTokens ?? DEFAULT_MAX_TOKENS,\n\t\t\tcompat: template.compat,\n\t\t\tthinkingLevelMap: template.thinkingLevelMap,\n\t\t},\n\t\tsupplied: {\n\t\t\tcontextWindow: contextWindow !== undefined,\n\t\t\tmaxTokens: maxTokens !== undefined,\n\t\t\tinput: true,\n\t\t\tname: typeof raw.name === \"string\" && raw.name.trim().length > 0,\n\t\t\tcost: pricing !== undefined,\n\t\t\treasoning: supported.includes(\"reasoning\"),\n\t\t},\n\t};\n}\n\nexport function discoverLiveModels(\n\tproviderId: string,\n\tpayload: unknown,\n\tbakedIn: readonly Model<Api>[],\n): LiveModelDiscovery[] {\n\tconst template = firstBakedInModel(bakedIn);\n\tif (!template) return [];\n\tconst rows = parseOpenAIModelsList(payload);\n\tconst discoveries: LiveModelDiscovery[] = [];\n\tfor (const raw of rows) {\n\t\tconst id = typeof raw.id === \"string\" ? raw.id.trim() : \"\";\n\t\tif (!id) continue;\n\t\tif (providerId === \"openrouter\") {\n\t\t\tconst mapped = mapOpenRouterModel(raw, { ...template, provider: providerId });\n\t\t\tif (mapped) discoveries.push(mapped);\n\t\t\tcontinue;\n\t\t}\n\t\tdiscoveries.push(synthesizeLiveModel(id, { ...template, provider: providerId }, raw));\n\t}\n\treturn discoveries;\n}\n\nexport function missingLiveFields(supplied: LiveFieldSupply): Array<\"contextWindow\" | \"maxTokens\" | \"input\"> {\n\tconst missing: Array<\"contextWindow\" | \"maxTokens\" | \"input\"> = [];\n\tif (!supplied.contextWindow) missing.push(\"contextWindow\");\n\tif (!supplied.maxTokens) missing.push(\"maxTokens\");\n\tif (!supplied.input) missing.push(\"input\");\n\treturn missing;\n}\n\nexport function isLiveModelIncomplete(discovery: LiveModelDiscovery, knownKeys: Set<string>): boolean {\n\tif (knownKeys.has(modelKey(discovery.model.provider, discovery.model.id))) return false;\n\treturn missingLiveFields(discovery.supplied).length > 0;\n}\n\nexport function collectIncompleteLiveModels(\n\tdiscoveries: readonly LiveModelDiscovery[],\n\tbakedIn: readonly Model<Api>[],\n\tknownKeys: Set<string>,\n): IncompleteLiveModel[] {\n\tconst apis = uniqueApis(bakedIn);\n\tconst incomplete: IncompleteLiveModel[] = [];\n\tfor (const discovery of discoveries) {\n\t\tif (!isLiveModelIncomplete(discovery, knownKeys)) continue;\n\t\tincomplete.push({\n\t\t\tprovider: discovery.model.provider,\n\t\t\tid: discovery.model.id,\n\t\t\tname: discovery.model.name,\n\t\t\tmissing: missingLiveFields(discovery.supplied),\n\t\t\tdraft: discovery.model,\n\t\t\tavailableApis: apis,\n\t\t});\n\t}\n\treturn incomplete;\n}\n\nexport function buildLiveOverlay(\n\tbakedIn: readonly Model<Api>[],\n\tdiscoveries: readonly LiveModelDiscovery[],\n): Model<Api>[] {\n\tconst bakedById = new Map(bakedIn.map((model) => [model.id, model]));\n\tconst overlay: Model<Api>[] = [];\n\tfor (const discovery of discoveries) {\n\t\tconst baked = bakedById.get(discovery.model.id);\n\t\tif (!baked) {\n\t\t\toverlay.push(discovery.model);\n\t\t\tcontinue;\n\t\t}\n\t\toverlay.push({\n\t\t\t...baked,\n\t\t\tname: discovery.supplied.name ? discovery.model.name : baked.name,\n\t\t\tcontextWindow: discovery.supplied.contextWindow ? discovery.model.contextWindow : baked.contextWindow,\n\t\t\tmaxTokens: discovery.supplied.maxTokens ? discovery.model.maxTokens : baked.maxTokens,\n\t\t\tinput: discovery.supplied.input ? discovery.model.input : baked.input,\n\t\t\tcost: discovery.supplied.cost ? discovery.model.cost : baked.cost,\n\t\t\treasoning: discovery.supplied.reasoning ? discovery.model.reasoning : baked.reasoning,\n\t\t});\n\t}\n\treturn overlay;\n}\n\nexport function describeIncomplete(model: IncompleteLiveModel): string {\n\tconst labels: string[] = [];\n\tfor (const field of model.missing) {\n\t\tif (field === \"contextWindow\") labels.push(\"context window\");\n\t\telse if (field === \"maxTokens\") labels.push(\"max tokens\");\n\t\telse labels.push(\"input types\");\n\t}\n\tlet missingText = \"metadata\";\n\tif (labels.length === 1) missingText = labels[0] ?? missingText;\n\telse if (labels.length === 2) missingText = `${labels[0]} and ${labels[1]}`;\n\telse if (labels.length > 2) missingText = `${labels.slice(0, -1).join(\", \")}, and ${labels[labels.length - 1]}`;\n\treturn `New model ${model.provider}/${model.id} — missing ${missingText}.`;\n}\n\nexport function parsePositiveInt(value: string | undefined, fallback: number): number {\n\tif (!value?.trim()) return fallback;\n\tconst parsed = Number(value.trim());\n\tif (!Number.isInteger(parsed) || parsed <= 0) return fallback;\n\treturn parsed;\n}\n\nexport interface IncompleteModelAnswers {\n\tcontextWindow?: number;\n\tmaxTokens?: number;\n\tinput?: (\"text\" | \"image\")[];\n\treasoning?: boolean;\n\tapi?: Api;\n}\n\nexport function applyIncompleteAnswers(draft: Model<Api>, answers: IncompleteModelAnswers): Model<Api> {\n\treturn {\n\t\t...draft,\n\t\tcontextWindow: answers.contextWindow ?? draft.contextWindow,\n\t\tmaxTokens: answers.maxTokens ?? draft.maxTokens,\n\t\tinput: answers.input ?? draft.input,\n\t\treasoning: answers.reasoning ?? draft.reasoning,\n\t\tapi: answers.api ?? draft.api,\n\t};\n}\n\nexport interface FetchLiveProviderModelsOptions {\n\tproviderId: string;\n\tbaseUrl: string;\n\tbakedIn: readonly Model<Api>[];\n\tcredential?: Credential;\n\tknownKeys: Set<string>;\n\ttimeoutMs?: number;\n\tsignal?: AbortSignal;\n\tfetchImpl?: typeof fetch;\n}\n\nexport async function fetchLiveProviderModels(options: FetchLiveProviderModelsOptions): Promise<LiveCatalogResult> {\n\tconst empty: LiveCatalogResult = {\n\t\tproviderId: options.providerId,\n\t\tstatus: \"skipped\",\n\t\tdiscoveries: [],\n\t\tadded: 0,\n\t\ttotal: 0,\n\t\tincomplete: [],\n\t};\n\tconst template = firstBakedInModel(options.bakedIn);\n\tif (!template || !options.baseUrl) return empty;\n\n\tconst timeoutMs = options.timeoutMs ?? LIVE_CATALOG_TIMEOUT_MS;\n\tconst controller = new AbortController();\n\tlet timedOut = false;\n\tconst timer = setTimeout(() => {\n\t\ttimedOut = true;\n\t\tcontroller.abort();\n\t}, timeoutMs);\n\tconst onParentAbort = () => controller.abort();\n\toptions.signal?.addEventListener(\"abort\", onParentAbort, { once: true });\n\tif (options.signal?.aborted) controller.abort();\n\n\ttry {\n\t\tconst fetchImpl = options.fetchImpl ?? fetch;\n\t\tconst response = await Promise.race([\n\t\t\tfetchImpl(modelsListUrl(options.baseUrl), {\n\t\t\t\theaders: {\n\t\t\t\t\taccept: \"application/json\",\n\t\t\t\t\t\"User-Agent\": getPiUserAgent(VERSION),\n\t\t\t\t\t...credentialAuthHeaders(options.credential),\n\t\t\t\t},\n\t\t\t\tsignal: controller.signal,\n\t\t\t}),\n\t\t\tnew Promise<never>((_, reject) => {\n\t\t\t\tconst abortError = new Error(\"The operation was aborted\");\n\t\t\t\tabortError.name = \"AbortError\";\n\t\t\t\tcontroller.signal.addEventListener(\"abort\", () => reject(abortError), { once: true });\n\t\t\t\tif (controller.signal.aborted) reject(abortError);\n\t\t\t}),\n\t\t]);\n\t\tif (!response.ok) {\n\t\t\treturn {\n\t\t\t\t...empty,\n\t\t\t\tstatus: \"error\",\n\t\t\t\terror: `HTTP ${response.status}`,\n\t\t\t};\n\t\t}\n\t\tconst discoveries = discoverLiveModels(options.providerId, await response.json(), options.bakedIn);\n\t\tconst bakedIds = new Set(options.bakedIn.map((model) => model.id));\n\t\tconst added = discoveries.filter((discovery) => !bakedIds.has(discovery.model.id)).length;\n\t\treturn {\n\t\t\tproviderId: options.providerId,\n\t\t\tstatus: \"ok\",\n\t\t\tdiscoveries,\n\t\t\tadded,\n\t\t\ttotal: discoveries.length,\n\t\t\tincomplete: collectIncompleteLiveModels(discoveries, options.bakedIn, options.knownKeys),\n\t\t};\n\t} catch (error) {\n\t\tif (options.signal?.aborted && !timedOut) return { ...empty, status: \"skipped\", error: \"aborted\" };\n\t\tif (timedOut || (error instanceof Error && error.name === \"AbortError\")) {\n\t\t\treturn { ...empty, status: \"timeout\", error: \"timed out\" };\n\t\t}\n\t\treturn {\n\t\t\t...empty,\n\t\t\tstatus: \"error\",\n\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t};\n\t} finally {\n\t\tclearTimeout(timer);\n\t\toptions.signal?.removeEventListener(\"abort\", onParentAbort);\n\t}\n}\n"]}
1
+ {"version":3,"file":"live-catalog.js","sourceRoot":"","sources":["../../src/core/live-catalog.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Api, type Credential, isOpenAiChatModel, type Model, parseOpenAiGptVersion } from \"@ashx-j/lunr-ai\";\nimport { codexModelsUrl, resolveCodexCatalogVersion } from \"@ashx-j/lunr-ai/catalog/codex\";\nimport { normalizeCatalogPricing } from \"@ashx-j/lunr-ai/catalog/metadata\";\nimport { VERSION } from \"../config.ts\";\nimport { getPiUserAgent } from \"../utils/pi-user-agent.ts\";\nimport { discoverCodexModels } from \"./codex-catalog.ts\";\nimport { modelKey } from \"./official-catalog.ts\";\n\nexport const LIVE_CATALOG_TIMEOUT_MS = 4000;\nexport const INCOMPLETE_PROMPT_CAP = 8;\nexport const DEFAULT_CONTEXT_WINDOW = 128000;\nexport const DEFAULT_MAX_TOKENS = 8192;\n\nexport const LIVE_LIST_PROVIDER_IDS = [\n\t\"openai-codex\",\n\t\"xai\",\n\t\"openrouter\",\n\t\"qwen-cloud\",\n\t\"qwen-cloud-cn\",\n\t\"groq\",\n\t\"openai\",\n\t\"deepseek\",\n] as const;\n\nexport type LiveListProviderId = (typeof LIVE_LIST_PROVIDER_IDS)[number];\n\nconst LIVE_LIST_PROVIDER_SET = new Set<string>(LIVE_LIST_PROVIDER_IDS);\n\nexport function isLiveListProvider(providerId: string): providerId is LiveListProviderId {\n\treturn LIVE_LIST_PROVIDER_SET.has(providerId);\n}\n\nexport interface LiveFieldSupply {\n\tcontextWindow: boolean;\n\tmaxTokens: boolean;\n\tinput: boolean;\n\tname: boolean;\n\tcost: boolean;\n\treasoning: boolean;\n}\n\nexport interface LiveModelDiscovery {\n\tmodel: Model<Api>;\n\tsupplied: LiveFieldSupply;\n}\n\nexport interface IncompleteLiveModel {\n\tprovider: string;\n\tid: string;\n\tname: string;\n\tmissing: Array<\"contextWindow\" | \"maxTokens\" | \"input\">;\n\tdraft: Model<Api>;\n\tavailableApis: Api[];\n}\n\nexport type LiveCatalogStatus = \"ok\" | \"timeout\" | \"error\" | \"skipped\";\n\nexport interface LiveCatalogResult {\n\tdiscoveryClientVersion?: string;\n\tproviderId: string;\n\tstatus: LiveCatalogStatus;\n\tdiscoveries: LiveModelDiscovery[];\n\tadded: number;\n\ttotal: number;\n\tincomplete: IncompleteLiveModel[];\n\terror?: string;\n}\n\nconst ZERO_COST = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };\nconst NONE_SUPPLIED: LiveFieldSupply = {\n\tcontextWindow: false,\n\tmaxTokens: false,\n\tinput: false,\n\tname: false,\n\tcost: false,\n\treasoning: false,\n};\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction asFiniteNumber(value: unknown): number | undefined {\n\tif (typeof value === \"number\" && Number.isFinite(value)) return value;\n\tif (typeof value === \"string\" && value.trim()) {\n\t\tconst parsed = Number(value);\n\t\tif (Number.isFinite(parsed)) return parsed;\n\t}\n\treturn undefined;\n}\n\nfunction roundCost(value: number): number {\n\treturn Number(value.toFixed(6));\n}\n\nexport function modelsListUrl(baseUrl: string): string {\n\treturn `${baseUrl.replace(/\\/+$/u, \"\")}/models`;\n}\n\nexport function credentialAuthHeaders(credential: Credential | undefined): Record<string, string> {\n\tif (!credential) return {};\n\tif (credential.type === \"api_key\" && credential.key) {\n\t\treturn { Authorization: `Bearer ${credential.key}` };\n\t}\n\tif (credential.type === \"oauth\" && typeof credential.access === \"string\" && credential.access) {\n\t\treturn { Authorization: `Bearer ${credential.access}` };\n\t}\n\treturn {};\n}\n\n/** OpenAI `{ data: [{ id, ... }] }` plus a bare array. */\nexport function parseOpenAIModelsList(value: unknown): Record<string, unknown>[] {\n\tconst entries = isRecord(value) && Array.isArray(value.data) ? value.data : Array.isArray(value) ? value : [];\n\tconst rows: Record<string, unknown>[] = [];\n\tfor (const entry of entries) {\n\t\tif (typeof entry === \"string\" && entry.trim()) {\n\t\t\trows.push({ id: entry.trim() });\n\t\t\tcontinue;\n\t\t}\n\t\tif (isRecord(entry) && typeof entry.id === \"string\" && entry.id.trim()) rows.push(entry);\n\t}\n\treturn rows;\n}\n\nexport function firstBakedInModel(models: readonly Model<Api>[]): Model<Api> | undefined {\n\treturn models[0];\n}\n\nexport function selectLiveTemplate(\n\tproviderId: string,\n\tid: string,\n\tbakedIn: readonly Model<Api>[],\n): Model<Api> | undefined {\n\tconst exact = bakedIn.find((model) => model.id === id);\n\tif (exact) return exact;\n\tconst version = parseOpenAiGptVersion(id);\n\tif (providerId !== \"openai\" || !version || version.major < 5 || isOpenAiChatModel(id)) {\n\t\treturn firstBakedInModel(bakedIn);\n\t}\n\tlet reasoning: Model<Api> | undefined;\n\tfor (const model of bakedIn) {\n\t\tif (model.reasoning && parseOpenAiGptVersion(model.id)) reasoning = model;\n\t}\n\treturn reasoning ?? firstBakedInModel(bakedIn);\n}\n\nexport function uniqueApis(models: readonly Model<Api>[]): Api[] {\n\tconst seen = new Set<Api>();\n\tconst apis: Api[] = [];\n\tfor (const model of models) {\n\t\tif (seen.has(model.api)) continue;\n\t\tseen.add(model.api);\n\t\tapis.push(model.api);\n\t}\n\treturn apis;\n}\n\nexport function synthesizeLiveModel(\n\tid: string,\n\ttemplate: Model<Api>,\n\traw: Record<string, unknown> = {},\n): LiveModelDiscovery {\n\tconst name = typeof raw.name === \"string\" && raw.name.trim() ? raw.name.trim() : id;\n\tconst exact = id === template.id;\n\tconst discovery: LiveModelDiscovery = {\n\t\tmodel: {\n\t\t\tid,\n\t\t\tname,\n\t\t\tapi: template.api,\n\t\t\tprovider: template.provider,\n\t\t\tbaseUrl: template.baseUrl,\n\t\t\treasoning: template.reasoning,\n\t\t\tinput: exact ? template.input : [\"text\"],\n\t\t\tcost: ZERO_COST,\n\t\t\tcontextWindow: DEFAULT_CONTEXT_WINDOW,\n\t\t\tmaxTokens: DEFAULT_MAX_TOKENS,\n\t\t\tcompat: template.compat,\n\t\t\tthinkingLevelMap: exact ? template.thinkingLevelMap : undefined,\n\t\t\tcatalog: { source: \"provider\", supplied: typeof raw.name === \"string\" ? [\"name\"] : [], pricing: \"unknown\" },\n\t\t},\n\t\tsupplied: {\n\t\t\t...NONE_SUPPLIED,\n\t\t\tname: typeof raw.name === \"string\" && raw.name.trim().length > 0,\n\t\t},\n\t};\n\tconst context = asFiniteNumber(raw.context_window ?? raw.context_length ?? raw.max_context_length);\n\tconst output = asFiniteNumber(raw.max_output_tokens ?? raw.max_completion_tokens);\n\tif (context && context > 0) {\n\t\tdiscovery.model.contextWindow = context;\n\t\tdiscovery.supplied.contextWindow = true;\n\t}\n\tif (output && output > 0) {\n\t\tdiscovery.model.maxTokens = output;\n\t\tdiscovery.supplied.maxTokens = true;\n\t}\n\tif (typeof raw.reasoning === \"boolean\") {\n\t\tdiscovery.model.reasoning = raw.reasoning;\n\t\tdiscovery.supplied.reasoning = true;\n\t}\n\tif (Array.isArray(raw.input_modalities)) {\n\t\tconst input = raw.input_modalities.filter(\n\t\t\t(value): value is \"text\" | \"image\" => value === \"text\" || value === \"image\",\n\t\t);\n\t\tif (input.length) {\n\t\t\tdiscovery.model.input = input;\n\t\t\tdiscovery.supplied.input = true;\n\t\t}\n\t}\n\tdiscovery.model.catalog!.supplied = Object.entries(discovery.supplied)\n\t\t.filter(([, value]) => value)\n\t\t.map(([field]) => field) as NonNullable<Model<Api>[\"catalog\"]>[\"supplied\"];\n\treturn discovery;\n}\n\n/** OpenRouter field mapping (tools filter, pricing × 1e6, context) from generate-models. */\nexport function mapOpenRouterModel(raw: Record<string, unknown>, template: Model<Api>): LiveModelDiscovery | undefined {\n\tconst id = typeof raw.id === \"string\" ? raw.id.trim() : \"\";\n\tif (!id) return undefined;\n\tconst supported = Array.isArray(raw.supported_parameters) ? raw.supported_parameters : [];\n\tif (!supported.includes(\"tools\")) return undefined;\n\n\tconst architecture = isRecord(raw.architecture) ? raw.architecture : undefined;\n\tconst modality = typeof architecture?.modality === \"string\" ? architecture.modality : \"\";\n\tconst input: (\"text\" | \"image\")[] = [\"text\"];\n\tif (modality.includes(\"image\")) input.push(\"image\");\n\n\tconst pricing = isRecord(raw.pricing) ? raw.pricing : undefined;\n\tconst inputCost = roundCost((asFiniteNumber(pricing?.prompt) ?? 0) * 1_000_000);\n\tconst outputCost = roundCost((asFiniteNumber(pricing?.completion) ?? 0) * 1_000_000);\n\tconst cacheReadCost = roundCost((asFiniteNumber(pricing?.input_cache_read) ?? 0) * 1_000_000);\n\tconst cacheWriteCost = roundCost((asFiniteNumber(pricing?.input_cache_write) ?? 0) * 1_000_000);\n\n\tconst topProvider = isRecord(raw.top_provider) ? raw.top_provider : undefined;\n\tconst contextWindow = asFiniteNumber(topProvider?.context_length) ?? asFiniteNumber(raw.context_length);\n\tconst maxTokens = asFiniteNumber(topProvider?.max_completion_tokens) ?? asFiniteNumber(raw.max_completion_tokens);\n\n\tconst name = typeof raw.name === \"string\" && raw.name.trim() ? raw.name.trim() : id;\n\treturn {\n\t\tmodel: {\n\t\t\tid,\n\t\t\tname,\n\t\t\tapi: template.api,\n\t\t\tprovider: template.provider,\n\t\t\tbaseUrl: template.baseUrl,\n\t\t\treasoning: supported.includes(\"reasoning\") || template.reasoning,\n\t\t\tinput,\n\t\t\tcost: {\n\t\t\t\tinput: inputCost,\n\t\t\t\toutput: outputCost,\n\t\t\t\tcacheRead: cacheReadCost,\n\t\t\t\tcacheWrite: cacheWriteCost,\n\t\t\t},\n\t\t\tcontextWindow: contextWindow ?? DEFAULT_CONTEXT_WINDOW,\n\t\t\tmaxTokens: maxTokens ?? DEFAULT_MAX_TOKENS,\n\t\t\tcompat: template.compat,\n\t\t\tthinkingLevelMap: template.thinkingLevelMap,\n\t\t},\n\t\tsupplied: {\n\t\t\tcontextWindow: contextWindow !== undefined,\n\t\t\tmaxTokens: maxTokens !== undefined,\n\t\t\tinput: true,\n\t\t\tname: typeof raw.name === \"string\" && raw.name.trim().length > 0,\n\t\t\tcost: asFiniteNumber(pricing?.prompt) !== undefined && asFiniteNumber(pricing?.completion) !== undefined,\n\t\t\treasoning: supported.includes(\"reasoning\"),\n\t\t},\n\t};\n}\n\nexport function discoverLiveModels(\n\tproviderId: string,\n\tpayload: unknown,\n\tbakedIn: readonly Model<Api>[],\n): LiveModelDiscovery[] {\n\tif (providerId === \"openai-codex\")\n\t\treturn discoverCodexModels(payload, bakedIn[0]?.baseUrl ?? \"https://chatgpt.com/backend-api\");\n\tconst fallback = firstBakedInModel(bakedIn);\n\tif (!fallback) return [];\n\tconst rows = parseOpenAIModelsList(payload);\n\tconst discoveries: LiveModelDiscovery[] = [];\n\tfor (const raw of rows) {\n\t\tconst id = typeof raw.id === \"string\" ? raw.id.trim() : \"\";\n\t\tif (!id) continue;\n\t\tif (\n\t\t\traw.tool_call === false ||\n\t\t\traw.type === \"embedding\" ||\n\t\t\t(providerId === \"openai\" &&\n\t\t\t\t/^(?:text-embedding-|tts-|whisper-|dall-e-|gpt-image-|gpt-audio|gpt-realtime|sora-|.*moderation)/i.test(id))\n\t\t)\n\t\t\tcontinue;\n\t\tconst template = { ...(selectLiveTemplate(providerId, id, bakedIn) ?? fallback), provider: providerId };\n\t\tif (providerId === \"openrouter\") {\n\t\t\tconst mapped = mapOpenRouterModel(raw, template);\n\t\t\tif (mapped) {\n\t\t\t\tmapped.model.catalog = {\n\t\t\t\t\tsource: \"provider\",\n\t\t\t\t\t...(!mapped.supplied.cost ? { pricing: \"unknown\" as const } : {}),\n\t\t\t\t\tsupplied: Object.entries(mapped.supplied)\n\t\t\t\t\t\t.filter(([, supplied]) => supplied)\n\t\t\t\t\t\t.map(([key]) => key) as NonNullable<Model<Api>[\"catalog\"]>[\"supplied\"],\n\t\t\t\t};\n\t\t\t\tmapped.model = normalizeCatalogPricing(mapped.model);\n\t\t\t\tif (mapped.model.catalog?.pricing === \"unknown\") mapped.supplied.cost = false;\n\t\t\t\tdiscoveries.push(mapped);\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\tdiscoveries.push(synthesizeLiveModel(id, template, raw));\n\t}\n\treturn discoveries;\n}\n\nexport function missingLiveFields(supplied: LiveFieldSupply): Array<\"contextWindow\" | \"maxTokens\" | \"input\"> {\n\tconst missing: Array<\"contextWindow\" | \"maxTokens\" | \"input\"> = [];\n\tif (!supplied.contextWindow) missing.push(\"contextWindow\");\n\tif (!supplied.maxTokens) missing.push(\"maxTokens\");\n\tif (!supplied.input) missing.push(\"input\");\n\treturn missing;\n}\n\nexport function isLiveModelIncomplete(discovery: LiveModelDiscovery, knownKeys: Set<string>): boolean {\n\tif (knownKeys.has(modelKey(discovery.model.provider, discovery.model.id))) return false;\n\treturn missingLiveFields(discovery.supplied).length > 0;\n}\n\nexport function collectIncompleteLiveModels(\n\tdiscoveries: readonly LiveModelDiscovery[],\n\tbakedIn: readonly Model<Api>[],\n\tknownKeys: Set<string>,\n): IncompleteLiveModel[] {\n\tconst apis = uniqueApis(bakedIn);\n\tconst incomplete: IncompleteLiveModel[] = [];\n\tfor (const discovery of discoveries) {\n\t\tif (!isLiveModelIncomplete(discovery, knownKeys)) continue;\n\t\tincomplete.push({\n\t\t\tprovider: discovery.model.provider,\n\t\t\tid: discovery.model.id,\n\t\t\tname: discovery.model.name,\n\t\t\tmissing: missingLiveFields(discovery.supplied),\n\t\t\tdraft: discovery.model,\n\t\t\tavailableApis: apis,\n\t\t});\n\t}\n\treturn incomplete;\n}\n\nexport function buildLiveOverlay(\n\tbakedIn: readonly Model<Api>[],\n\tdiscoveries: readonly LiveModelDiscovery[],\n): Model<Api>[] {\n\tconst bakedById = new Map(bakedIn.map((model) => [model.id, model]));\n\tconst overlay: Model<Api>[] = [];\n\tfor (const discovery of discoveries) {\n\t\tconst baked = bakedById.get(discovery.model.id);\n\t\tif (!baked) {\n\t\t\toverlay.push(discovery.model);\n\t\t\tcontinue;\n\t\t}\n\t\toverlay.push({\n\t\t\t...baked,\n\t\t\tcatalog: discovery.model.catalog,\n\t\t\tthinkingLevelMap: discovery.model.catalog?.supplied.includes(\"thinkingLevelMap\")\n\t\t\t\t? discovery.model.thinkingLevelMap\n\t\t\t\t: baked.thinkingLevelMap,\n\t\t\tname: discovery.supplied.name ? discovery.model.name : baked.name,\n\t\t\tcontextWindow: discovery.supplied.contextWindow ? discovery.model.contextWindow : baked.contextWindow,\n\t\t\tmaxTokens: discovery.supplied.maxTokens ? discovery.model.maxTokens : baked.maxTokens,\n\t\t\tinput: discovery.supplied.input ? discovery.model.input : baked.input,\n\t\t\tcost: discovery.supplied.cost ? discovery.model.cost : baked.cost,\n\t\t\treasoning: discovery.supplied.reasoning ? discovery.model.reasoning : baked.reasoning,\n\t\t});\n\t}\n\treturn overlay;\n}\n\nexport function describeIncomplete(model: IncompleteLiveModel): string {\n\tconst labels: string[] = [];\n\tfor (const field of model.missing) {\n\t\tif (field === \"contextWindow\") labels.push(\"context window\");\n\t\telse if (field === \"maxTokens\") labels.push(\"max tokens\");\n\t\telse labels.push(\"input types\");\n\t}\n\tlet missingText = \"metadata\";\n\tif (labels.length === 1) missingText = labels[0] ?? missingText;\n\telse if (labels.length === 2) missingText = `${labels[0]} and ${labels[1]}`;\n\telse if (labels.length > 2) missingText = `${labels.slice(0, -1).join(\", \")}, and ${labels[labels.length - 1]}`;\n\treturn `New model ${model.provider}/${model.id} — missing ${missingText}.`;\n}\n\nexport function parsePositiveInt(value: string | undefined, fallback: number): number {\n\tif (!value?.trim()) return fallback;\n\tconst parsed = Number(value.trim());\n\tif (!Number.isInteger(parsed) || parsed <= 0) return fallback;\n\treturn parsed;\n}\n\nexport interface IncompleteModelAnswers {\n\tcontextWindow?: number;\n\tmaxTokens?: number;\n\tinput?: (\"text\" | \"image\")[];\n\treasoning?: boolean;\n\tapi?: Api;\n}\n\nexport function applyIncompleteAnswers(draft: Model<Api>, answers: IncompleteModelAnswers): Model<Api> {\n\treturn {\n\t\t...draft,\n\t\tcontextWindow: answers.contextWindow ?? draft.contextWindow,\n\t\tmaxTokens: answers.maxTokens ?? draft.maxTokens,\n\t\tinput: answers.input ?? draft.input,\n\t\treasoning: answers.reasoning ?? draft.reasoning,\n\t\tapi: answers.api ?? draft.api,\n\t};\n}\n\nexport interface FetchLiveProviderModelsOptions {\n\tdiscoveryClientVersion?: string;\n\tproviderId: string;\n\tbaseUrl: string;\n\tbakedIn: readonly Model<Api>[];\n\tcredential?: Credential;\n\tknownKeys: Set<string>;\n\ttimeoutMs?: number;\n\tsignal?: AbortSignal;\n\tfetchImpl?: typeof fetch;\n}\n\nexport async function fetchLiveProviderModels(options: FetchLiveProviderModelsOptions): Promise<LiveCatalogResult> {\n\tconst empty: LiveCatalogResult = {\n\t\tproviderId: options.providerId,\n\t\tstatus: \"skipped\",\n\t\tdiscoveries: [],\n\t\tadded: 0,\n\t\ttotal: 0,\n\t\tincomplete: [],\n\t};\n\tconst template = firstBakedInModel(options.bakedIn);\n\tif ((!template && options.providerId !== \"openai-codex\") || !options.baseUrl) return empty;\n\n\tconst timeoutMs = options.timeoutMs ?? LIVE_CATALOG_TIMEOUT_MS;\n\tconst controller = new AbortController();\n\tlet timedOut = false;\n\tconst timer = setTimeout(() => {\n\t\ttimedOut = true;\n\t\tcontroller.abort();\n\t}, timeoutMs);\n\tconst onParentAbort = () => controller.abort();\n\toptions.signal?.addEventListener(\"abort\", onParentAbort, { once: true });\n\tif (options.signal?.aborted) controller.abort();\n\n\ttry {\n\t\tconst fetchImpl = options.fetchImpl ?? fetch;\n\t\tconst codex = options.providerId === \"openai-codex\";\n\t\tconst accountId =\n\t\t\toptions.credential?.type === \"oauth\" && typeof options.credential.accountId === \"string\"\n\t\t\t\t? options.credential.accountId\n\t\t\t\t: undefined;\n\t\tlet discoveryClientVersion = options.discoveryClientVersion;\n\t\tconst payload = await Promise.race([\n\t\t\t(async () => {\n\t\t\t\tif (codex)\n\t\t\t\t\tdiscoveryClientVersion = await resolveCodexCatalogVersion(\n\t\t\t\t\t\tfetchImpl,\n\t\t\t\t\t\tcontroller.signal,\n\t\t\t\t\t\tdiscoveryClientVersion,\n\t\t\t\t\t);\n\t\t\t\tconst response = await fetchImpl(\n\t\t\t\t\tcodex ? codexModelsUrl(options.baseUrl, discoveryClientVersion) : modelsListUrl(options.baseUrl),\n\t\t\t\t\t{\n\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\taccept: \"application/json\",\n\t\t\t\t\t\t\t\"User-Agent\": getPiUserAgent(VERSION),\n\t\t\t\t\t\t\t...credentialAuthHeaders(options.credential),\n\t\t\t\t\t\t\t...(accountId ? { \"ChatGPT-Account-ID\": accountId } : {}),\n\t\t\t\t\t\t},\n\t\t\t\t\t\tsignal: controller.signal,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tif (!response.ok) throw new Error(`HTTP ${response.status}`);\n\t\t\t\treturn response.json();\n\t\t\t})(),\n\t\t\tnew Promise<never>((_, reject) => {\n\t\t\t\tconst abortError = new Error(\"The operation was aborted\");\n\t\t\t\tabortError.name = \"AbortError\";\n\t\t\t\tcontroller.signal.addEventListener(\"abort\", () => reject(abortError), { once: true });\n\t\t\t\tif (controller.signal.aborted) reject(abortError);\n\t\t\t}),\n\t\t]);\n\t\tconst discoveries = codex\n\t\t\t? discoverCodexModels(payload, options.baseUrl)\n\t\t\t: discoverLiveModels(options.providerId, payload, options.bakedIn);\n\t\tif (!discoveries.length) throw new Error(\"No usable models returned; retaining cached models\");\n\t\tconst bakedIds = new Set(options.bakedIn.map((model) => model.id));\n\t\tconst added = discoveries.filter((discovery) => !bakedIds.has(discovery.model.id)).length;\n\t\treturn {\n\t\t\tproviderId: options.providerId,\n\t\t\tdiscoveryClientVersion,\n\t\t\tstatus: \"ok\",\n\t\t\tdiscoveries,\n\t\t\tadded,\n\t\t\ttotal: discoveries.length,\n\t\t\tincomplete: collectIncompleteLiveModels(discoveries, options.bakedIn, options.knownKeys),\n\t\t};\n\t} catch (error) {\n\t\tif (options.signal?.aborted && !timedOut) return { ...empty, status: \"skipped\", error: \"aborted\" };\n\t\tif (timedOut || (error instanceof Error && error.name === \"AbortError\")) {\n\t\t\treturn { ...empty, status: \"timeout\", error: \"timed out\" };\n\t\t}\n\t\treturn {\n\t\t\t...empty,\n\t\t\tstatus: \"error\",\n\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t};\n\t} finally {\n\t\tclearTimeout(timer);\n\t\toptions.signal?.removeEventListener(\"abort\", onParentAbort);\n\t}\n}\n"]}
@@ -60,6 +60,8 @@ export declare class ModelRuntime implements Models {
60
60
  private lastOfficial;
61
61
  private catalogRefresh;
62
62
  private catalogRefreshAllowsNetwork;
63
+ private nextAutomaticRefresh;
64
+ private automaticRefreshIdentity;
63
65
  private readonly grokHome;
64
66
  private constructor();
65
67
  static create(options?: CreateModelRuntimeOptions): Promise<ModelRuntime>;
@@ -73,6 +75,7 @@ export declare class ModelRuntime implements Models {
73
75
  private bakedInModels;
74
76
  private rebuildProviders;
75
77
  private updateModelSnapshot;
78
+ private isCatalogModelAvailable;
76
79
  private listStoredProviderIds;
77
80
  /** `/model` lists stored creds + models.json/extension keys, never ambient envApiKeyAuth. */
78
81
  private configuredProviderIds;
@@ -122,6 +125,11 @@ export declare class ModelRuntime implements Models {
122
125
  refresh(options?: ModelsRefreshOptions): Promise<CatalogRefreshResult>;
123
126
  private executeCatalogRefresh;
124
127
  getLastCatalogRefresh(): CatalogRefreshResult;
128
+ /** Called after first paint and by the picker; explicit /refresh always bypasses this gate. */
129
+ refreshIfStale(options?: {
130
+ signal?: AbortSignal;
131
+ }): Promise<CatalogRefreshResult>;
132
+ private scopeFor;
125
133
  persistUserModels(rows: readonly UserModelEntry[]): void;
126
134
  private refreshOfficialCatalog;
127
135
  private restoreLiveCatalogs;