@ashx-j/lunr 0.2.12 → 0.2.14

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 (225) hide show
  1. package/CHANGELOG.md +16 -1
  2. package/README.md +6 -3
  3. package/dist/builtin-extensions/ashxj-tui.d.ts +16 -1
  4. package/dist/builtin-extensions/ashxj-tui.d.ts.map +1 -1
  5. package/dist/builtin-extensions/ashxj-tui.js +44 -20
  6. package/dist/builtin-extensions/ashxj-tui.js.map +1 -1
  7. package/dist/builtin-extensions/pi-subagents/src/extension/index.d.ts +2 -0
  8. package/dist/builtin-extensions/pi-subagents/src/extension/index.d.ts.map +1 -1
  9. package/dist/builtin-extensions/pi-subagents/src/extension/index.js +27 -22
  10. package/dist/builtin-extensions/pi-subagents/src/extension/index.js.map +1 -1
  11. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-execution.d.ts.map +1 -1
  12. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-execution.js +5 -2
  13. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-execution.js.map +1 -1
  14. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-resume.d.ts.map +1 -1
  15. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-resume.js +12 -1
  16. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-resume.js.map +1 -1
  17. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-status.d.ts +1 -0
  18. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-status.d.ts.map +1 -1
  19. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-status.js +3 -2
  20. package/dist/builtin-extensions/pi-subagents/src/runs/background/async-status.js.map +1 -1
  21. package/dist/builtin-extensions/pi-subagents/src/runs/background/chain-append.d.ts.map +1 -1
  22. package/dist/builtin-extensions/pi-subagents/src/runs/background/chain-append.js +1 -0
  23. package/dist/builtin-extensions/pi-subagents/src/runs/background/chain-append.js.map +1 -1
  24. package/dist/builtin-extensions/pi-subagents/src/runs/background/chain-root-attachment.d.ts.map +1 -1
  25. package/dist/builtin-extensions/pi-subagents/src/runs/background/chain-root-attachment.js +3 -0
  26. package/dist/builtin-extensions/pi-subagents/src/runs/background/chain-root-attachment.js.map +1 -1
  27. package/dist/builtin-extensions/pi-subagents/src/runs/background/fleet-view.d.ts.map +1 -1
  28. package/dist/builtin-extensions/pi-subagents/src/runs/background/fleet-view.js +3 -3
  29. package/dist/builtin-extensions/pi-subagents/src/runs/background/fleet-view.js.map +1 -1
  30. package/dist/builtin-extensions/pi-subagents/src/runs/background/run-status.d.ts.map +1 -1
  31. package/dist/builtin-extensions/pi-subagents/src/runs/background/run-status.js +2 -2
  32. package/dist/builtin-extensions/pi-subagents/src/runs/background/run-status.js.map +1 -1
  33. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-runner.d.ts.map +1 -1
  34. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-runner.js +3 -0
  35. package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-runner.js.map +1 -1
  36. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-execution.d.ts.map +1 -1
  37. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-execution.js +7 -1
  38. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-execution.js.map +1 -1
  39. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/execution.d.ts.map +1 -1
  40. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/execution.js +2 -0
  41. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/execution.js.map +1 -1
  42. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.d.ts +1 -0
  43. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.d.ts.map +1 -1
  44. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.js +19 -3
  45. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.js.map +1 -1
  46. package/dist/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.d.ts +10 -1
  47. package/dist/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.d.ts.map +1 -1
  48. package/dist/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.js +19 -0
  49. package/dist/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.js.map +1 -1
  50. package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.d.ts +1 -0
  51. package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.d.ts.map +1 -1
  52. package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.js.map +1 -1
  53. package/dist/builtin-extensions/pi-subagents/src/shared/child-spec.d.ts +2 -1
  54. package/dist/builtin-extensions/pi-subagents/src/shared/child-spec.d.ts.map +1 -1
  55. package/dist/builtin-extensions/pi-subagents/src/shared/child-spec.js +17 -0
  56. package/dist/builtin-extensions/pi-subagents/src/shared/child-spec.js.map +1 -1
  57. package/dist/builtin-extensions/pi-subagents/src/shared/formatters.d.ts +3 -1
  58. package/dist/builtin-extensions/pi-subagents/src/shared/formatters.d.ts.map +1 -1
  59. package/dist/builtin-extensions/pi-subagents/src/shared/formatters.js +14 -3
  60. package/dist/builtin-extensions/pi-subagents/src/shared/formatters.js.map +1 -1
  61. package/dist/builtin-extensions/pi-subagents/src/shared/types.d.ts +14 -0
  62. package/dist/builtin-extensions/pi-subagents/src/shared/types.d.ts.map +1 -1
  63. package/dist/builtin-extensions/pi-subagents/src/shared/types.js.map +1 -1
  64. package/dist/builtin-extensions/pi-subagents/src/tui/fleet.d.ts.map +1 -1
  65. package/dist/builtin-extensions/pi-subagents/src/tui/fleet.js +2 -2
  66. package/dist/builtin-extensions/pi-subagents/src/tui/fleet.js.map +1 -1
  67. package/dist/builtin-extensions/pi-subagents/src/tui/render.d.ts.map +1 -1
  68. package/dist/builtin-extensions/pi-subagents/src/tui/render.js +12 -10
  69. package/dist/builtin-extensions/pi-subagents/src/tui/render.js.map +1 -1
  70. package/dist/catalog/models.json +1 -1
  71. package/dist/catalog/providers/amazon-bedrock.json +1 -1
  72. package/dist/catalog/providers/anthropic.json +1 -1
  73. package/dist/catalog/providers/azure-openai-responses.json +1 -1
  74. package/dist/catalog/providers/cloudflare-ai-gateway.json +1 -1
  75. package/dist/catalog/providers/cloudflare-workers-ai.json +1 -1
  76. package/dist/catalog/providers/fireworks.json +1 -1
  77. package/dist/catalog/providers/github-copilot.json +1 -1
  78. package/dist/catalog/providers/google-vertex.json +1 -1
  79. package/dist/catalog/providers/google.json +1 -1
  80. package/dist/catalog/providers/groq.json +1 -1
  81. package/dist/catalog/providers/huggingface.json +1 -1
  82. package/dist/catalog/providers/nvidia.json +1 -1
  83. package/dist/catalog/providers/openai-codex.json +1 -1
  84. package/dist/catalog/providers/openai.json +1 -1
  85. package/dist/catalog/providers/opencode-go.json +1 -1
  86. package/dist/catalog/providers/opencode.json +1 -1
  87. package/dist/catalog/providers/openrouter.json +1 -1
  88. package/dist/catalog/providers/together.json +1 -1
  89. package/dist/catalog/providers/vercel-ai-gateway.json +1 -1
  90. package/dist/catalog/publication.json +131 -3
  91. package/dist/cli/list-models.d.ts.map +1 -1
  92. package/dist/cli/list-models.js +1 -0
  93. package/dist/cli/list-models.js.map +1 -1
  94. package/dist/cli.d.ts.map +1 -1
  95. package/dist/cli.js +52 -27
  96. package/dist/cli.js.map +1 -1
  97. package/dist/core/catalog-cache-scope.d.ts +3 -0
  98. package/dist/core/catalog-cache-scope.d.ts.map +1 -0
  99. package/dist/core/catalog-cache-scope.js +12 -0
  100. package/dist/core/catalog-cache-scope.js.map +1 -0
  101. package/dist/core/catalog-merge.d.ts +2 -0
  102. package/dist/core/catalog-merge.d.ts.map +1 -1
  103. package/dist/core/catalog-merge.js +29 -2
  104. package/dist/core/catalog-merge.js.map +1 -1
  105. package/dist/core/catalog-refresh-polling.d.ts +8 -0
  106. package/dist/core/catalog-refresh-polling.d.ts.map +1 -0
  107. package/dist/core/catalog-refresh-polling.js +30 -0
  108. package/dist/core/catalog-refresh-polling.js.map +1 -0
  109. package/dist/core/codex-catalog.d.ts +3 -0
  110. package/dist/core/codex-catalog.d.ts.map +1 -0
  111. package/dist/core/codex-catalog.js +15 -0
  112. package/dist/core/codex-catalog.js.map +1 -0
  113. package/dist/core/context-breakdown.d.ts +3 -1
  114. package/dist/core/context-breakdown.d.ts.map +1 -1
  115. package/dist/core/context-breakdown.js +5 -2
  116. package/dist/core/context-breakdown.js.map +1 -1
  117. package/dist/core/customize.d.ts +2 -4
  118. package/dist/core/customize.d.ts.map +1 -1
  119. package/dist/core/customize.js +2 -8
  120. package/dist/core/customize.js.map +1 -1
  121. package/dist/core/footer-data-provider.d.ts +3 -4
  122. package/dist/core/footer-data-provider.d.ts.map +1 -1
  123. package/dist/core/footer-data-provider.js +54 -82
  124. package/dist/core/footer-data-provider.js.map +1 -1
  125. package/dist/core/live-catalog.d.ts +5 -2
  126. package/dist/core/live-catalog.d.ts.map +1 -1
  127. package/dist/core/live-catalog.js +108 -27
  128. package/dist/core/live-catalog.js.map +1 -1
  129. package/dist/core/model-runtime.d.ts +8 -0
  130. package/dist/core/model-runtime.d.ts.map +1 -1
  131. package/dist/core/model-runtime.js +64 -12
  132. package/dist/core/model-runtime.js.map +1 -1
  133. package/dist/core/official-catalog.d.ts +4 -0
  134. package/dist/core/official-catalog.d.ts.map +1 -1
  135. package/dist/core/official-catalog.js +86 -21
  136. package/dist/core/official-catalog.js.map +1 -1
  137. package/dist/core/settings-manager.d.ts +7 -6
  138. package/dist/core/settings-manager.d.ts.map +1 -1
  139. package/dist/core/settings-manager.js +13 -17
  140. package/dist/core/settings-manager.js.map +1 -1
  141. package/dist/core/slash-commands.d.ts.map +1 -1
  142. package/dist/core/slash-commands.js +1 -0
  143. package/dist/core/slash-commands.js.map +1 -1
  144. package/dist/index.d.ts +1 -1
  145. package/dist/index.d.ts.map +1 -1
  146. package/dist/index.js.map +1 -1
  147. package/dist/main.d.ts +2 -0
  148. package/dist/main.d.ts.map +1 -1
  149. package/dist/main.js +106 -50
  150. package/dist/main.js.map +1 -1
  151. package/dist/migrations.d.ts +2 -0
  152. package/dist/migrations.d.ts.map +1 -1
  153. package/dist/migrations.js +14 -4
  154. package/dist/migrations.js.map +1 -1
  155. package/dist/modes/interactive/components/assistant-message.d.ts +1 -3
  156. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  157. package/dist/modes/interactive/components/assistant-message.js +4 -32
  158. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  159. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
  160. package/dist/modes/interactive/components/custom-editor.js +2 -1
  161. package/dist/modes/interactive/components/custom-editor.js.map +1 -1
  162. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  163. package/dist/modes/interactive/components/model-selector.js +4 -1
  164. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  165. package/dist/modes/interactive/components/plan-message.d.ts +1 -3
  166. package/dist/modes/interactive/components/plan-message.d.ts.map +1 -1
  167. package/dist/modes/interactive/components/plan-message.js +1 -16
  168. package/dist/modes/interactive/components/plan-message.js.map +1 -1
  169. package/dist/modes/interactive/components/settings-selector.d.ts +3 -5
  170. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  171. package/dist/modes/interactive/components/settings-selector.js +113 -117
  172. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  173. package/dist/modes/interactive/components/user-message.d.ts +1 -3
  174. package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  175. package/dist/modes/interactive/components/user-message.js +2 -19
  176. package/dist/modes/interactive/components/user-message.js.map +1 -1
  177. package/dist/modes/interactive/interactive-mode.d.ts +12 -1
  178. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  179. package/dist/modes/interactive/interactive-mode.js +153 -130
  180. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  181. package/dist/modes/interactive/skill-tag-autocomplete.d.ts +13 -0
  182. package/dist/modes/interactive/skill-tag-autocomplete.d.ts.map +1 -0
  183. package/dist/modes/interactive/skill-tag-autocomplete.js +72 -0
  184. package/dist/modes/interactive/skill-tag-autocomplete.js.map +1 -0
  185. package/dist/modes/interactive/theme/moon.json +0 -1
  186. package/dist/modes/interactive/theme/theme-schema.json +3 -3
  187. package/dist/modes/interactive/theme/theme.d.ts +1 -1
  188. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  189. package/dist/modes/interactive/theme/theme.js +95 -90
  190. package/dist/modes/interactive/theme/theme.js.map +1 -1
  191. package/dist/startup/interactive-view.d.ts +55 -0
  192. package/dist/startup/interactive-view.d.ts.map +1 -0
  193. package/dist/startup/interactive-view.js +332 -0
  194. package/dist/startup/interactive-view.js.map +1 -0
  195. package/dist/startup/launch-routing.d.ts +8 -0
  196. package/dist/startup/launch-routing.d.ts.map +1 -0
  197. package/dist/startup/launch-routing.js +29 -0
  198. package/dist/startup/launch-routing.js.map +1 -0
  199. package/dist/startup/startup-milestones.d.ts +4 -0
  200. package/dist/startup/startup-milestones.d.ts.map +1 -0
  201. package/dist/startup/startup-milestones.js +14 -0
  202. package/dist/startup/startup-milestones.js.map +1 -0
  203. package/dist/utils/syntax-highlight.d.ts.map +1 -1
  204. package/dist/utils/syntax-highlight.js +10 -4
  205. package/dist/utils/syntax-highlight.js.map +1 -1
  206. package/docs/features.md +2 -2
  207. package/docs/interactive-startup.md +58 -0
  208. package/docs/keybindings.md +1 -1
  209. package/docs/model-catalog.md +29 -0
  210. package/docs/quickstart.md +1 -1
  211. package/docs/settings.md +2 -3
  212. package/docs/skills.md +10 -0
  213. package/docs/terminal-setup.md +2 -2
  214. package/docs/usage.md +2 -1
  215. package/docs/windows.md +1 -1
  216. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  217. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  218. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  219. package/examples/extensions/gondolin/package-lock.json +2 -2
  220. package/examples/extensions/gondolin/package.json +1 -1
  221. package/examples/extensions/sandbox/package-lock.json +2 -2
  222. package/examples/extensions/sandbox/package.json +1 -1
  223. package/examples/extensions/with-deps/package-lock.json +2 -2
  224. package/examples/extensions/with-deps/package.json +1 -1
  225. package/package.json +16 -16
@@ -1,6 +1,134 @@
1
1
  {
2
- "generatedAt": "2026-08-29T19:25:04.565Z",
3
- "sourceCommit": "10c801b19c19d6114c15231006a2e8ff0772085d",
2
+ "version": 2,
3
+ "revision": "sha256-e4f0493be0ddc4665131268d7cd9eeee0ece7b68a438edd4e06eb392b1b77fcf",
4
+ "providers": [
5
+ "amazon-bedrock",
6
+ "ant-ling",
7
+ "anthropic",
8
+ "azure-openai-responses",
9
+ "cerebras",
10
+ "cloudflare-ai-gateway",
11
+ "cloudflare-workers-ai",
12
+ "deepseek",
13
+ "fireworks",
14
+ "github-copilot",
15
+ "google",
16
+ "google-vertex",
17
+ "groq",
18
+ "huggingface",
19
+ "kimi-coding",
20
+ "minimax",
21
+ "minimax-cn",
22
+ "mistral",
23
+ "moonshotai",
24
+ "moonshotai-cn",
25
+ "nvidia",
26
+ "openai",
27
+ "openai-codex",
28
+ "opencode",
29
+ "opencode-go",
30
+ "openrouter",
31
+ "qwen-cloud",
32
+ "qwen-cloud-cn",
33
+ "qwen-token-plan",
34
+ "qwen-token-plan-cn",
35
+ "together",
36
+ "vercel-ai-gateway",
37
+ "xai",
38
+ "xiaomi",
39
+ "xiaomi-token-plan-ams",
40
+ "xiaomi-token-plan-cn",
41
+ "xiaomi-token-plan-sgp",
42
+ "zai",
43
+ "zai-coding-cn"
44
+ ],
45
+ "shards": {
46
+ "amazon-bedrock": "efb2ece675233c7e358cac47817e2cc8dd7e0f09f24f0e2217c7c5a5851fe360",
47
+ "ant-ling": "85d35f44183c9558dc86c7698700a48a3b7b7c119a615fa684bd00ca56f6062f",
48
+ "anthropic": "a416ba1ae04a43a10c20e3df915990c3b49d36246ce416e9e2789d2e608c3f19",
49
+ "azure-openai-responses": "84c84a33d01e4484c79e2871e03361a7e884a8e6f99022b6f3aefc0e5057203f",
50
+ "cerebras": "a462bf870090b76280d83116e3731c076d5972ad3f41b2ca7dc882b575ce8f98",
51
+ "cloudflare-ai-gateway": "bbd5da35bbdfca1910da32e6c9a2fbf202ccceec37d50fb0203433941b73db74",
52
+ "cloudflare-workers-ai": "a0b371e234fecad108e3247da2808c0dca78ccf9d7ca932bfbf8853bf5d7bee1",
53
+ "deepseek": "ca5d7ba4befdf2a01f93ef0aefecf05ae3c1c3af2851814fa909bd49e035e17f",
54
+ "fireworks": "703747604b788f393b8c62ef914f80f0546a0a7de3cb2127fa42eb27d8a2946a",
55
+ "github-copilot": "c4f8891a3b5e8f36bdcd0dfb6f96cf623d0c22e46ef070564d3208cd2b981063",
56
+ "google": "c432ced269c2c9d556c16b8a54e5e60956f99f96f12637b09141d9813d23f554",
57
+ "google-vertex": "196ba8b70801b66bf41f7f7e9ac3a17c90ef7f219ea6f8e8a7365e759e66a23c",
58
+ "groq": "570718dc81117da906dfd3e0ac63e6edbc3f24e7c78159d64b4a698cb5aa1805",
59
+ "huggingface": "3f34d7ca275d1e1bd7bf7c8737d54f5bf1f7a0a0d2eba773099d5af83ad1224d",
60
+ "kimi-coding": "90920ef2a2fd2ea0b56364c44b9ac5011e2b286f19bce86d5dd3253e8685d738",
61
+ "minimax": "296b507c02b64625557cfabcaff24c17aa596414ca0750cd649464f5bddb6ad7",
62
+ "minimax-cn": "a157a4146eddeb80604f74d5402a4a9a30c1dd00f61ae65e52bbde4a7ebe56f9",
63
+ "mistral": "20ab53b7dcdf97f8d30e4ece80512bb4c026888eb915ae9286daf62683f5f663",
64
+ "moonshotai": "774a389bc8b6e29554da5f7129b3b6b462ccc903398740917557f29cb0ff77cb",
65
+ "moonshotai-cn": "8eda731eb0bc505102e4ceb2e2e465d71a87b1dfdde2af672284906fad9bbfb0",
66
+ "nvidia": "e88cdbd97cab570f0cb0b56e9aa3740da8ef5da659625e3b9f3b6762c21abed8",
67
+ "openai": "43b40fc0d8136483cbc96c0bf2959e640ae4e685fc34afe86fd98f2f4deb5445",
68
+ "openai-codex": "a958bf6c271e35ac83ad57aca795d251ee4cc791fb815631468a34041c1c69ce",
69
+ "opencode": "f3d17fdac9b2b3a144b252f15bda9e8934152090aeb5bd8773cf776187717e9b",
70
+ "opencode-go": "a1ad132f63237c70ee501307102e21520c97c7b8d0817449293c83585aa46392",
71
+ "openrouter": "af3c0ab4b3253d71b907a2eee3f49f3bd57682f70ded9a8c06fffb66ae08b6d4",
72
+ "qwen-cloud": "fe88d6387ffab4a09d18eb0189a054526036a5003029f9a5ac42b5926880395d",
73
+ "qwen-cloud-cn": "3a3ece652c9b3f7baad1320155587945e5b95efee86bff3b439d580198a329a1",
74
+ "qwen-token-plan": "c6bc53c40ab2e9fcb84b2ad5dff28ee78dbf586e57ee9a94481998a72ebccffc",
75
+ "qwen-token-plan-cn": "aeb61deb931c9adbfca9884207e900bedf57965bc029b5f65a646ee1ba68e183",
76
+ "together": "af2fa47920f07f3927f2413335ee23408cb9b7ab08c580facc192ea9ee18ec66",
77
+ "vercel-ai-gateway": "72f1c38a0d4c357521a9fb297ab3e752938a3fd21dc02f12c1171ac78f7e9c7f",
78
+ "xai": "26945e08d10e7daadf3deae2feecfd67a75767aa16e7a86bf1061024cf293044",
79
+ "xiaomi": "9fee25834768f63373eb99f7140a3c45a37abfaa7122effaf3bbf457863936a6",
80
+ "xiaomi-token-plan-ams": "5673c0507d4066b5f5185a506f812cd84faf8bd9b0201ec825a369127084a13f",
81
+ "xiaomi-token-plan-cn": "18270ac2ea0449947ff300720f503ae0ed5758b4070fb54803d19f4991c031dd",
82
+ "xiaomi-token-plan-sgp": "ffaa2b7532971b05c514441681ac2b885bf666835d54fab119d8ec9731bfba17",
83
+ "zai": "3f03a61d7a3a86da7b245064e0d7abab8f82b224cb06fa50c114c56444a4ee23",
84
+ "zai-coding-cn": "9fb458e1854b88f85c6c84cd3b56658df3a0063bb8e135c2a292a6371dcab625"
85
+ },
86
+ "sources": [
87
+ {
88
+ "url": "https://ai-gateway.vercel.sh/v1/models",
89
+ "status": "fresh",
90
+ "fetchedAt": "2026-09-05T10:38:35.773Z",
91
+ "digest": "7b7eafbf296781b2a9caabc581359aa0c574669957b769ce637035164d5081d8"
92
+ },
93
+ {
94
+ "url": "https://integrate.api.nvidia.com/v1/models",
95
+ "status": "fresh",
96
+ "fetchedAt": "2026-09-05T10:38:35.833Z",
97
+ "digest": "9aeda5acda7aff735b50b78ada52060fbad4f91c2315477d6b08d981aedae511"
98
+ },
99
+ {
100
+ "url": "https://models.dev/api.json",
101
+ "status": "fresh",
102
+ "fetchedAt": "2026-09-05T10:38:35.643Z",
103
+ "digest": "5ca22a6997fae0d44f6ae8eed27d22214a1d0e7387f45aa040f550eb8f43de61"
104
+ },
105
+ {
106
+ "url": "https://opencode.ai/zen/go/v1/models",
107
+ "status": "fresh",
108
+ "fetchedAt": "2026-09-05T10:38:36.351Z",
109
+ "digest": "f6a73fe21d004e12e13028a77029f8659bd914fde4c2af0191e99d76ae960111"
110
+ },
111
+ {
112
+ "url": "https://opencode.ai/zen/v1/models",
113
+ "status": "fresh",
114
+ "fetchedAt": "2026-09-05T10:38:36.241Z",
115
+ "digest": "8ca1e6c9a2121ee57244e3067fb815df0ca214ae122b18f607eec30d801a263c"
116
+ },
117
+ {
118
+ "url": "https://openrouter.ai/api/v1/models",
119
+ "status": "fresh",
120
+ "fetchedAt": "2026-09-05T10:38:35.489Z",
121
+ "digest": "f9c6914208b09725eb998234b3881149b58ab5f389fc94fd437991924420d331"
122
+ },
123
+ {
124
+ "url": "https://raw.githubusercontent.com/openai/codex/main/codex-rs/models-manager/models.json",
125
+ "status": "fresh",
126
+ "fetchedAt": "2026-09-05T10:38:35.718Z",
127
+ "digest": "8f454d185afd210f9d8cc71b7053d6165f7fccb679546eca4ac02fe960f4cff8"
128
+ }
129
+ ],
130
+ "generatedAt": "2026-09-05T10:38:36.535Z",
131
+ "sourceCommit": "8a08e872fb3d61b9b62e2958d9ca84b4821f17a5",
4
132
  "providerCount": 39,
5
- "modelCount": 1392
133
+ "modelCount": 1457
6
134
  }
@@ -1 +1 @@
1
- {"version":3,"file":"list-models.d.ts","sourceRoot":"","sources":["../../src/cli/list-models.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAiB7D;;GAEG;AACH,wBAAsB,UAAU,CAAC,YAAY,EAAE,YAAY,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAkFlG","sourcesContent":["/**\n * List available models with optional fuzzy search\n */\n\nimport type { Api, Model } from \"@ashx-j/lunr-ai\";\nimport { fuzzyFilter } from \"@ashx-j/lunr-tui\";\nimport chalk from \"chalk\";\nimport { formatNoModelsAvailableMessage } from \"../core/auth-guidance.ts\";\nimport type { ModelRuntime } from \"../core/model-runtime.ts\";\n\n/**\n * Format a number as human-readable (e.g., 200000 -> \"200K\", 1000000 -> \"1M\")\n */\nfunction formatTokenCount(count: number): string {\n\tif (count >= 1_000_000) {\n\t\tconst millions = count / 1_000_000;\n\t\treturn millions % 1 === 0 ? `${millions}M` : `${millions.toFixed(1)}M`;\n\t}\n\tif (count >= 1_000) {\n\t\tconst thousands = count / 1_000;\n\t\treturn thousands % 1 === 0 ? `${thousands}K` : `${thousands.toFixed(1)}K`;\n\t}\n\treturn count.toString();\n}\n\n/**\n * List available models, optionally filtered by search pattern\n */\nexport async function listModels(modelRuntime: ModelRuntime, searchPattern?: string): Promise<void> {\n\tconst loadError = modelRuntime.getError();\n\tif (loadError) {\n\t\tconsole.error(chalk.yellow(`Warning: errors loading models.json:\\n${loadError}`));\n\t}\n\n\tconst models = [...(await modelRuntime.getAvailable())];\n\n\tif (models.length === 0) {\n\t\tconsole.log(formatNoModelsAvailableMessage());\n\t\treturn;\n\t}\n\n\t// Apply fuzzy filter if search pattern provided\n\tlet filteredModels: Model<Api>[] = models;\n\tif (searchPattern) {\n\t\tfilteredModels = fuzzyFilter(models, searchPattern, (m) => `${m.provider} ${m.id}`);\n\t}\n\n\tif (filteredModels.length === 0) {\n\t\tconsole.log(`No models matching \"${searchPattern}\"`);\n\t\treturn;\n\t}\n\n\t// Sort by provider, then by model id\n\tfilteredModels.sort((a, b) => {\n\t\tconst providerCmp = a.provider.localeCompare(b.provider);\n\t\tif (providerCmp !== 0) return providerCmp;\n\t\treturn a.id.localeCompare(b.id);\n\t});\n\n\t// Calculate column widths\n\tconst rows = filteredModels.map((m) => ({\n\t\tprovider: m.provider,\n\t\tmodel: m.id,\n\t\tcontext: formatTokenCount(m.contextWindow),\n\t\tmaxOut: formatTokenCount(m.maxTokens),\n\t\tthinking: m.reasoning ? \"yes\" : \"no\",\n\t\timages: m.input.includes(\"image\") ? \"yes\" : \"no\",\n\t}));\n\n\tconst headers = {\n\t\tprovider: \"provider\",\n\t\tmodel: \"model\",\n\t\tcontext: \"context\",\n\t\tmaxOut: \"max-out\",\n\t\tthinking: \"thinking\",\n\t\timages: \"images\",\n\t};\n\n\tconst widths = {\n\t\tprovider: Math.max(headers.provider.length, ...rows.map((r) => r.provider.length)),\n\t\tmodel: Math.max(headers.model.length, ...rows.map((r) => r.model.length)),\n\t\tcontext: Math.max(headers.context.length, ...rows.map((r) => r.context.length)),\n\t\tmaxOut: Math.max(headers.maxOut.length, ...rows.map((r) => r.maxOut.length)),\n\t\tthinking: Math.max(headers.thinking.length, ...rows.map((r) => r.thinking.length)),\n\t\timages: Math.max(headers.images.length, ...rows.map((r) => r.images.length)),\n\t};\n\n\t// Print header\n\tconst headerLine = [\n\t\theaders.provider.padEnd(widths.provider),\n\t\theaders.model.padEnd(widths.model),\n\t\theaders.context.padEnd(widths.context),\n\t\theaders.maxOut.padEnd(widths.maxOut),\n\t\theaders.thinking.padEnd(widths.thinking),\n\t\theaders.images.padEnd(widths.images),\n\t].join(\" \");\n\tconsole.log(headerLine);\n\n\t// Print rows\n\tfor (const row of rows) {\n\t\tconst line = [\n\t\t\trow.provider.padEnd(widths.provider),\n\t\t\trow.model.padEnd(widths.model),\n\t\t\trow.context.padEnd(widths.context),\n\t\t\trow.maxOut.padEnd(widths.maxOut),\n\t\t\trow.thinking.padEnd(widths.thinking),\n\t\t\trow.images.padEnd(widths.images),\n\t\t].join(\" \");\n\t\tconsole.log(line);\n\t}\n}\n"]}
1
+ {"version":3,"file":"list-models.d.ts","sourceRoot":"","sources":["../../src/cli/list-models.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAiB7D;;GAEG;AACH,wBAAsB,UAAU,CAAC,YAAY,EAAE,YAAY,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAmFlG","sourcesContent":["/**\n * List available models with optional fuzzy search\n */\n\nimport type { Api, Model } from \"@ashx-j/lunr-ai\";\nimport { fuzzyFilter } from \"@ashx-j/lunr-tui\";\nimport chalk from \"chalk\";\nimport { formatNoModelsAvailableMessage } from \"../core/auth-guidance.ts\";\nimport type { ModelRuntime } from \"../core/model-runtime.ts\";\n\n/**\n * Format a number as human-readable (e.g., 200000 -> \"200K\", 1000000 -> \"1M\")\n */\nfunction formatTokenCount(count: number): string {\n\tif (count >= 1_000_000) {\n\t\tconst millions = count / 1_000_000;\n\t\treturn millions % 1 === 0 ? `${millions}M` : `${millions.toFixed(1)}M`;\n\t}\n\tif (count >= 1_000) {\n\t\tconst thousands = count / 1_000;\n\t\treturn thousands % 1 === 0 ? `${thousands}K` : `${thousands.toFixed(1)}K`;\n\t}\n\treturn count.toString();\n}\n\n/**\n * List available models, optionally filtered by search pattern\n */\nexport async function listModels(modelRuntime: ModelRuntime, searchPattern?: string): Promise<void> {\n\tawait modelRuntime.refreshIfStale();\n\tconst loadError = modelRuntime.getError();\n\tif (loadError) {\n\t\tconsole.error(chalk.yellow(`Warning: errors loading models.json:\\n${loadError}`));\n\t}\n\n\tconst models = [...(await modelRuntime.getAvailable())];\n\n\tif (models.length === 0) {\n\t\tconsole.log(formatNoModelsAvailableMessage());\n\t\treturn;\n\t}\n\n\t// Apply fuzzy filter if search pattern provided\n\tlet filteredModels: Model<Api>[] = models;\n\tif (searchPattern) {\n\t\tfilteredModels = fuzzyFilter(models, searchPattern, (m) => `${m.provider} ${m.id}`);\n\t}\n\n\tif (filteredModels.length === 0) {\n\t\tconsole.log(`No models matching \"${searchPattern}\"`);\n\t\treturn;\n\t}\n\n\t// Sort by provider, then by model id\n\tfilteredModels.sort((a, b) => {\n\t\tconst providerCmp = a.provider.localeCompare(b.provider);\n\t\tif (providerCmp !== 0) return providerCmp;\n\t\treturn a.id.localeCompare(b.id);\n\t});\n\n\t// Calculate column widths\n\tconst rows = filteredModels.map((m) => ({\n\t\tprovider: m.provider,\n\t\tmodel: m.id,\n\t\tcontext: formatTokenCount(m.contextWindow),\n\t\tmaxOut: formatTokenCount(m.maxTokens),\n\t\tthinking: m.reasoning ? \"yes\" : \"no\",\n\t\timages: m.input.includes(\"image\") ? \"yes\" : \"no\",\n\t}));\n\n\tconst headers = {\n\t\tprovider: \"provider\",\n\t\tmodel: \"model\",\n\t\tcontext: \"context\",\n\t\tmaxOut: \"max-out\",\n\t\tthinking: \"thinking\",\n\t\timages: \"images\",\n\t};\n\n\tconst widths = {\n\t\tprovider: Math.max(headers.provider.length, ...rows.map((r) => r.provider.length)),\n\t\tmodel: Math.max(headers.model.length, ...rows.map((r) => r.model.length)),\n\t\tcontext: Math.max(headers.context.length, ...rows.map((r) => r.context.length)),\n\t\tmaxOut: Math.max(headers.maxOut.length, ...rows.map((r) => r.maxOut.length)),\n\t\tthinking: Math.max(headers.thinking.length, ...rows.map((r) => r.thinking.length)),\n\t\timages: Math.max(headers.images.length, ...rows.map((r) => r.images.length)),\n\t};\n\n\t// Print header\n\tconst headerLine = [\n\t\theaders.provider.padEnd(widths.provider),\n\t\theaders.model.padEnd(widths.model),\n\t\theaders.context.padEnd(widths.context),\n\t\theaders.maxOut.padEnd(widths.maxOut),\n\t\theaders.thinking.padEnd(widths.thinking),\n\t\theaders.images.padEnd(widths.images),\n\t].join(\" \");\n\tconsole.log(headerLine);\n\n\t// Print rows\n\tfor (const row of rows) {\n\t\tconst line = [\n\t\t\trow.provider.padEnd(widths.provider),\n\t\t\trow.model.padEnd(widths.model),\n\t\t\trow.context.padEnd(widths.context),\n\t\t\trow.maxOut.padEnd(widths.maxOut),\n\t\t\trow.thinking.padEnd(widths.thinking),\n\t\t\trow.images.padEnd(widths.images),\n\t\t].join(\" \");\n\t\tconsole.log(line);\n\t}\n}\n"]}
@@ -22,6 +22,7 @@ function formatTokenCount(count) {
22
22
  * List available models, optionally filtered by search pattern
23
23
  */
24
24
  export async function listModels(modelRuntime, searchPattern) {
25
+ await modelRuntime.refreshIfStale();
25
26
  const loadError = modelRuntime.getError();
26
27
  if (loadError) {
27
28
  console.error(chalk.yellow(`Warning: errors loading models.json:\n${loadError}`));
@@ -1 +1 @@
1
- {"version":3,"file":"list-models.js","sourceRoot":"","sources":["../../src/cli/list-models.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * List available models with optional fuzzy search\n */\n\nimport type { Api, Model } from \"@ashx-j/lunr-ai\";\nimport { fuzzyFilter } from \"@ashx-j/lunr-tui\";\nimport chalk from \"chalk\";\nimport { formatNoModelsAvailableMessage } from \"../core/auth-guidance.ts\";\nimport type { ModelRuntime } from \"../core/model-runtime.ts\";\n\n/**\n * Format a number as human-readable (e.g., 200000 -> \"200K\", 1000000 -> \"1M\")\n */\nfunction formatTokenCount(count: number): string {\n\tif (count >= 1_000_000) {\n\t\tconst millions = count / 1_000_000;\n\t\treturn millions % 1 === 0 ? `${millions}M` : `${millions.toFixed(1)}M`;\n\t}\n\tif (count >= 1_000) {\n\t\tconst thousands = count / 1_000;\n\t\treturn thousands % 1 === 0 ? `${thousands}K` : `${thousands.toFixed(1)}K`;\n\t}\n\treturn count.toString();\n}\n\n/**\n * List available models, optionally filtered by search pattern\n */\nexport async function listModels(modelRuntime: ModelRuntime, searchPattern?: string): Promise<void> {\n\tconst loadError = modelRuntime.getError();\n\tif (loadError) {\n\t\tconsole.error(chalk.yellow(`Warning: errors loading models.json:\\n${loadError}`));\n\t}\n\n\tconst models = [...(await modelRuntime.getAvailable())];\n\n\tif (models.length === 0) {\n\t\tconsole.log(formatNoModelsAvailableMessage());\n\t\treturn;\n\t}\n\n\t// Apply fuzzy filter if search pattern provided\n\tlet filteredModels: Model<Api>[] = models;\n\tif (searchPattern) {\n\t\tfilteredModels = fuzzyFilter(models, searchPattern, (m) => `${m.provider} ${m.id}`);\n\t}\n\n\tif (filteredModels.length === 0) {\n\t\tconsole.log(`No models matching \"${searchPattern}\"`);\n\t\treturn;\n\t}\n\n\t// Sort by provider, then by model id\n\tfilteredModels.sort((a, b) => {\n\t\tconst providerCmp = a.provider.localeCompare(b.provider);\n\t\tif (providerCmp !== 0) return providerCmp;\n\t\treturn a.id.localeCompare(b.id);\n\t});\n\n\t// Calculate column widths\n\tconst rows = filteredModels.map((m) => ({\n\t\tprovider: m.provider,\n\t\tmodel: m.id,\n\t\tcontext: formatTokenCount(m.contextWindow),\n\t\tmaxOut: formatTokenCount(m.maxTokens),\n\t\tthinking: m.reasoning ? \"yes\" : \"no\",\n\t\timages: m.input.includes(\"image\") ? \"yes\" : \"no\",\n\t}));\n\n\tconst headers = {\n\t\tprovider: \"provider\",\n\t\tmodel: \"model\",\n\t\tcontext: \"context\",\n\t\tmaxOut: \"max-out\",\n\t\tthinking: \"thinking\",\n\t\timages: \"images\",\n\t};\n\n\tconst widths = {\n\t\tprovider: Math.max(headers.provider.length, ...rows.map((r) => r.provider.length)),\n\t\tmodel: Math.max(headers.model.length, ...rows.map((r) => r.model.length)),\n\t\tcontext: Math.max(headers.context.length, ...rows.map((r) => r.context.length)),\n\t\tmaxOut: Math.max(headers.maxOut.length, ...rows.map((r) => r.maxOut.length)),\n\t\tthinking: Math.max(headers.thinking.length, ...rows.map((r) => r.thinking.length)),\n\t\timages: Math.max(headers.images.length, ...rows.map((r) => r.images.length)),\n\t};\n\n\t// Print header\n\tconst headerLine = [\n\t\theaders.provider.padEnd(widths.provider),\n\t\theaders.model.padEnd(widths.model),\n\t\theaders.context.padEnd(widths.context),\n\t\theaders.maxOut.padEnd(widths.maxOut),\n\t\theaders.thinking.padEnd(widths.thinking),\n\t\theaders.images.padEnd(widths.images),\n\t].join(\" \");\n\tconsole.log(headerLine);\n\n\t// Print rows\n\tfor (const row of rows) {\n\t\tconst line = [\n\t\t\trow.provider.padEnd(widths.provider),\n\t\t\trow.model.padEnd(widths.model),\n\t\t\trow.context.padEnd(widths.context),\n\t\t\trow.maxOut.padEnd(widths.maxOut),\n\t\t\trow.thinking.padEnd(widths.thinking),\n\t\t\trow.images.padEnd(widths.images),\n\t\t].join(\" \");\n\t\tconsole.log(line);\n\t}\n}\n"]}
1
+ {"version":3,"file":"list-models.js","sourceRoot":"","sources":["../../src/cli/list-models.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * List available models with optional fuzzy search\n */\n\nimport type { Api, Model } from \"@ashx-j/lunr-ai\";\nimport { fuzzyFilter } from \"@ashx-j/lunr-tui\";\nimport chalk from \"chalk\";\nimport { formatNoModelsAvailableMessage } from \"../core/auth-guidance.ts\";\nimport type { ModelRuntime } from \"../core/model-runtime.ts\";\n\n/**\n * Format a number as human-readable (e.g., 200000 -> \"200K\", 1000000 -> \"1M\")\n */\nfunction formatTokenCount(count: number): string {\n\tif (count >= 1_000_000) {\n\t\tconst millions = count / 1_000_000;\n\t\treturn millions % 1 === 0 ? `${millions}M` : `${millions.toFixed(1)}M`;\n\t}\n\tif (count >= 1_000) {\n\t\tconst thousands = count / 1_000;\n\t\treturn thousands % 1 === 0 ? `${thousands}K` : `${thousands.toFixed(1)}K`;\n\t}\n\treturn count.toString();\n}\n\n/**\n * List available models, optionally filtered by search pattern\n */\nexport async function listModels(modelRuntime: ModelRuntime, searchPattern?: string): Promise<void> {\n\tawait modelRuntime.refreshIfStale();\n\tconst loadError = modelRuntime.getError();\n\tif (loadError) {\n\t\tconsole.error(chalk.yellow(`Warning: errors loading models.json:\\n${loadError}`));\n\t}\n\n\tconst models = [...(await modelRuntime.getAvailable())];\n\n\tif (models.length === 0) {\n\t\tconsole.log(formatNoModelsAvailableMessage());\n\t\treturn;\n\t}\n\n\t// Apply fuzzy filter if search pattern provided\n\tlet filteredModels: Model<Api>[] = models;\n\tif (searchPattern) {\n\t\tfilteredModels = fuzzyFilter(models, searchPattern, (m) => `${m.provider} ${m.id}`);\n\t}\n\n\tif (filteredModels.length === 0) {\n\t\tconsole.log(`No models matching \"${searchPattern}\"`);\n\t\treturn;\n\t}\n\n\t// Sort by provider, then by model id\n\tfilteredModels.sort((a, b) => {\n\t\tconst providerCmp = a.provider.localeCompare(b.provider);\n\t\tif (providerCmp !== 0) return providerCmp;\n\t\treturn a.id.localeCompare(b.id);\n\t});\n\n\t// Calculate column widths\n\tconst rows = filteredModels.map((m) => ({\n\t\tprovider: m.provider,\n\t\tmodel: m.id,\n\t\tcontext: formatTokenCount(m.contextWindow),\n\t\tmaxOut: formatTokenCount(m.maxTokens),\n\t\tthinking: m.reasoning ? \"yes\" : \"no\",\n\t\timages: m.input.includes(\"image\") ? \"yes\" : \"no\",\n\t}));\n\n\tconst headers = {\n\t\tprovider: \"provider\",\n\t\tmodel: \"model\",\n\t\tcontext: \"context\",\n\t\tmaxOut: \"max-out\",\n\t\tthinking: \"thinking\",\n\t\timages: \"images\",\n\t};\n\n\tconst widths = {\n\t\tprovider: Math.max(headers.provider.length, ...rows.map((r) => r.provider.length)),\n\t\tmodel: Math.max(headers.model.length, ...rows.map((r) => r.model.length)),\n\t\tcontext: Math.max(headers.context.length, ...rows.map((r) => r.context.length)),\n\t\tmaxOut: Math.max(headers.maxOut.length, ...rows.map((r) => r.maxOut.length)),\n\t\tthinking: Math.max(headers.thinking.length, ...rows.map((r) => r.thinking.length)),\n\t\timages: Math.max(headers.images.length, ...rows.map((r) => r.images.length)),\n\t};\n\n\t// Print header\n\tconst headerLine = [\n\t\theaders.provider.padEnd(widths.provider),\n\t\theaders.model.padEnd(widths.model),\n\t\theaders.context.padEnd(widths.context),\n\t\theaders.maxOut.padEnd(widths.maxOut),\n\t\theaders.thinking.padEnd(widths.thinking),\n\t\theaders.images.padEnd(widths.images),\n\t].join(\" \");\n\tconsole.log(headerLine);\n\n\t// Print rows\n\tfor (const row of rows) {\n\t\tconst line = [\n\t\t\trow.provider.padEnd(widths.provider),\n\t\t\trow.model.padEnd(widths.model),\n\t\t\trow.context.padEnd(widths.context),\n\t\t\trow.maxOut.padEnd(widths.maxOut),\n\t\t\trow.thinking.padEnd(widths.thinking),\n\t\t\trow.images.padEnd(widths.images),\n\t\t].join(\" \");\n\t\tconsole.log(line);\n\t}\n}\n"]}
package/dist/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"","sourcesContent":["#!/usr/bin/env node\n/**\n * CLI entry point for the refactored coding agent.\n * Uses main.ts with AgentSession and new mode modules.\n *\n * Test with: npx tsx src/cli-new.ts [args...]\n */\nimport { enableCompileCache } from \"node:module\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\n// lunr: set the process / tab title before the slow dynamic import of main.ts\n// so Windows Terminal does not sit on \"node\" during cold start.\nprocess.title = \"lunr\";\nif (process.stdout.isTTY) {\n\tprocess.stdout.write(\"\\x1b]0;lunr\\x07\");\n}\n\n// Enable before importing the rest of the graph so subsequent processes can\n// reuse V8 code cache. Helps the first start after a reboot when the OS page\n// cache is cold. Static imports are hoisted, so main is loaded dynamically.\ntry {\n\tconst agentDir = process.env.PI_CODING_AGENT_DIR?.trim() || join(homedir(), \".lunr\", \"agent\");\n\tenableCompileCache(join(agentDir, \"compile-cache\"));\n} catch {\n\t// Node < 22.8 or unwritable cache dir.\n}\n\nconst importStarted = Date.now();\nconst [{ APP_NAME }, { configureHttpDispatcher }, { main }, { noteImportMain }] = await Promise.all([\n\timport(\"./config.ts\"),\n\timport(\"./core/http-dispatcher.ts\"),\n\timport(\"./main.ts\"),\n\timport(\"./core/timings.ts\"),\n]);\nnoteImportMain(Date.now() - importStarted);\n\nprocess.title = APP_NAME;\nprocess.env.PI_CODING_AGENT = \"true\";\nprocess.emitWarning = (() => {}) as typeof process.emitWarning;\n\n// Configure undici's global dispatcher before provider SDKs issue requests.\n// Runtime settings are applied once SettingsManager has loaded global/project settings.\nconfigureHttpDispatcher();\n\nawait main(process.argv.slice(2));\n"]}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"","sourcesContent":["#!/usr/bin/env node\nimport { enableCompileCache } from \"node:module\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { InteractiveView } from \"./startup/interactive-view.ts\";\nimport { resolvePreloadLaunchMode } from \"./startup/launch-routing.ts\";\nimport { markStartupMilestone } from \"./startup/startup-milestones.ts\";\n\nmarkStartupMilestone(\"process_entry\");\nprocess.title = \"lunr\";\nif (process.stdout.isTTY) {\n\tprocess.stdout.write(\"\\x1b]0;lunr\\x07\");\n}\n\ntry {\n\tconst agentDir = process.env.PI_CODING_AGENT_DIR?.trim() || join(homedir(), \".lunr\", \"agent\");\n\tenableCompileCache(join(agentDir, \"compile-cache\"));\n} catch {}\n\nprocess.env.PI_CODING_AGENT = \"true\";\nprocess.emitWarning = (() => {}) as typeof process.emitWarning;\n\nconst args = process.argv.slice(2);\nconst startupBenchmark = process.env.PI_STARTUP_BENCHMARK === \"1\";\nconst preloadMode = resolvePreloadLaunchMode(args, {\n\tstdinIsTTY: process.stdin.isTTY === true,\n\tstdoutIsTTY: process.stdout.isTTY === true,\n\tstartupBenchmark,\n});\nmarkStartupMilestone(\"mode_routed\");\n\nlet startupView: InteractiveView | undefined;\nif (preloadMode === \"interactive\") {\n\tconst { InteractiveView } = await import(\"./startup/interactive-view.ts\");\n\tstartupView = new InteractiveView();\n\tstartupView.start();\n\tawait startupView.waitForFirstFrame();\n\tif (startupView.isExitRequested) process.exit(0);\n}\n\nconst startRuntime = async () => {\n\tconst importStarted = performance.now();\n\ttry {\n\t\tconst [{ APP_NAME }, { main }, { noteImportMain }] = await Promise.all([\n\t\t\timport(\"./config.ts\"),\n\t\t\timport(\"./main.ts\"),\n\t\t\timport(\"./core/timings.ts\"),\n\t\t]);\n\t\tnoteImportMain(performance.now() - importStarted);\n\t\tprocess.title = APP_NAME;\n\t\tawait main(args, { startupView });\n\t} catch (error) {\n\t\tif (startupView && !startupView.isExitRequested) {\n\t\t\tprocess.exitCode = 1;\n\t\t\tawait startupView.fail(error);\n\t\t} else {\n\t\t\tthrow error;\n\t\t}\n\t}\n};\nprocess.once(\"exit\", () => startupView?.stop());\nif (startupView) {\n\tawait Promise.race([startRuntime(), startupView.waitForExit()]);\n\tif (startupView.isExitRequested) process.exit(process.exitCode ?? 0);\n} else {\n\tawait startRuntime();\n}\n"]}
package/dist/cli.js CHANGED
@@ -1,42 +1,67 @@
1
1
  #!/usr/bin/env node
2
- /**
3
- * CLI entry point for the refactored coding agent.
4
- * Uses main.ts with AgentSession and new mode modules.
5
- *
6
- * Test with: npx tsx src/cli-new.ts [args...]
7
- */
8
2
  import { enableCompileCache } from "node:module";
9
3
  import { homedir } from "node:os";
10
4
  import { join } from "node:path";
11
- // lunr: set the process / tab title before the slow dynamic import of main.ts
12
- // so Windows Terminal does not sit on "node" during cold start.
5
+ import { resolvePreloadLaunchMode } from "./startup/launch-routing.js";
6
+ import { markStartupMilestone } from "./startup/startup-milestones.js";
7
+ markStartupMilestone("process_entry");
13
8
  process.title = "lunr";
14
9
  if (process.stdout.isTTY) {
15
10
  process.stdout.write("\x1b]0;lunr\x07");
16
11
  }
17
- // Enable before importing the rest of the graph so subsequent processes can
18
- // reuse V8 code cache. Helps the first start after a reboot when the OS page
19
- // cache is cold. Static imports are hoisted, so main is loaded dynamically.
20
12
  try {
21
13
  const agentDir = process.env.PI_CODING_AGENT_DIR?.trim() || join(homedir(), ".lunr", "agent");
22
14
  enableCompileCache(join(agentDir, "compile-cache"));
23
15
  }
24
- catch {
25
- // Node < 22.8 or unwritable cache dir.
26
- }
27
- const importStarted = Date.now();
28
- const [{ APP_NAME }, { configureHttpDispatcher }, { main }, { noteImportMain }] = await Promise.all([
29
- import("./config.js"),
30
- import("./core/http-dispatcher.js"),
31
- import("./main.js"),
32
- import("./core/timings.js"),
33
- ]);
34
- noteImportMain(Date.now() - importStarted);
35
- process.title = APP_NAME;
16
+ catch { }
36
17
  process.env.PI_CODING_AGENT = "true";
37
18
  process.emitWarning = (() => { });
38
- // Configure undici's global dispatcher before provider SDKs issue requests.
39
- // Runtime settings are applied once SettingsManager has loaded global/project settings.
40
- configureHttpDispatcher();
41
- await main(process.argv.slice(2));
19
+ const args = process.argv.slice(2);
20
+ const startupBenchmark = process.env.PI_STARTUP_BENCHMARK === "1";
21
+ const preloadMode = resolvePreloadLaunchMode(args, {
22
+ stdinIsTTY: process.stdin.isTTY === true,
23
+ stdoutIsTTY: process.stdout.isTTY === true,
24
+ startupBenchmark,
25
+ });
26
+ markStartupMilestone("mode_routed");
27
+ let startupView;
28
+ if (preloadMode === "interactive") {
29
+ const { InteractiveView } = await import("./startup/interactive-view.js");
30
+ startupView = new InteractiveView();
31
+ startupView.start();
32
+ await startupView.waitForFirstFrame();
33
+ if (startupView.isExitRequested)
34
+ process.exit(0);
35
+ }
36
+ const startRuntime = async () => {
37
+ const importStarted = performance.now();
38
+ try {
39
+ const [{ APP_NAME }, { main }, { noteImportMain }] = await Promise.all([
40
+ import("./config.js"),
41
+ import("./main.js"),
42
+ import("./core/timings.js"),
43
+ ]);
44
+ noteImportMain(performance.now() - importStarted);
45
+ process.title = APP_NAME;
46
+ await main(args, { startupView });
47
+ }
48
+ catch (error) {
49
+ if (startupView && !startupView.isExitRequested) {
50
+ process.exitCode = 1;
51
+ await startupView.fail(error);
52
+ }
53
+ else {
54
+ throw error;
55
+ }
56
+ }
57
+ };
58
+ process.once("exit", () => startupView?.stop());
59
+ if (startupView) {
60
+ await Promise.race([startRuntime(), startupView.waitForExit()]);
61
+ if (startupView.isExitRequested)
62
+ process.exit(process.exitCode ?? 0);
63
+ }
64
+ else {
65
+ await startRuntime();
66
+ }
42
67
  //# sourceMappingURL=cli.js.map
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;GAKG;AACH,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,8EAA8E;AAC9E,gEAAgE;AAChE,OAAO,CAAC,KAAK,GAAG,MAAM,CAAC;AACvB,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;IAC1B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;AACzC,CAAC;AAED,4EAA4E;AAC5E,6EAA6E;AAC7E,4EAA4E;AAC5E,IAAI,CAAC;IACJ,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,EAAE,IAAI,EAAE,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAC9F,kBAAkB,CAAC,IAAI,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAC,CAAC;AACrD,CAAC;AAAC,MAAM,CAAC;IACR,uCAAuC;AACxC,CAAC;AAED,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;AACjC,MAAM,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,uBAAuB,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,cAAc,EAAE,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;IACnG,MAAM,CAAC,aAAa,CAAC;IACrB,MAAM,CAAC,2BAA2B,CAAC;IACnC,MAAM,CAAC,WAAW,CAAC;IACnB,MAAM,CAAC,mBAAmB,CAAC;CAC3B,CAAC,CAAC;AACH,cAAc,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,aAAa,CAAC,CAAC;AAE3C,OAAO,CAAC,KAAK,GAAG,QAAQ,CAAC;AACzB,OAAO,CAAC,GAAG,CAAC,eAAe,GAAG,MAAM,CAAC;AACrC,OAAO,CAAC,WAAW,GAAG,CAAC,GAAG,EAAE,CAAC,EAAC,CAAC,CAA+B,CAAC;AAE/D,4EAA4E;AAC5E,wFAAwF;AACxF,uBAAuB,EAAE,CAAC;AAE1B,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC","sourcesContent":["#!/usr/bin/env node\n/**\n * CLI entry point for the refactored coding agent.\n * Uses main.ts with AgentSession and new mode modules.\n *\n * Test with: npx tsx src/cli-new.ts [args...]\n */\nimport { enableCompileCache } from \"node:module\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\n// lunr: set the process / tab title before the slow dynamic import of main.ts\n// so Windows Terminal does not sit on \"node\" during cold start.\nprocess.title = \"lunr\";\nif (process.stdout.isTTY) {\n\tprocess.stdout.write(\"\\x1b]0;lunr\\x07\");\n}\n\n// Enable before importing the rest of the graph so subsequent processes can\n// reuse V8 code cache. Helps the first start after a reboot when the OS page\n// cache is cold. Static imports are hoisted, so main is loaded dynamically.\ntry {\n\tconst agentDir = process.env.PI_CODING_AGENT_DIR?.trim() || join(homedir(), \".lunr\", \"agent\");\n\tenableCompileCache(join(agentDir, \"compile-cache\"));\n} catch {\n\t// Node < 22.8 or unwritable cache dir.\n}\n\nconst importStarted = Date.now();\nconst [{ APP_NAME }, { configureHttpDispatcher }, { main }, { noteImportMain }] = await Promise.all([\n\timport(\"./config.ts\"),\n\timport(\"./core/http-dispatcher.ts\"),\n\timport(\"./main.ts\"),\n\timport(\"./core/timings.ts\"),\n]);\nnoteImportMain(Date.now() - importStarted);\n\nprocess.title = APP_NAME;\nprocess.env.PI_CODING_AGENT = \"true\";\nprocess.emitWarning = (() => {}) as typeof process.emitWarning;\n\n// Configure undici's global dispatcher before provider SDKs issue requests.\n// Runtime settings are applied once SettingsManager has loaded global/project settings.\nconfigureHttpDispatcher();\n\nawait main(process.argv.slice(2));\n"]}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\nimport { enableCompileCache } from \"node:module\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { InteractiveView } from \"./startup/interactive-view.ts\";\nimport { resolvePreloadLaunchMode } from \"./startup/launch-routing.ts\";\nimport { markStartupMilestone } from \"./startup/startup-milestones.ts\";\n\nmarkStartupMilestone(\"process_entry\");\nprocess.title = \"lunr\";\nif (process.stdout.isTTY) {\n\tprocess.stdout.write(\"\\x1b]0;lunr\\x07\");\n}\n\ntry {\n\tconst agentDir = process.env.PI_CODING_AGENT_DIR?.trim() || join(homedir(), \".lunr\", \"agent\");\n\tenableCompileCache(join(agentDir, \"compile-cache\"));\n} catch {}\n\nprocess.env.PI_CODING_AGENT = \"true\";\nprocess.emitWarning = (() => {}) as typeof process.emitWarning;\n\nconst args = process.argv.slice(2);\nconst startupBenchmark = process.env.PI_STARTUP_BENCHMARK === \"1\";\nconst preloadMode = resolvePreloadLaunchMode(args, {\n\tstdinIsTTY: process.stdin.isTTY === true,\n\tstdoutIsTTY: process.stdout.isTTY === true,\n\tstartupBenchmark,\n});\nmarkStartupMilestone(\"mode_routed\");\n\nlet startupView: InteractiveView | undefined;\nif (preloadMode === \"interactive\") {\n\tconst { InteractiveView } = await import(\"./startup/interactive-view.ts\");\n\tstartupView = new InteractiveView();\n\tstartupView.start();\n\tawait startupView.waitForFirstFrame();\n\tif (startupView.isExitRequested) process.exit(0);\n}\n\nconst startRuntime = async () => {\n\tconst importStarted = performance.now();\n\ttry {\n\t\tconst [{ APP_NAME }, { main }, { noteImportMain }] = await Promise.all([\n\t\t\timport(\"./config.ts\"),\n\t\t\timport(\"./main.ts\"),\n\t\t\timport(\"./core/timings.ts\"),\n\t\t]);\n\t\tnoteImportMain(performance.now() - importStarted);\n\t\tprocess.title = APP_NAME;\n\t\tawait main(args, { startupView });\n\t} catch (error) {\n\t\tif (startupView && !startupView.isExitRequested) {\n\t\t\tprocess.exitCode = 1;\n\t\t\tawait startupView.fail(error);\n\t\t} else {\n\t\t\tthrow error;\n\t\t}\n\t}\n};\nprocess.once(\"exit\", () => startupView?.stop());\nif (startupView) {\n\tawait Promise.race([startRuntime(), startupView.waitForExit()]);\n\tif (startupView.isExitRequested) process.exit(process.exitCode ?? 0);\n} else {\n\tawait startRuntime();\n}\n"]}
@@ -0,0 +1,3 @@
1
+ import type { Credential } from "@ashx-j/lunr-ai";
2
+ export declare function catalogCacheScope(provider: string, baseUrl: string, credential?: Credential): string;
3
+ //# sourceMappingURL=catalog-cache-scope.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog-cache-scope.d.ts","sourceRoot":"","sources":["../../src/core/catalog-cache-scope.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAExD,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,UAAU,GAAG,MAAM,CAUpG","sourcesContent":["import { createHash } from \"node:crypto\";\nimport type { Credential } from \"@ashx-j/lunr-ai\";\n\nexport function catalogCacheScope(provider: string, baseUrl: string, credential?: Credential): string {\n\tconst identity =\n\t\tcredential?.type === \"oauth\"\n\t\t\t? typeof credential.accountId === \"string\"\n\t\t\t\t? credential.accountId\n\t\t\t\t: credential.refresh || credential.access\n\t\t\t: credential?.key;\n\treturn createHash(\"sha256\")\n\t\t.update(JSON.stringify([provider, baseUrl.replace(/\\/+$/, \"\"), identity ?? null]))\n\t\t.digest(\"hex\");\n}\n"]}
@@ -0,0 +1,12 @@
1
+ import { createHash } from "node:crypto";
2
+ export function catalogCacheScope(provider, baseUrl, credential) {
3
+ const identity = credential?.type === "oauth"
4
+ ? typeof credential.accountId === "string"
5
+ ? credential.accountId
6
+ : credential.refresh || credential.access
7
+ : credential?.key;
8
+ return createHash("sha256")
9
+ .update(JSON.stringify([provider, baseUrl.replace(/\/+$/, ""), identity ?? null]))
10
+ .digest("hex");
11
+ }
12
+ //# sourceMappingURL=catalog-cache-scope.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog-cache-scope.js","sourceRoot":"","sources":["../../src/core/catalog-cache-scope.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGzC,MAAM,UAAU,iBAAiB,CAAC,QAAgB,EAAE,OAAe,EAAE,UAAuB,EAAU;IACrG,MAAM,QAAQ,GACb,UAAU,EAAE,IAAI,KAAK,OAAO;QAC3B,CAAC,CAAC,OAAO,UAAU,CAAC,SAAS,KAAK,QAAQ;YACzC,CAAC,CAAC,UAAU,CAAC,SAAS;YACtB,CAAC,CAAC,UAAU,CAAC,OAAO,IAAI,UAAU,CAAC,MAAM;QAC1C,CAAC,CAAC,UAAU,EAAE,GAAG,CAAC;IACpB,OAAO,UAAU,CAAC,QAAQ,CAAC;SACzB,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,QAAQ,EAAE,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,QAAQ,IAAI,IAAI,CAAC,CAAC,CAAC;SACjF,MAAM,CAAC,KAAK,CAAC,CAAC;AAAA,CAChB","sourcesContent":["import { createHash } from \"node:crypto\";\nimport type { Credential } from \"@ashx-j/lunr-ai\";\n\nexport function catalogCacheScope(provider: string, baseUrl: string, credential?: Credential): string {\n\tconst identity =\n\t\tcredential?.type === \"oauth\"\n\t\t\t? typeof credential.accountId === \"string\"\n\t\t\t\t? credential.accountId\n\t\t\t\t: credential.refresh || credential.access\n\t\t\t: credential?.key;\n\treturn createHash(\"sha256\")\n\t\t.update(JSON.stringify([provider, baseUrl.replace(/\\/+$/, \"\"), identity ?? null]))\n\t\t.digest(\"hex\");\n}\n"]}
@@ -17,6 +17,8 @@ export declare class CatalogOverlaySource {
17
17
  officialFor(providerId: string): Model<Api>[];
18
18
  userFor(providerId: string): Model<Api>[];
19
19
  liveFor(providerId: string): Model<Api>[];
20
+ /** Codex's complete account catalog is authoritative for picker availability only. */
21
+ isAvailable(model: Model<Api>): boolean;
20
22
  }
21
23
  export declare function withCatalogOverlay<T extends {
22
24
  id: string;
@@ -1 +1 @@
1
- {"version":3,"file":"catalog-merge.d.ts","sourceRoot":"","sources":["../../src/core/catalog-merge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,GAAG,EAAE,KAAK,KAAK,EAAyB,MAAM,uBAAuB,CAAC;AACpF,OAAO,EAAY,KAAK,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAE7E,MAAM,MAAM,4BAA4B,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,QAAQ,CAAC;AAE7F,wBAAgB,kBAAkB,CAAC,IAAI,EAAE;IACxC,OAAO,EAAE,SAAS,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;IAC/B,IAAI,CAAC,EAAE,SAAS,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;IAC7B,IAAI,CAAC,EAAE,SAAS,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;IAC7B,QAAQ,CAAC,EAAE,SAAS,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;CACjC,GAAG,KAAK,CAAC,GAAG,CAAC,EAAE,CAuBf;AAED,qBAAa,oBAAoB;IAChC,OAAO,CAAC,QAAQ,CAAmC;IACnD,OAAO,CAAC,IAAI,CAAmC;IAC/C,OAAO,CAAC,IAAI,CAAmC;IAE/C,WAAW,CAAC,MAAM,EAAE,SAAS,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,IAAI,CAE/C;IAED,OAAO,CAAC,MAAM,EAAE,SAAS,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,IAAI,CAE3C;IAED,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,IAAI,CAE/D;IAED,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,EAAE,CAE5C;IAED,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,EAAE,CAExC;IAED,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,EAAE,CAExC;CACD;AAYD,wBAAgB,kBAAkB,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,SAAS,KAAK,CAAC,GAAG,CAAC,EAAE,CAAA;CAAE,EAClG,QAAQ,EAAE,CAAC,EACX,OAAO,EAAE,oBAAoB,GAC3B,CAAC,CAYH;AAED,MAAM,WAAW,6BAA6B;IAC7C,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,4BAA4B,CAAC;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,0BAA0B;IAC1C,QAAQ,CAAC,EAAE;QAAE,MAAM,EAAE,qBAAqB,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1F,SAAS,EAAE,SAAS,6BAA6B,EAAE,CAAC;IACpD,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,yFAAyF;AACzF,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,0BAA0B,GAAG,MAAM,CA2CrF;AAcD,wBAAgB,cAAc,CAC7B,OAAO,EAAE,SAAS,KAAK,CAAC,GAAG,CAAC,EAAE,EAC9B,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,EAC1B,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,GACpB,GAAG,CAAC,MAAM,CAAC,CAKb","sourcesContent":["import { type Api, type Model, withXaiEffortMetadata } from \"@ashx-j/lunr-ai\";\nimport { modelKey, type OfficialCatalogSource } from \"./official-catalog.ts\";\n\nexport type CatalogProviderRefreshStatus = \"ok\" | \"timeout\" | \"error\" | \"skipped\" | \"static\";\n\nexport function mergeCatalogLayers(args: {\n\tbakedIn: readonly Model<Api>[];\n\tlive?: readonly Model<Api>[];\n\tuser?: readonly Model<Api>[];\n\tofficial?: readonly Model<Api>[];\n}): Model<Api>[] {\n\tconst byId = new Map<string, Model<Api>>();\n\tfor (const model of args.bakedIn) byId.set(model.id, model);\n\tfor (const model of args.live ?? []) byId.set(model.id, model);\n\tfor (const model of args.user ?? []) byId.set(model.id, model);\n\tfor (const model of args.official ?? []) byId.set(model.id, model);\n\n\tconst seen = new Set<string>();\n\tconst result: Model<Api>[] = [];\n\tfor (const baked of args.bakedIn) {\n\t\tconst merged = byId.get(baked.id);\n\t\tif (!merged) continue;\n\t\tresult.push(merged);\n\t\tseen.add(baked.id);\n\t}\n\tfor (const model of [...(args.live ?? []), ...(args.user ?? []), ...(args.official ?? [])]) {\n\t\tif (seen.has(model.id)) continue;\n\t\tconst winner = byId.get(model.id);\n\t\tif (!winner) continue;\n\t\tresult.push(winner);\n\t\tseen.add(model.id);\n\t}\n\treturn result.map((model) => withXaiEffortMetadata(model));\n}\n\nexport class CatalogOverlaySource {\n\tprivate official = new Map<string, Model<Api>[]>();\n\tprivate user = new Map<string, Model<Api>[]>();\n\tprivate live = new Map<string, Model<Api>[]>();\n\n\tsetOfficial(models: readonly Model<Api>[]): void {\n\t\tthis.official = groupByProvider(models);\n\t}\n\n\tsetUser(models: readonly Model<Api>[]): void {\n\t\tthis.user = groupByProvider(models);\n\t}\n\n\tsetLive(providerId: string, models: readonly Model<Api>[]): void {\n\t\tthis.live.set(providerId, [...models]);\n\t}\n\n\tofficialFor(providerId: string): Model<Api>[] {\n\t\treturn this.official.get(providerId) ?? [];\n\t}\n\n\tuserFor(providerId: string): Model<Api>[] {\n\t\treturn this.user.get(providerId) ?? [];\n\t}\n\n\tliveFor(providerId: string): Model<Api>[] {\n\t\treturn this.live.get(providerId) ?? [];\n\t}\n}\n\nfunction groupByProvider(models: readonly Model<Api>[]): Map<string, Model<Api>[]> {\n\tconst byProvider = new Map<string, Model<Api>[]>();\n\tfor (const model of models) {\n\t\tconst list = byProvider.get(model.provider) ?? [];\n\t\tlist.push(model);\n\t\tbyProvider.set(model.provider, list);\n\t}\n\treturn byProvider;\n}\n\nexport function withCatalogOverlay<T extends { id: string; getModels: () => readonly Model<Api>[] }>(\n\tprovider: T,\n\toverlay: CatalogOverlaySource,\n): T {\n\tconst bakedIn = () => provider.getModels();\n\treturn {\n\t\t...provider,\n\t\tgetModels: () =>\n\t\t\tmergeCatalogLayers({\n\t\t\t\tbakedIn: bakedIn(),\n\t\t\t\tlive: overlay.liveFor(provider.id),\n\t\t\t\tuser: overlay.userFor(provider.id),\n\t\t\t\tofficial: overlay.officialFor(provider.id),\n\t\t\t}),\n\t};\n}\n\nexport interface CatalogRefreshProviderSummary {\n\tid: string;\n\tstatus: CatalogProviderRefreshStatus;\n\tadded?: number;\n\ttotal?: number;\n\terror?: string;\n}\n\nexport interface CatalogRefreshSummaryInput {\n\tofficial?: { source: OfficialCatalogSource; modelCount: number; evictedUserRows: number };\n\tproviders: readonly CatalogRefreshProviderSummary[];\n\tasked?: readonly string[];\n\textraDefaults?: number;\n\tollama?: string;\n}\n\n/** Build the /refresh toast. One hung provider must not become a global timeout line. */\nexport function formatCatalogRefreshSummary(input: CatalogRefreshSummaryInput): string {\n\tconst parts: string[] = [];\n\tif (input.official?.source === \"github\") {\n\t\tconst evicted =\n\t\t\tinput.official.evictedUserRows > 0 ? `; replaced ${input.official.evictedUserRows} user-filled row` : \"\";\n\t\tconst plural = input.official.evictedUserRows === 1 ? \"\" : input.official.evictedUserRows > 0 ? \"s\" : \"\";\n\t\tparts.push(`Official catalog updated (${input.official.modelCount} models)${evicted}${plural}.`);\n\t}\n\n\tconst refreshed: string[] = [];\n\tconst failed: string[] = [];\n\tfor (const provider of input.providers) {\n\t\tif (provider.status === \"ok\") {\n\t\t\tconst added = provider.added ?? 0;\n\t\t\tconst total = provider.total ?? 0;\n\t\t\trefreshed.push(added > 0 ? `${provider.id} (+${added})` : `${provider.id} (${total})`);\n\t\t} else if (provider.status === \"timeout\") {\n\t\t\tfailed.push(`${provider.id} timed out (cached)`);\n\t\t} else if (provider.status === \"error\") {\n\t\t\tfailed.push(formatLiveProviderError(provider));\n\t\t}\n\t}\n\n\tif (refreshed.length > 0) {\n\t\tparts.push(`Refreshed ${refreshed.join(\", \")}.`);\n\t} else if (input.providers.some((provider) => provider.status === \"ok\")) {\n\t\tparts.push(\"Refreshed model catalogs.\");\n\t}\n\n\tif (failed.length > 0) {\n\t\tparts.push(`${failed.join(\"; \")}.`);\n\t}\n\n\tif (input.asked && input.asked.length > 0) {\n\t\tparts.push(`Asked for missing metadata on ${input.asked.join(\", \")}.`);\n\t}\n\tif (input.extraDefaults && input.extraDefaults > 0) {\n\t\tparts.push(`+${input.extraDefaults} more using defaults.`);\n\t}\n\tif (input.ollama) parts.push(input.ollama);\n\n\tif (parts.length === 0) return \"Model catalogs refreshed.\";\n\treturn parts.join(\" \");\n}\n\nfunction formatLiveProviderError(provider: CatalogRefreshProviderSummary): string {\n\tif (\n\t\tprovider.id === \"xai\" &&\n\t\tprovider.error &&\n\t\t/invalid_grant|refresh token revoked/i.test(provider.error) &&\n\t\t!/timed out|aborted|cancelled|ECONN|ENOTFOUND|network/i.test(provider.error)\n\t) {\n\t\treturn \"xai login expired (run /login xai)\";\n\t}\n\treturn provider.error ? `${provider.id} failed (${provider.error})` : `${provider.id} failed`;\n}\n\nexport function knownModelKeys(\n\tbakedIn: readonly Model<Api>[],\n\tofficial: Iterable<string>,\n\tuser: Iterable<string>,\n): Set<string> {\n\tconst keys = new Set<string>(official);\n\tfor (const key of user) keys.add(key);\n\tfor (const model of bakedIn) keys.add(modelKey(model.provider, model.id));\n\treturn keys;\n}\n"]}
1
+ {"version":3,"file":"catalog-merge.d.ts","sourceRoot":"","sources":["../../src/core/catalog-merge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,GAAG,EAAE,KAAK,KAAK,EAAmD,MAAM,uBAAuB,CAAC;AAC9G,OAAO,EAAY,KAAK,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAE7E,MAAM,MAAM,4BAA4B,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,QAAQ,CAAC;AAE7F,wBAAgB,kBAAkB,CAAC,IAAI,EAAE;IACxC,OAAO,EAAE,SAAS,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;IAC/B,IAAI,CAAC,EAAE,SAAS,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;IAC7B,IAAI,CAAC,EAAE,SAAS,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;IAC7B,QAAQ,CAAC,EAAE,SAAS,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;CACjC,GAAG,KAAK,CAAC,GAAG,CAAC,EAAE,CAuCf;AAED,qBAAa,oBAAoB;IAChC,OAAO,CAAC,QAAQ,CAAmC;IACnD,OAAO,CAAC,IAAI,CAAmC;IAC/C,OAAO,CAAC,IAAI,CAAmC;IAE/C,WAAW,CAAC,MAAM,EAAE,SAAS,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,IAAI,CAE/C;IAED,OAAO,CAAC,MAAM,EAAE,SAAS,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,IAAI,CAE3C;IAED,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,IAAI,CAE/D;IAED,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,EAAE,CAE5C;IAED,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,EAAE,CAExC;IAED,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,EAAE,CAExC;IAED,sFAAsF;IACtF,WAAW,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,OAAO,CAQtC;CACD;AAYD,wBAAgB,kBAAkB,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,SAAS,KAAK,CAAC,GAAG,CAAC,EAAE,CAAA;CAAE,EAClG,QAAQ,EAAE,CAAC,EACX,OAAO,EAAE,oBAAoB,GAC3B,CAAC,CAYH;AAED,MAAM,WAAW,6BAA6B;IAC7C,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,4BAA4B,CAAC;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,0BAA0B;IAC1C,QAAQ,CAAC,EAAE;QAAE,MAAM,EAAE,qBAAqB,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1F,SAAS,EAAE,SAAS,6BAA6B,EAAE,CAAC;IACpD,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,yFAAyF;AACzF,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,0BAA0B,GAAG,MAAM,CA2CrF;AAcD,wBAAgB,cAAc,CAC7B,OAAO,EAAE,SAAS,KAAK,CAAC,GAAG,CAAC,EAAE,EAC9B,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,EAC1B,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,GACpB,GAAG,CAAC,MAAM,CAAC,CAKb","sourcesContent":["import { type Api, type Model, withOpenAiEffortMetadata, withXaiEffortMetadata } from \"@ashx-j/lunr-ai\";\nimport { modelKey, type OfficialCatalogSource } from \"./official-catalog.ts\";\n\nexport type CatalogProviderRefreshStatus = \"ok\" | \"timeout\" | \"error\" | \"skipped\" | \"static\";\n\nexport function mergeCatalogLayers(args: {\n\tbakedIn: readonly Model<Api>[];\n\tlive?: readonly Model<Api>[];\n\tuser?: readonly Model<Api>[];\n\tofficial?: readonly Model<Api>[];\n}): Model<Api>[] {\n\tconst byId = new Map<string, Model<Api>>();\n\tfor (const model of args.bakedIn) byId.set(model.id, model);\n\tfor (const model of args.live ?? []) byId.set(model.id, model);\n\tfor (const model of args.user ?? []) byId.set(model.id, model);\n\tfor (const model of args.official ?? []) byId.set(model.id, model);\n\n\tconst seen = new Set<string>();\n\tconst result: Model<Api>[] = [];\n\tfor (const baked of args.bakedIn) {\n\t\tconst merged = byId.get(baked.id);\n\t\tif (!merged) continue;\n\t\tresult.push(merged);\n\t\tseen.add(baked.id);\n\t}\n\tfor (const model of [...(args.live ?? []), ...(args.user ?? []), ...(args.official ?? [])]) {\n\t\tif (seen.has(model.id)) continue;\n\t\tconst winner = byId.get(model.id);\n\t\tif (!winner) continue;\n\t\tresult.push(winner);\n\t\tseen.add(model.id);\n\t}\n\tconst liveById = new Map((args.live ?? []).map((model) => [model.id, model]));\n\tconst pricedIds = new Set(\n\t\t[...args.bakedIn, ...(args.official ?? []), ...(args.user ?? [])]\n\t\t\t.filter((model) => model.catalog?.pricing !== \"unknown\")\n\t\t\t.map((model) => model.id),\n\t);\n\treturn result.map((model) => {\n\t\tlet resolved = withXaiEffortMetadata(model);\n\t\tif (!model.catalog?.supplied.includes(\"thinkingLevelMap\")) resolved = withOpenAiEffortMetadata(resolved);\n\t\tconst live = liveById.get(model.id);\n\t\tif (!live?.catalog) return resolved;\n\t\tresolved = { ...resolved, catalog: { ...live.catalog } };\n\t\t// Only supplied fields may override curated metadata. Inferred defaults never win.\n\t\tfor (const field of live.catalog.supplied) Object.assign(resolved, { [field]: live[field] });\n\t\tif (pricedIds.has(model.id) || live.catalog.supplied.includes(\"cost\")) delete resolved.catalog!.pricing;\n\t\treturn resolved;\n\t});\n}\n\nexport class CatalogOverlaySource {\n\tprivate official = new Map<string, Model<Api>[]>();\n\tprivate user = new Map<string, Model<Api>[]>();\n\tprivate live = new Map<string, Model<Api>[]>();\n\n\tsetOfficial(models: readonly Model<Api>[]): void {\n\t\tthis.official = groupByProvider(models);\n\t}\n\n\tsetUser(models: readonly Model<Api>[]): void {\n\t\tthis.user = groupByProvider(models);\n\t}\n\n\tsetLive(providerId: string, models: readonly Model<Api>[]): void {\n\t\tthis.live.set(providerId, [...models]);\n\t}\n\n\tofficialFor(providerId: string): Model<Api>[] {\n\t\treturn this.official.get(providerId) ?? [];\n\t}\n\n\tuserFor(providerId: string): Model<Api>[] {\n\t\treturn this.user.get(providerId) ?? [];\n\t}\n\n\tliveFor(providerId: string): Model<Api>[] {\n\t\treturn this.live.get(providerId) ?? [];\n\t}\n\n\t/** Codex's complete account catalog is authoritative for picker availability only. */\n\tisAvailable(model: Model<Api>): boolean {\n\t\tif (model.catalog?.hidden) return false;\n\t\tconst live = this.liveFor(model.provider);\n\t\treturn (\n\t\t\tmodel.provider !== \"openai-codex\" ||\n\t\t\t!live.length ||\n\t\t\tlive.some((row) => row.id === model.id && !row.catalog?.hidden)\n\t\t);\n\t}\n}\n\nfunction groupByProvider(models: readonly Model<Api>[]): Map<string, Model<Api>[]> {\n\tconst byProvider = new Map<string, Model<Api>[]>();\n\tfor (const model of models) {\n\t\tconst list = byProvider.get(model.provider) ?? [];\n\t\tlist.push(model);\n\t\tbyProvider.set(model.provider, list);\n\t}\n\treturn byProvider;\n}\n\nexport function withCatalogOverlay<T extends { id: string; getModels: () => readonly Model<Api>[] }>(\n\tprovider: T,\n\toverlay: CatalogOverlaySource,\n): T {\n\tconst bakedIn = () => provider.getModels();\n\treturn {\n\t\t...provider,\n\t\tgetModels: () =>\n\t\t\tmergeCatalogLayers({\n\t\t\t\tbakedIn: bakedIn(),\n\t\t\t\tlive: overlay.liveFor(provider.id),\n\t\t\t\tuser: overlay.userFor(provider.id),\n\t\t\t\tofficial: overlay.officialFor(provider.id),\n\t\t\t}),\n\t};\n}\n\nexport interface CatalogRefreshProviderSummary {\n\tid: string;\n\tstatus: CatalogProviderRefreshStatus;\n\tadded?: number;\n\ttotal?: number;\n\terror?: string;\n}\n\nexport interface CatalogRefreshSummaryInput {\n\tofficial?: { source: OfficialCatalogSource; modelCount: number; evictedUserRows: number };\n\tproviders: readonly CatalogRefreshProviderSummary[];\n\tasked?: readonly string[];\n\textraDefaults?: number;\n\tollama?: string;\n}\n\n/** Build the /refresh toast. One hung provider must not become a global timeout line. */\nexport function formatCatalogRefreshSummary(input: CatalogRefreshSummaryInput): string {\n\tconst parts: string[] = [];\n\tif (input.official?.source === \"github\") {\n\t\tconst evicted =\n\t\t\tinput.official.evictedUserRows > 0 ? `; replaced ${input.official.evictedUserRows} user-filled row` : \"\";\n\t\tconst plural = input.official.evictedUserRows === 1 ? \"\" : input.official.evictedUserRows > 0 ? \"s\" : \"\";\n\t\tparts.push(`Official catalog updated (${input.official.modelCount} models)${evicted}${plural}.`);\n\t}\n\n\tconst refreshed: string[] = [];\n\tconst failed: string[] = [];\n\tfor (const provider of input.providers) {\n\t\tif (provider.status === \"ok\") {\n\t\t\tconst added = provider.added ?? 0;\n\t\t\tconst total = provider.total ?? 0;\n\t\t\trefreshed.push(added > 0 ? `${provider.id} (+${added})` : `${provider.id} (${total})`);\n\t\t} else if (provider.status === \"timeout\") {\n\t\t\tfailed.push(`${provider.id} timed out (cached)`);\n\t\t} else if (provider.status === \"error\") {\n\t\t\tfailed.push(formatLiveProviderError(provider));\n\t\t}\n\t}\n\n\tif (refreshed.length > 0) {\n\t\tparts.push(`Refreshed ${refreshed.join(\", \")}.`);\n\t} else if (input.providers.some((provider) => provider.status === \"ok\")) {\n\t\tparts.push(\"Refreshed model catalogs.\");\n\t}\n\n\tif (failed.length > 0) {\n\t\tparts.push(`${failed.join(\"; \")}.`);\n\t}\n\n\tif (input.asked && input.asked.length > 0) {\n\t\tparts.push(`Asked for missing metadata on ${input.asked.join(\", \")}.`);\n\t}\n\tif (input.extraDefaults && input.extraDefaults > 0) {\n\t\tparts.push(`+${input.extraDefaults} more using defaults.`);\n\t}\n\tif (input.ollama) parts.push(input.ollama);\n\n\tif (parts.length === 0) return \"Model catalogs refreshed.\";\n\treturn parts.join(\" \");\n}\n\nfunction formatLiveProviderError(provider: CatalogRefreshProviderSummary): string {\n\tif (\n\t\tprovider.id === \"xai\" &&\n\t\tprovider.error &&\n\t\t/invalid_grant|refresh token revoked/i.test(provider.error) &&\n\t\t!/timed out|aborted|cancelled|ECONN|ENOTFOUND|network/i.test(provider.error)\n\t) {\n\t\treturn \"xai login expired (run /login xai)\";\n\t}\n\treturn provider.error ? `${provider.id} failed (${provider.error})` : `${provider.id} failed`;\n}\n\nexport function knownModelKeys(\n\tbakedIn: readonly Model<Api>[],\n\tofficial: Iterable<string>,\n\tuser: Iterable<string>,\n): Set<string> {\n\tconst keys = new Set<string>(official);\n\tfor (const key of user) keys.add(key);\n\tfor (const model of bakedIn) keys.add(modelKey(model.provider, model.id));\n\treturn keys;\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { withXaiEffortMetadata } from "@ashx-j/lunr-ai";
1
+ import { withOpenAiEffortMetadata, withXaiEffortMetadata } from "@ashx-j/lunr-ai";
2
2
  import { modelKey } from "./official-catalog.js";
3
3
  export function mergeCatalogLayers(args) {
4
4
  const byId = new Map();
@@ -28,7 +28,25 @@ export function mergeCatalogLayers(args) {
28
28
  result.push(winner);
29
29
  seen.add(model.id);
30
30
  }
31
- return result.map((model) => withXaiEffortMetadata(model));
31
+ const liveById = new Map((args.live ?? []).map((model) => [model.id, model]));
32
+ const pricedIds = new Set([...args.bakedIn, ...(args.official ?? []), ...(args.user ?? [])]
33
+ .filter((model) => model.catalog?.pricing !== "unknown")
34
+ .map((model) => model.id));
35
+ return result.map((model) => {
36
+ let resolved = withXaiEffortMetadata(model);
37
+ if (!model.catalog?.supplied.includes("thinkingLevelMap"))
38
+ resolved = withOpenAiEffortMetadata(resolved);
39
+ const live = liveById.get(model.id);
40
+ if (!live?.catalog)
41
+ return resolved;
42
+ resolved = { ...resolved, catalog: { ...live.catalog } };
43
+ // Only supplied fields may override curated metadata. Inferred defaults never win.
44
+ for (const field of live.catalog.supplied)
45
+ Object.assign(resolved, { [field]: live[field] });
46
+ if (pricedIds.has(model.id) || live.catalog.supplied.includes("cost"))
47
+ delete resolved.catalog.pricing;
48
+ return resolved;
49
+ });
32
50
  }
33
51
  export class CatalogOverlaySource {
34
52
  official = new Map();
@@ -52,6 +70,15 @@ export class CatalogOverlaySource {
52
70
  liveFor(providerId) {
53
71
  return this.live.get(providerId) ?? [];
54
72
  }
73
+ /** Codex's complete account catalog is authoritative for picker availability only. */
74
+ isAvailable(model) {
75
+ if (model.catalog?.hidden)
76
+ return false;
77
+ const live = this.liveFor(model.provider);
78
+ return (model.provider !== "openai-codex" ||
79
+ !live.length ||
80
+ live.some((row) => row.id === model.id && !row.catalog?.hidden));
81
+ }
55
82
  }
56
83
  function groupByProvider(models) {
57
84
  const byProvider = new Map();
@@ -1 +1 @@
1
- {"version":3,"file":"catalog-merge.js","sourceRoot":"","sources":["../../src/core/catalog-merge.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Api, type Model, withXaiEffortMetadata } from \"@ashx-j/lunr-ai\";\nimport { modelKey, type OfficialCatalogSource } from \"./official-catalog.ts\";\n\nexport type CatalogProviderRefreshStatus = \"ok\" | \"timeout\" | \"error\" | \"skipped\" | \"static\";\n\nexport function mergeCatalogLayers(args: {\n\tbakedIn: readonly Model<Api>[];\n\tlive?: readonly Model<Api>[];\n\tuser?: readonly Model<Api>[];\n\tofficial?: readonly Model<Api>[];\n}): Model<Api>[] {\n\tconst byId = new Map<string, Model<Api>>();\n\tfor (const model of args.bakedIn) byId.set(model.id, model);\n\tfor (const model of args.live ?? []) byId.set(model.id, model);\n\tfor (const model of args.user ?? []) byId.set(model.id, model);\n\tfor (const model of args.official ?? []) byId.set(model.id, model);\n\n\tconst seen = new Set<string>();\n\tconst result: Model<Api>[] = [];\n\tfor (const baked of args.bakedIn) {\n\t\tconst merged = byId.get(baked.id);\n\t\tif (!merged) continue;\n\t\tresult.push(merged);\n\t\tseen.add(baked.id);\n\t}\n\tfor (const model of [...(args.live ?? []), ...(args.user ?? []), ...(args.official ?? [])]) {\n\t\tif (seen.has(model.id)) continue;\n\t\tconst winner = byId.get(model.id);\n\t\tif (!winner) continue;\n\t\tresult.push(winner);\n\t\tseen.add(model.id);\n\t}\n\treturn result.map((model) => withXaiEffortMetadata(model));\n}\n\nexport class CatalogOverlaySource {\n\tprivate official = new Map<string, Model<Api>[]>();\n\tprivate user = new Map<string, Model<Api>[]>();\n\tprivate live = new Map<string, Model<Api>[]>();\n\n\tsetOfficial(models: readonly Model<Api>[]): void {\n\t\tthis.official = groupByProvider(models);\n\t}\n\n\tsetUser(models: readonly Model<Api>[]): void {\n\t\tthis.user = groupByProvider(models);\n\t}\n\n\tsetLive(providerId: string, models: readonly Model<Api>[]): void {\n\t\tthis.live.set(providerId, [...models]);\n\t}\n\n\tofficialFor(providerId: string): Model<Api>[] {\n\t\treturn this.official.get(providerId) ?? [];\n\t}\n\n\tuserFor(providerId: string): Model<Api>[] {\n\t\treturn this.user.get(providerId) ?? [];\n\t}\n\n\tliveFor(providerId: string): Model<Api>[] {\n\t\treturn this.live.get(providerId) ?? [];\n\t}\n}\n\nfunction groupByProvider(models: readonly Model<Api>[]): Map<string, Model<Api>[]> {\n\tconst byProvider = new Map<string, Model<Api>[]>();\n\tfor (const model of models) {\n\t\tconst list = byProvider.get(model.provider) ?? [];\n\t\tlist.push(model);\n\t\tbyProvider.set(model.provider, list);\n\t}\n\treturn byProvider;\n}\n\nexport function withCatalogOverlay<T extends { id: string; getModels: () => readonly Model<Api>[] }>(\n\tprovider: T,\n\toverlay: CatalogOverlaySource,\n): T {\n\tconst bakedIn = () => provider.getModels();\n\treturn {\n\t\t...provider,\n\t\tgetModels: () =>\n\t\t\tmergeCatalogLayers({\n\t\t\t\tbakedIn: bakedIn(),\n\t\t\t\tlive: overlay.liveFor(provider.id),\n\t\t\t\tuser: overlay.userFor(provider.id),\n\t\t\t\tofficial: overlay.officialFor(provider.id),\n\t\t\t}),\n\t};\n}\n\nexport interface CatalogRefreshProviderSummary {\n\tid: string;\n\tstatus: CatalogProviderRefreshStatus;\n\tadded?: number;\n\ttotal?: number;\n\terror?: string;\n}\n\nexport interface CatalogRefreshSummaryInput {\n\tofficial?: { source: OfficialCatalogSource; modelCount: number; evictedUserRows: number };\n\tproviders: readonly CatalogRefreshProviderSummary[];\n\tasked?: readonly string[];\n\textraDefaults?: number;\n\tollama?: string;\n}\n\n/** Build the /refresh toast. One hung provider must not become a global timeout line. */\nexport function formatCatalogRefreshSummary(input: CatalogRefreshSummaryInput): string {\n\tconst parts: string[] = [];\n\tif (input.official?.source === \"github\") {\n\t\tconst evicted =\n\t\t\tinput.official.evictedUserRows > 0 ? `; replaced ${input.official.evictedUserRows} user-filled row` : \"\";\n\t\tconst plural = input.official.evictedUserRows === 1 ? \"\" : input.official.evictedUserRows > 0 ? \"s\" : \"\";\n\t\tparts.push(`Official catalog updated (${input.official.modelCount} models)${evicted}${plural}.`);\n\t}\n\n\tconst refreshed: string[] = [];\n\tconst failed: string[] = [];\n\tfor (const provider of input.providers) {\n\t\tif (provider.status === \"ok\") {\n\t\t\tconst added = provider.added ?? 0;\n\t\t\tconst total = provider.total ?? 0;\n\t\t\trefreshed.push(added > 0 ? `${provider.id} (+${added})` : `${provider.id} (${total})`);\n\t\t} else if (provider.status === \"timeout\") {\n\t\t\tfailed.push(`${provider.id} timed out (cached)`);\n\t\t} else if (provider.status === \"error\") {\n\t\t\tfailed.push(formatLiveProviderError(provider));\n\t\t}\n\t}\n\n\tif (refreshed.length > 0) {\n\t\tparts.push(`Refreshed ${refreshed.join(\", \")}.`);\n\t} else if (input.providers.some((provider) => provider.status === \"ok\")) {\n\t\tparts.push(\"Refreshed model catalogs.\");\n\t}\n\n\tif (failed.length > 0) {\n\t\tparts.push(`${failed.join(\"; \")}.`);\n\t}\n\n\tif (input.asked && input.asked.length > 0) {\n\t\tparts.push(`Asked for missing metadata on ${input.asked.join(\", \")}.`);\n\t}\n\tif (input.extraDefaults && input.extraDefaults > 0) {\n\t\tparts.push(`+${input.extraDefaults} more using defaults.`);\n\t}\n\tif (input.ollama) parts.push(input.ollama);\n\n\tif (parts.length === 0) return \"Model catalogs refreshed.\";\n\treturn parts.join(\" \");\n}\n\nfunction formatLiveProviderError(provider: CatalogRefreshProviderSummary): string {\n\tif (\n\t\tprovider.id === \"xai\" &&\n\t\tprovider.error &&\n\t\t/invalid_grant|refresh token revoked/i.test(provider.error) &&\n\t\t!/timed out|aborted|cancelled|ECONN|ENOTFOUND|network/i.test(provider.error)\n\t) {\n\t\treturn \"xai login expired (run /login xai)\";\n\t}\n\treturn provider.error ? `${provider.id} failed (${provider.error})` : `${provider.id} failed`;\n}\n\nexport function knownModelKeys(\n\tbakedIn: readonly Model<Api>[],\n\tofficial: Iterable<string>,\n\tuser: Iterable<string>,\n): Set<string> {\n\tconst keys = new Set<string>(official);\n\tfor (const key of user) keys.add(key);\n\tfor (const model of bakedIn) keys.add(modelKey(model.provider, model.id));\n\treturn keys;\n}\n"]}
1
+ {"version":3,"file":"catalog-merge.js","sourceRoot":"","sources":["../../src/core/catalog-merge.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Api, type Model, withOpenAiEffortMetadata, withXaiEffortMetadata } from \"@ashx-j/lunr-ai\";\nimport { modelKey, type OfficialCatalogSource } from \"./official-catalog.ts\";\n\nexport type CatalogProviderRefreshStatus = \"ok\" | \"timeout\" | \"error\" | \"skipped\" | \"static\";\n\nexport function mergeCatalogLayers(args: {\n\tbakedIn: readonly Model<Api>[];\n\tlive?: readonly Model<Api>[];\n\tuser?: readonly Model<Api>[];\n\tofficial?: readonly Model<Api>[];\n}): Model<Api>[] {\n\tconst byId = new Map<string, Model<Api>>();\n\tfor (const model of args.bakedIn) byId.set(model.id, model);\n\tfor (const model of args.live ?? []) byId.set(model.id, model);\n\tfor (const model of args.user ?? []) byId.set(model.id, model);\n\tfor (const model of args.official ?? []) byId.set(model.id, model);\n\n\tconst seen = new Set<string>();\n\tconst result: Model<Api>[] = [];\n\tfor (const baked of args.bakedIn) {\n\t\tconst merged = byId.get(baked.id);\n\t\tif (!merged) continue;\n\t\tresult.push(merged);\n\t\tseen.add(baked.id);\n\t}\n\tfor (const model of [...(args.live ?? []), ...(args.user ?? []), ...(args.official ?? [])]) {\n\t\tif (seen.has(model.id)) continue;\n\t\tconst winner = byId.get(model.id);\n\t\tif (!winner) continue;\n\t\tresult.push(winner);\n\t\tseen.add(model.id);\n\t}\n\tconst liveById = new Map((args.live ?? []).map((model) => [model.id, model]));\n\tconst pricedIds = new Set(\n\t\t[...args.bakedIn, ...(args.official ?? []), ...(args.user ?? [])]\n\t\t\t.filter((model) => model.catalog?.pricing !== \"unknown\")\n\t\t\t.map((model) => model.id),\n\t);\n\treturn result.map((model) => {\n\t\tlet resolved = withXaiEffortMetadata(model);\n\t\tif (!model.catalog?.supplied.includes(\"thinkingLevelMap\")) resolved = withOpenAiEffortMetadata(resolved);\n\t\tconst live = liveById.get(model.id);\n\t\tif (!live?.catalog) return resolved;\n\t\tresolved = { ...resolved, catalog: { ...live.catalog } };\n\t\t// Only supplied fields may override curated metadata. Inferred defaults never win.\n\t\tfor (const field of live.catalog.supplied) Object.assign(resolved, { [field]: live[field] });\n\t\tif (pricedIds.has(model.id) || live.catalog.supplied.includes(\"cost\")) delete resolved.catalog!.pricing;\n\t\treturn resolved;\n\t});\n}\n\nexport class CatalogOverlaySource {\n\tprivate official = new Map<string, Model<Api>[]>();\n\tprivate user = new Map<string, Model<Api>[]>();\n\tprivate live = new Map<string, Model<Api>[]>();\n\n\tsetOfficial(models: readonly Model<Api>[]): void {\n\t\tthis.official = groupByProvider(models);\n\t}\n\n\tsetUser(models: readonly Model<Api>[]): void {\n\t\tthis.user = groupByProvider(models);\n\t}\n\n\tsetLive(providerId: string, models: readonly Model<Api>[]): void {\n\t\tthis.live.set(providerId, [...models]);\n\t}\n\n\tofficialFor(providerId: string): Model<Api>[] {\n\t\treturn this.official.get(providerId) ?? [];\n\t}\n\n\tuserFor(providerId: string): Model<Api>[] {\n\t\treturn this.user.get(providerId) ?? [];\n\t}\n\n\tliveFor(providerId: string): Model<Api>[] {\n\t\treturn this.live.get(providerId) ?? [];\n\t}\n\n\t/** Codex's complete account catalog is authoritative for picker availability only. */\n\tisAvailable(model: Model<Api>): boolean {\n\t\tif (model.catalog?.hidden) return false;\n\t\tconst live = this.liveFor(model.provider);\n\t\treturn (\n\t\t\tmodel.provider !== \"openai-codex\" ||\n\t\t\t!live.length ||\n\t\t\tlive.some((row) => row.id === model.id && !row.catalog?.hidden)\n\t\t);\n\t}\n}\n\nfunction groupByProvider(models: readonly Model<Api>[]): Map<string, Model<Api>[]> {\n\tconst byProvider = new Map<string, Model<Api>[]>();\n\tfor (const model of models) {\n\t\tconst list = byProvider.get(model.provider) ?? [];\n\t\tlist.push(model);\n\t\tbyProvider.set(model.provider, list);\n\t}\n\treturn byProvider;\n}\n\nexport function withCatalogOverlay<T extends { id: string; getModels: () => readonly Model<Api>[] }>(\n\tprovider: T,\n\toverlay: CatalogOverlaySource,\n): T {\n\tconst bakedIn = () => provider.getModels();\n\treturn {\n\t\t...provider,\n\t\tgetModels: () =>\n\t\t\tmergeCatalogLayers({\n\t\t\t\tbakedIn: bakedIn(),\n\t\t\t\tlive: overlay.liveFor(provider.id),\n\t\t\t\tuser: overlay.userFor(provider.id),\n\t\t\t\tofficial: overlay.officialFor(provider.id),\n\t\t\t}),\n\t};\n}\n\nexport interface CatalogRefreshProviderSummary {\n\tid: string;\n\tstatus: CatalogProviderRefreshStatus;\n\tadded?: number;\n\ttotal?: number;\n\terror?: string;\n}\n\nexport interface CatalogRefreshSummaryInput {\n\tofficial?: { source: OfficialCatalogSource; modelCount: number; evictedUserRows: number };\n\tproviders: readonly CatalogRefreshProviderSummary[];\n\tasked?: readonly string[];\n\textraDefaults?: number;\n\tollama?: string;\n}\n\n/** Build the /refresh toast. One hung provider must not become a global timeout line. */\nexport function formatCatalogRefreshSummary(input: CatalogRefreshSummaryInput): string {\n\tconst parts: string[] = [];\n\tif (input.official?.source === \"github\") {\n\t\tconst evicted =\n\t\t\tinput.official.evictedUserRows > 0 ? `; replaced ${input.official.evictedUserRows} user-filled row` : \"\";\n\t\tconst plural = input.official.evictedUserRows === 1 ? \"\" : input.official.evictedUserRows > 0 ? \"s\" : \"\";\n\t\tparts.push(`Official catalog updated (${input.official.modelCount} models)${evicted}${plural}.`);\n\t}\n\n\tconst refreshed: string[] = [];\n\tconst failed: string[] = [];\n\tfor (const provider of input.providers) {\n\t\tif (provider.status === \"ok\") {\n\t\t\tconst added = provider.added ?? 0;\n\t\t\tconst total = provider.total ?? 0;\n\t\t\trefreshed.push(added > 0 ? `${provider.id} (+${added})` : `${provider.id} (${total})`);\n\t\t} else if (provider.status === \"timeout\") {\n\t\t\tfailed.push(`${provider.id} timed out (cached)`);\n\t\t} else if (provider.status === \"error\") {\n\t\t\tfailed.push(formatLiveProviderError(provider));\n\t\t}\n\t}\n\n\tif (refreshed.length > 0) {\n\t\tparts.push(`Refreshed ${refreshed.join(\", \")}.`);\n\t} else if (input.providers.some((provider) => provider.status === \"ok\")) {\n\t\tparts.push(\"Refreshed model catalogs.\");\n\t}\n\n\tif (failed.length > 0) {\n\t\tparts.push(`${failed.join(\"; \")}.`);\n\t}\n\n\tif (input.asked && input.asked.length > 0) {\n\t\tparts.push(`Asked for missing metadata on ${input.asked.join(\", \")}.`);\n\t}\n\tif (input.extraDefaults && input.extraDefaults > 0) {\n\t\tparts.push(`+${input.extraDefaults} more using defaults.`);\n\t}\n\tif (input.ollama) parts.push(input.ollama);\n\n\tif (parts.length === 0) return \"Model catalogs refreshed.\";\n\treturn parts.join(\" \");\n}\n\nfunction formatLiveProviderError(provider: CatalogRefreshProviderSummary): string {\n\tif (\n\t\tprovider.id === \"xai\" &&\n\t\tprovider.error &&\n\t\t/invalid_grant|refresh token revoked/i.test(provider.error) &&\n\t\t!/timed out|aborted|cancelled|ECONN|ENOTFOUND|network/i.test(provider.error)\n\t) {\n\t\treturn \"xai login expired (run /login xai)\";\n\t}\n\treturn provider.error ? `${provider.id} failed (${provider.error})` : `${provider.id} failed`;\n}\n\nexport function knownModelKeys(\n\tbakedIn: readonly Model<Api>[],\n\tofficial: Iterable<string>,\n\tuser: Iterable<string>,\n): Set<string> {\n\tconst keys = new Set<string>(official);\n\tfor (const key of user) keys.add(key);\n\tfor (const model of bakedIn) keys.add(modelKey(model.provider, model.id));\n\treturn keys;\n}\n"]}
@@ -0,0 +1,8 @@
1
+ /** Poll only after the owner has painted. Timers never keep a CLI process alive. */
2
+ export declare function startCatalogRefreshPolling(options: {
3
+ refresh: (signal: AbortSignal) => Promise<unknown>;
4
+ isBusy: () => boolean;
5
+ onUpdate: () => void;
6
+ onError?: (error: unknown) => void;
7
+ }): () => void;
8
+ //# sourceMappingURL=catalog-refresh-polling.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog-refresh-polling.d.ts","sourceRoot":"","sources":["../../src/core/catalog-refresh-polling.ts"],"names":[],"mappings":"AAAA,oFAAoF;AACpF,wBAAgB,0BAA0B,CAAC,OAAO,EAAE;IACnD,OAAO,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACnD,MAAM,EAAE,MAAM,OAAO,CAAC;IACtB,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CACnC,GAAG,MAAM,IAAI,CAsBb","sourcesContent":["/** Poll only after the owner has painted. Timers never keep a CLI process alive. */\nexport function startCatalogRefreshPolling(options: {\n\trefresh: (signal: AbortSignal) => Promise<unknown>;\n\tisBusy: () => boolean;\n\tonUpdate: () => void;\n\tonError?: (error: unknown) => void;\n}): () => void {\n\tconst controller = new AbortController();\n\tlet running = false;\n\tconst tick = async () => {\n\t\tif (running || controller.signal.aborted || options.isBusy()) return;\n\t\trunning = true;\n\t\ttry {\n\t\t\tawait options.refresh(controller.signal);\n\t\t\tif (!controller.signal.aborted && !options.isBusy()) options.onUpdate();\n\t\t} catch (error) {\n\t\t\tif (!controller.signal.aborted) options.onError?.(error);\n\t\t} finally {\n\t\t\trunning = false;\n\t\t}\n\t};\n\tvoid tick();\n\tconst timer = setInterval(() => void tick(), 60_000);\n\ttimer.unref?.();\n\treturn () => {\n\t\tcontroller.abort();\n\t\tclearInterval(timer);\n\t};\n}\n"]}
@@ -0,0 +1,30 @@
1
+ /** Poll only after the owner has painted. Timers never keep a CLI process alive. */
2
+ export function startCatalogRefreshPolling(options) {
3
+ const controller = new AbortController();
4
+ let running = false;
5
+ const tick = async () => {
6
+ if (running || controller.signal.aborted || options.isBusy())
7
+ return;
8
+ running = true;
9
+ try {
10
+ await options.refresh(controller.signal);
11
+ if (!controller.signal.aborted && !options.isBusy())
12
+ options.onUpdate();
13
+ }
14
+ catch (error) {
15
+ if (!controller.signal.aborted)
16
+ options.onError?.(error);
17
+ }
18
+ finally {
19
+ running = false;
20
+ }
21
+ };
22
+ void tick();
23
+ const timer = setInterval(() => void tick(), 60_000);
24
+ timer.unref?.();
25
+ return () => {
26
+ controller.abort();
27
+ clearInterval(timer);
28
+ };
29
+ }
30
+ //# sourceMappingURL=catalog-refresh-polling.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog-refresh-polling.js","sourceRoot":"","sources":["../../src/core/catalog-refresh-polling.ts"],"names":[],"mappings":"AAAA,oFAAoF;AACpF,MAAM,UAAU,0BAA0B,CAAC,OAK1C,EAAc;IACd,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,MAAM,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;QACxB,IAAI,OAAO,IAAI,UAAU,CAAC,MAAM,CAAC,OAAO,IAAI,OAAO,CAAC,MAAM,EAAE;YAAE,OAAO;QACrE,OAAO,GAAG,IAAI,CAAC;QACf,IAAI,CAAC;YACJ,MAAM,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;YACzC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE;gBAAE,OAAO,CAAC,QAAQ,EAAE,CAAC;QACzE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,OAAO;gBAAE,OAAO,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC;QAC1D,CAAC;gBAAS,CAAC;YACV,OAAO,GAAG,KAAK,CAAC;QACjB,CAAC;IAAA,CACD,CAAC;IACF,KAAK,IAAI,EAAE,CAAC;IACZ,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,KAAK,IAAI,EAAE,EAAE,MAAM,CAAC,CAAC;IACrD,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC;IAChB,OAAO,GAAG,EAAE,CAAC;QACZ,UAAU,CAAC,KAAK,EAAE,CAAC;QACnB,aAAa,CAAC,KAAK,CAAC,CAAC;IAAA,CACrB,CAAC;AAAA,CACF","sourcesContent":["/** Poll only after the owner has painted. Timers never keep a CLI process alive. */\nexport function startCatalogRefreshPolling(options: {\n\trefresh: (signal: AbortSignal) => Promise<unknown>;\n\tisBusy: () => boolean;\n\tonUpdate: () => void;\n\tonError?: (error: unknown) => void;\n}): () => void {\n\tconst controller = new AbortController();\n\tlet running = false;\n\tconst tick = async () => {\n\t\tif (running || controller.signal.aborted || options.isBusy()) return;\n\t\trunning = true;\n\t\ttry {\n\t\t\tawait options.refresh(controller.signal);\n\t\t\tif (!controller.signal.aborted && !options.isBusy()) options.onUpdate();\n\t\t} catch (error) {\n\t\t\tif (!controller.signal.aborted) options.onError?.(error);\n\t\t} finally {\n\t\t\trunning = false;\n\t\t}\n\t};\n\tvoid tick();\n\tconst timer = setInterval(() => void tick(), 60_000);\n\ttimer.unref?.();\n\treturn () => {\n\t\tcontroller.abort();\n\t\tclearInterval(timer);\n\t};\n}\n"]}
@@ -0,0 +1,3 @@
1
+ import type { LiveModelDiscovery } from "./live-catalog.ts";
2
+ export declare function discoverCodexModels(payload: unknown, baseUrl: string): LiveModelDiscovery[];
3
+ //# sourceMappingURL=codex-catalog.d.ts.map