@bastani/atomic 0.9.4-alpha.1 → 0.9.4-alpha.11

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 (345) hide show
  1. package/CHANGELOG.md +109 -0
  2. package/dist/builtin/cursor/CHANGELOG.md +24 -0
  3. package/dist/builtin/cursor/package.json +4 -4
  4. package/dist/builtin/intercom/CHANGELOG.md +24 -0
  5. package/dist/builtin/intercom/package.json +2 -2
  6. package/dist/builtin/mcp/CHANGELOG.md +24 -0
  7. package/dist/builtin/mcp/package.json +4 -4
  8. package/dist/builtin/subagents/CHANGELOG.md +52 -0
  9. package/dist/builtin/subagents/agents/code-simplifier.md +2 -2
  10. package/dist/builtin/subagents/agents/codebase-analyzer.md +2 -2
  11. package/dist/builtin/subagents/agents/codebase-locator.md +2 -2
  12. package/dist/builtin/subagents/agents/codebase-online-researcher.md +2 -2
  13. package/dist/builtin/subagents/agents/codebase-pattern-finder.md +2 -2
  14. package/dist/builtin/subagents/agents/codebase-research-analyzer.md +2 -2
  15. package/dist/builtin/subagents/agents/codebase-research-locator.md +2 -2
  16. package/dist/builtin/subagents/agents/debugger.md +1 -1
  17. package/dist/builtin/subagents/agents/worker.md +2 -2
  18. package/dist/builtin/subagents/package.json +4 -4
  19. package/dist/builtin/subagents/src/runs/background/async-execution-chain.ts +11 -1
  20. package/dist/builtin/subagents/src/runs/background/async-execution-single.ts +11 -1
  21. package/dist/builtin/subagents/src/runs/background/async-execution-types.ts +2 -0
  22. package/dist/builtin/subagents/src/runs/background/subagent-runner-step.ts +27 -4
  23. package/dist/builtin/subagents/src/runs/background/subagent-runner-streaming.ts +25 -0
  24. package/dist/builtin/subagents/src/runs/foreground/chain-execution-dynamic-step.ts +1 -0
  25. package/dist/builtin/subagents/src/runs/foreground/chain-execution-parallel-runner.ts +1 -0
  26. package/dist/builtin/subagents/src/runs/foreground/chain-execution-parallel-step.ts +1 -0
  27. package/dist/builtin/subagents/src/runs/foreground/chain-execution-sequential-step.ts +1 -0
  28. package/dist/builtin/subagents/src/runs/foreground/chain-execution-types.ts +2 -0
  29. package/dist/builtin/subagents/src/runs/foreground/chain-execution.ts +3 -1
  30. package/dist/builtin/subagents/src/runs/foreground/execution-attempt.ts +22 -0
  31. package/dist/builtin/subagents/src/runs/foreground/execution-run-sync.ts +15 -5
  32. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-async.ts +5 -1
  33. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-parallel-task.ts +2 -0
  34. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-parallel.ts +4 -1
  35. package/dist/builtin/subagents/src/runs/foreground/subagent-executor-single.ts +4 -1
  36. package/dist/builtin/subagents/src/runs/shared/attempt-watchdog.ts +126 -0
  37. package/dist/builtin/subagents/src/runs/shared/model-candidate-filter.ts +53 -0
  38. package/dist/builtin/subagents/src/runs/shared/model-fallback.ts +52 -53
  39. package/dist/builtin/subagents/src/runs/shared/parallel-utils.ts +2 -0
  40. package/dist/builtin/subagents/src/shared/model-info.ts +16 -0
  41. package/dist/builtin/subagents/src/shared/types-config.ts +2 -0
  42. package/dist/builtin/subagents/src/slash/slash-commands.ts +2 -2
  43. package/dist/builtin/subagents/src/tui/render-result-compact.ts +3 -2
  44. package/dist/builtin/subagents/src/tui/render-result.ts +3 -3
  45. package/dist/builtin/subagents/src/tui/render-widget-graph.ts +4 -3
  46. package/dist/builtin/subagents/src/tui/render-widget.ts +10 -4
  47. package/dist/builtin/web-access/CHANGELOG.md +24 -0
  48. package/dist/builtin/web-access/package.json +2 -2
  49. package/dist/builtin/workflows/CHANGELOG.md +54 -0
  50. package/dist/builtin/workflows/builtin/deep-research-codebase-utils.ts +24 -22
  51. package/dist/builtin/workflows/builtin/goal-runner.ts +12 -23
  52. package/dist/builtin/workflows/builtin/open-claude-design-runner.ts +4 -4
  53. package/dist/builtin/workflows/builtin/ralph-models.ts +53 -75
  54. package/dist/builtin/workflows/package.json +2 -2
  55. package/dist/builtin/workflows/src/runs/shared/model-fallback-failures.ts +59 -1
  56. package/dist/builtin/workflows/src/tui/keybindings-adapter.ts +4 -0
  57. package/dist/builtin/workflows/src/tui/overlay-adapter.ts +4 -0
  58. package/dist/builtin/workflows/src/tui/stage-chat-view-input.ts +12 -1
  59. package/dist/builtin/workflows/src/tui/stage-chat-view-state.ts +2 -0
  60. package/dist/builtin/workflows/src/tui/stage-chat-view-types.ts +6 -0
  61. package/dist/builtin/workflows/src/tui/stage-chat-view.ts +4 -0
  62. package/dist/builtin/workflows/src/tui/workflow-attach-pane-types.ts +4 -0
  63. package/dist/builtin/workflows/src/tui/workflow-attach-pane.ts +8 -9
  64. package/dist/bun/cli.d.ts.map +1 -1
  65. package/dist/bun/cli.js +3 -2
  66. package/dist/bun/cli.js.map +1 -1
  67. package/dist/cli/file-processor.d.ts.map +1 -1
  68. package/dist/cli/file-processor.js +13 -25
  69. package/dist/cli/file-processor.js.map +1 -1
  70. package/dist/cli.d.ts.map +1 -1
  71. package/dist/cli.js +15 -5
  72. package/dist/cli.js.map +1 -1
  73. package/dist/config.d.ts +10 -3
  74. package/dist/config.d.ts.map +1 -1
  75. package/dist/config.js +18 -1
  76. package/dist/config.js.map +1 -1
  77. package/dist/core/agent-session-auto-compaction.d.ts.map +1 -1
  78. package/dist/core/agent-session-auto-compaction.js +8 -1
  79. package/dist/core/agent-session-auto-compaction.js.map +1 -1
  80. package/dist/core/agent-session-events.d.ts.map +1 -1
  81. package/dist/core/agent-session-events.js +16 -8
  82. package/dist/core/agent-session-events.js.map +1 -1
  83. package/dist/core/agent-session-export.d.ts.map +1 -1
  84. package/dist/core/agent-session-export.js +4 -2
  85. package/dist/core/agent-session-export.js.map +1 -1
  86. package/dist/core/agent-session-extension-bindings.d.ts +5 -1
  87. package/dist/core/agent-session-extension-bindings.d.ts.map +1 -1
  88. package/dist/core/agent-session-extension-bindings.js +18 -7
  89. package/dist/core/agent-session-extension-bindings.js.map +1 -1
  90. package/dist/core/agent-session-methods.d.ts +13 -3
  91. package/dist/core/agent-session-methods.d.ts.map +1 -1
  92. package/dist/core/agent-session-methods.js.map +1 -1
  93. package/dist/core/agent-session-prompt.d.ts +2 -0
  94. package/dist/core/agent-session-prompt.d.ts.map +1 -1
  95. package/dist/core/agent-session-prompt.js +15 -2
  96. package/dist/core/agent-session-prompt.js.map +1 -1
  97. package/dist/core/agent-session-retry.d.ts +2 -0
  98. package/dist/core/agent-session-retry.d.ts.map +1 -1
  99. package/dist/core/agent-session-retry.js +66 -7
  100. package/dist/core/agent-session-retry.js.map +1 -1
  101. package/dist/core/agent-session-state.d.ts.map +1 -1
  102. package/dist/core/agent-session-state.js +2 -2
  103. package/dist/core/agent-session-state.js.map +1 -1
  104. package/dist/core/agent-session-tool-hooks.d.ts +7 -1
  105. package/dist/core/agent-session-tool-hooks.d.ts.map +1 -1
  106. package/dist/core/agent-session-tool-hooks.js +26 -4
  107. package/dist/core/agent-session-tool-hooks.js.map +1 -1
  108. package/dist/core/agent-session-tool-registry.d.ts.map +1 -1
  109. package/dist/core/agent-session-tool-registry.js +4 -0
  110. package/dist/core/agent-session-tool-registry.js.map +1 -1
  111. package/dist/core/agent-session-tree.d.ts.map +1 -1
  112. package/dist/core/agent-session-tree.js +3 -1
  113. package/dist/core/agent-session-tree.js.map +1 -1
  114. package/dist/core/agent-session-types.d.ts +4 -0
  115. package/dist/core/agent-session-types.d.ts.map +1 -1
  116. package/dist/core/agent-session-types.js.map +1 -1
  117. package/dist/core/agent-session.d.ts +5 -1
  118. package/dist/core/agent-session.d.ts.map +1 -1
  119. package/dist/core/agent-session.js +5 -0
  120. package/dist/core/agent-session.js.map +1 -1
  121. package/dist/core/async/format.d.ts +3 -0
  122. package/dist/core/async/format.d.ts.map +1 -0
  123. package/dist/core/async/format.js +50 -0
  124. package/dist/core/async/format.js.map +1 -0
  125. package/dist/core/async/job-manager.d.ts +39 -0
  126. package/dist/core/async/job-manager.d.ts.map +1 -0
  127. package/dist/core/async/job-manager.js +254 -0
  128. package/dist/core/async/job-manager.js.map +1 -0
  129. package/dist/core/async/session-manager.d.ts +18 -0
  130. package/dist/core/async/session-manager.d.ts.map +1 -0
  131. package/dist/core/async/session-manager.js +61 -0
  132. package/dist/core/async/session-manager.js.map +1 -0
  133. package/dist/core/async/types.d.ts +23 -0
  134. package/dist/core/async/types.d.ts.map +1 -0
  135. package/dist/core/async/types.js +2 -0
  136. package/dist/core/async/types.js.map +1 -0
  137. package/dist/core/copilot-model-catalog.d.ts +38 -74
  138. package/dist/core/copilot-model-catalog.d.ts.map +1 -1
  139. package/dist/core/copilot-model-catalog.js +177 -68
  140. package/dist/core/copilot-model-catalog.js.map +1 -1
  141. package/dist/core/copilot-model-static-fallbacks.d.ts +43 -0
  142. package/dist/core/copilot-model-static-fallbacks.d.ts.map +1 -0
  143. package/dist/core/copilot-model-static-fallbacks.js +50 -0
  144. package/dist/core/copilot-model-static-fallbacks.js.map +1 -0
  145. package/dist/core/copilot-model-synthesis.d.ts +10 -0
  146. package/dist/core/copilot-model-synthesis.d.ts.map +1 -0
  147. package/dist/core/copilot-model-synthesis.js +89 -0
  148. package/dist/core/copilot-model-synthesis.js.map +1 -0
  149. package/dist/core/extensions/api-types.d.ts +2 -1
  150. package/dist/core/extensions/api-types.d.ts.map +1 -1
  151. package/dist/core/extensions/api-types.js.map +1 -1
  152. package/dist/core/extensions/index.d.ts +1 -1
  153. package/dist/core/extensions/index.d.ts.map +1 -1
  154. package/dist/core/extensions/index.js.map +1 -1
  155. package/dist/core/extensions/loader-core.d.ts.map +1 -1
  156. package/dist/core/extensions/loader-core.js +3 -3
  157. package/dist/core/extensions/loader-core.js.map +1 -1
  158. package/dist/core/extensions/loader-virtual-modules.d.ts +11 -0
  159. package/dist/core/extensions/loader-virtual-modules.d.ts.map +1 -1
  160. package/dist/core/extensions/loader-virtual-modules.js +79 -11
  161. package/dist/core/extensions/loader-virtual-modules.js.map +1 -1
  162. package/dist/core/extensions/session-events.d.ts +7 -1
  163. package/dist/core/extensions/session-events.d.ts.map +1 -1
  164. package/dist/core/extensions/session-events.js.map +1 -1
  165. package/dist/core/http-dispatcher.d.ts +2 -0
  166. package/dist/core/http-dispatcher.d.ts.map +1 -1
  167. package/dist/core/http-dispatcher.js +38 -5
  168. package/dist/core/http-dispatcher.js.map +1 -1
  169. package/dist/core/model-registry-builtins.d.ts.map +1 -1
  170. package/dist/core/model-registry-builtins.js +40 -6
  171. package/dist/core/model-registry-builtins.js.map +1 -1
  172. package/dist/core/model-registry.d.ts.map +1 -1
  173. package/dist/core/model-registry.js +4 -3
  174. package/dist/core/model-registry.js.map +1 -1
  175. package/dist/core/model-resolver-defaults.d.ts.map +1 -1
  176. package/dist/core/model-resolver-defaults.js +1 -1
  177. package/dist/core/model-resolver-defaults.js.map +1 -1
  178. package/dist/core/resource-loader-reload.d.ts.map +1 -1
  179. package/dist/core/resource-loader-reload.js +6 -3
  180. package/dist/core/resource-loader-reload.js.map +1 -1
  181. package/dist/core/resource-loader-types.d.ts +6 -0
  182. package/dist/core/resource-loader-types.d.ts.map +1 -1
  183. package/dist/core/resource-loader-types.js.map +1 -1
  184. package/dist/core/session-manager-core.d.ts +2 -12
  185. package/dist/core/session-manager-core.d.ts.map +1 -1
  186. package/dist/core/session-manager-core.js +8 -16
  187. package/dist/core/session-manager-core.js.map +1 -1
  188. package/dist/core/settings-manager-resource-accessors.d.ts +1 -0
  189. package/dist/core/settings-manager-resource-accessors.d.ts.map +1 -1
  190. package/dist/core/settings-manager-resource-accessors.js +11 -0
  191. package/dist/core/settings-manager-resource-accessors.js.map +1 -1
  192. package/dist/core/settings-manager-ui-accessors.d.ts +2 -0
  193. package/dist/core/settings-manager-ui-accessors.d.ts.map +1 -1
  194. package/dist/core/settings-manager-ui-accessors.js +9 -0
  195. package/dist/core/settings-manager-ui-accessors.js.map +1 -1
  196. package/dist/core/settings-types.d.ts +2 -0
  197. package/dist/core/settings-types.d.ts.map +1 -1
  198. package/dist/core/settings-types.js.map +1 -1
  199. package/dist/core/timings.d.ts +7 -5
  200. package/dist/core/timings.d.ts.map +1 -1
  201. package/dist/core/timings.js +42 -24
  202. package/dist/core/timings.js.map +1 -1
  203. package/dist/core/tools/bash-async-execution.d.ts +25 -0
  204. package/dist/core/tools/bash-async-execution.d.ts.map +1 -0
  205. package/dist/core/tools/bash-async-execution.js +71 -0
  206. package/dist/core/tools/bash-async-execution.js.map +1 -0
  207. package/dist/core/tools/bash-async-jobs.d.ts +10 -0
  208. package/dist/core/tools/bash-async-jobs.d.ts.map +1 -1
  209. package/dist/core/tools/bash-async-jobs.js +18 -2
  210. package/dist/core/tools/bash-async-jobs.js.map +1 -1
  211. package/dist/core/tools/bash-async-output.d.ts +3 -1
  212. package/dist/core/tools/bash-async-output.d.ts.map +1 -1
  213. package/dist/core/tools/bash-async-output.js +4 -1
  214. package/dist/core/tools/bash-async-output.js.map +1 -1
  215. package/dist/core/tools/bash-pty-native.d.ts.map +1 -1
  216. package/dist/core/tools/bash-pty-native.js +2 -2
  217. package/dist/core/tools/bash-pty-native.js.map +1 -1
  218. package/dist/core/tools/bash.d.ts +10 -4
  219. package/dist/core/tools/bash.d.ts.map +1 -1
  220. package/dist/core/tools/bash.js +20 -38
  221. package/dist/core/tools/bash.js.map +1 -1
  222. package/dist/core/tools/read-selectors.d.ts.map +1 -1
  223. package/dist/core/tools/read-selectors.js +19 -1
  224. package/dist/core/tools/read-selectors.js.map +1 -1
  225. package/dist/core/tools/read.d.ts.map +1 -1
  226. package/dist/core/tools/read.js +12 -23
  227. package/dist/core/tools/read.js.map +1 -1
  228. package/dist/core/tools/search-native.d.ts.map +1 -1
  229. package/dist/core/tools/search-native.js +2 -2
  230. package/dist/core/tools/search-native.js.map +1 -1
  231. package/dist/index-extensions.d.ts +1 -1
  232. package/dist/index-extensions.d.ts.map +1 -1
  233. package/dist/index-extensions.js.map +1 -1
  234. package/dist/index.d.ts +1 -1
  235. package/dist/index.d.ts.map +1 -1
  236. package/dist/index.js.map +1 -1
  237. package/dist/main-session.d.ts.map +1 -1
  238. package/dist/main-session.js +14 -5
  239. package/dist/main-session.js.map +1 -1
  240. package/dist/main.d.ts.map +1 -1
  241. package/dist/main.js +56 -32
  242. package/dist/main.js.map +1 -1
  243. package/dist/modes/interactive/components/assistant-message.d.ts +3 -1
  244. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  245. package/dist/modes/interactive/components/assistant-message.js +22 -15
  246. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  247. package/dist/modes/interactive/components/chat-message-renderer.d.ts +1 -0
  248. package/dist/modes/interactive/components/chat-message-renderer.d.ts.map +1 -1
  249. package/dist/modes/interactive/components/chat-message-renderer.js +5 -5
  250. package/dist/modes/interactive/components/chat-message-renderer.js.map +1 -1
  251. package/dist/modes/interactive/components/chat-session-host-events.d.ts.map +1 -1
  252. package/dist/modes/interactive/components/chat-session-host-events.js +8 -0
  253. package/dist/modes/interactive/components/chat-session-host-events.js.map +1 -1
  254. package/dist/modes/interactive/components/chat-session-host-rendering.d.ts.map +1 -1
  255. package/dist/modes/interactive/components/chat-session-host-rendering.js +1 -0
  256. package/dist/modes/interactive/components/chat-session-host-rendering.js.map +1 -1
  257. package/dist/modes/interactive/components/user-message.d.ts +6 -2
  258. package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  259. package/dist/modes/interactive/components/user-message.js +16 -5
  260. package/dist/modes/interactive/components/user-message.js.map +1 -1
  261. package/dist/modes/interactive/interactive-agent-events.d.ts.map +1 -1
  262. package/dist/modes/interactive/interactive-agent-events.js +6 -1
  263. package/dist/modes/interactive/interactive-agent-events.js.map +1 -1
  264. package/dist/modes/interactive/interactive-deferred-startup.d.ts +2 -0
  265. package/dist/modes/interactive/interactive-deferred-startup.d.ts.map +1 -0
  266. package/dist/modes/interactive/interactive-deferred-startup.js +59 -0
  267. package/dist/modes/interactive/interactive-deferred-startup.js.map +1 -0
  268. package/dist/modes/interactive/interactive-editor-actions.d.ts.map +1 -1
  269. package/dist/modes/interactive/interactive-editor-actions.js +1 -0
  270. package/dist/modes/interactive/interactive-editor-actions.js.map +1 -1
  271. package/dist/modes/interactive/interactive-extension-context.d.ts.map +1 -1
  272. package/dist/modes/interactive/interactive-extension-context.js +1 -0
  273. package/dist/modes/interactive/interactive-extension-context.js.map +1 -1
  274. package/dist/modes/interactive/interactive-mode-base.d.ts +3 -0
  275. package/dist/modes/interactive/interactive-mode-base.d.ts.map +1 -1
  276. package/dist/modes/interactive/interactive-mode-base.js +6 -0
  277. package/dist/modes/interactive/interactive-mode-base.js.map +1 -1
  278. package/dist/modes/interactive/interactive-mode-deps.d.ts +1 -1
  279. package/dist/modes/interactive/interactive-mode-deps.d.ts.map +1 -1
  280. package/dist/modes/interactive/interactive-mode-deps.js +1 -1
  281. package/dist/modes/interactive/interactive-mode-deps.js.map +1 -1
  282. package/dist/modes/interactive/interactive-mode-surface.d.ts +2 -0
  283. package/dist/modes/interactive/interactive-mode-surface.d.ts.map +1 -1
  284. package/dist/modes/interactive/interactive-mode-surface.js.map +1 -1
  285. package/dist/modes/interactive/interactive-mode-types.d.ts +2 -0
  286. package/dist/modes/interactive/interactive-mode-types.d.ts.map +1 -1
  287. package/dist/modes/interactive/interactive-mode-types.js.map +1 -1
  288. package/dist/modes/interactive/interactive-mode.d.ts +1 -0
  289. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  290. package/dist/modes/interactive/interactive-mode.js +1 -0
  291. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  292. package/dist/modes/interactive/interactive-model-routing.d.ts.map +1 -1
  293. package/dist/modes/interactive/interactive-model-routing.js +2 -4
  294. package/dist/modes/interactive/interactive-model-routing.js.map +1 -1
  295. package/dist/modes/interactive/interactive-render-chat.d.ts.map +1 -1
  296. package/dist/modes/interactive/interactive-render-chat.js +4 -3
  297. package/dist/modes/interactive/interactive-render-chat.js.map +1 -1
  298. package/dist/modes/interactive/interactive-session-runtime.d.ts.map +1 -1
  299. package/dist/modes/interactive/interactive-session-runtime.js +5 -2
  300. package/dist/modes/interactive/interactive-session-runtime.js.map +1 -1
  301. package/dist/modes/interactive/interactive-startup.d.ts.map +1 -1
  302. package/dist/modes/interactive/interactive-startup.js +11 -1
  303. package/dist/modes/interactive/interactive-startup.js.map +1 -1
  304. package/dist/modes/rpc/rpc-client.d.ts +28 -51
  305. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  306. package/dist/modes/rpc/rpc-client.js +27 -51
  307. package/dist/modes/rpc/rpc-client.js.map +1 -1
  308. package/dist/modes/rpc/rpc-command-handler.d.ts.map +1 -1
  309. package/dist/modes/rpc/rpc-command-handler.js +19 -0
  310. package/dist/modes/rpc/rpc-command-handler.js.map +1 -1
  311. package/dist/modes/rpc/rpc-types.d.ts +26 -0
  312. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  313. package/dist/modes/rpc/rpc-types.js.map +1 -1
  314. package/dist/rpc-entry.d.ts +3 -0
  315. package/dist/rpc-entry.d.ts.map +1 -0
  316. package/dist/rpc-entry.js +12 -0
  317. package/dist/rpc-entry.js.map +1 -0
  318. package/dist/utils/image-convert.d.ts +1 -0
  319. package/dist/utils/image-convert.d.ts.map +1 -1
  320. package/dist/utils/image-convert.js +21 -15
  321. package/dist/utils/image-convert.js.map +1 -1
  322. package/dist/utils/image-process.d.ts +18 -0
  323. package/dist/utils/image-process.d.ts.map +1 -0
  324. package/dist/utils/image-process.js +83 -0
  325. package/dist/utils/image-process.js.map +1 -0
  326. package/dist/utils/mime.d.ts.map +1 -1
  327. package/dist/utils/mime.js +41 -0
  328. package/dist/utils/mime.js.map +1 -1
  329. package/dist/utils/module-require.d.ts +11 -0
  330. package/dist/utils/module-require.d.ts.map +1 -0
  331. package/dist/utils/module-require.js +16 -0
  332. package/dist/utils/module-require.js.map +1 -0
  333. package/docs/compaction.md +2 -0
  334. package/docs/development.md +10 -0
  335. package/docs/extensions.md +11 -0
  336. package/docs/models.md +3 -3
  337. package/docs/providers.md +2 -1
  338. package/docs/rpc.md +60 -2
  339. package/docs/sdk.md +1 -1
  340. package/docs/settings.md +4 -1
  341. package/docs/subagents.md +6 -0
  342. package/docs/tools.md +4 -2
  343. package/docs/workflows.md +4 -2
  344. package/npm-shrinkwrap.json +138 -171
  345. package/package.json +19 -12
@@ -20,6 +20,12 @@ export interface SessionStartEvent {
20
20
  /** Previously active session file. Present for "new", "resume", and "fork". */
21
21
  previousSessionFile?: string;
22
22
  }
23
+ /** Fired when the current session metadata changes. */
24
+ export interface SessionInfoChangedEvent {
25
+ type: "session_info_changed";
26
+ /** Current normalized session name. Undefined when the name is cleared. */
27
+ name: string | undefined;
28
+ }
23
29
  /** Fired before switching to another session (can be cancelled) */
24
30
  export interface SessionBeforeSwitchEvent {
25
31
  type: "session_before_switch";
@@ -85,5 +91,5 @@ export interface SessionTreeEvent {
85
91
  summaryEntry?: BranchSummaryEntry;
86
92
  fromExtension?: boolean;
87
93
  }
88
- export type SessionEvent = SessionStartEvent | SessionBeforeSwitchEvent | SessionBeforeForkEvent | SessionBeforeCompactEvent | SessionCompactEvent | SessionShutdownEvent | SessionBeforeTreeEvent | SessionTreeEvent;
94
+ export type SessionEvent = SessionStartEvent | SessionInfoChangedEvent | SessionBeforeSwitchEvent | SessionBeforeForkEvent | SessionBeforeCompactEvent | SessionCompactEvent | SessionShutdownEvent | SessionBeforeTreeEvent | SessionTreeEvent;
89
95
  //# sourceMappingURL=session-events.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"session-events.d.ts","sourceRoot":"","sources":["../../../src/core/extensions/session-events.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ContextCompactionPreparation, ContextCompactionResult } from \"../compaction/index.ts\";\nimport type { BranchSummaryEntry, ContextCompactionEntry, SessionEntry } from \"../session-manager.ts\";\n\n// ============================================================================\n// Resource Events\n// ============================================================================\n\n/** Fired after session_start to allow extensions to provide additional resource paths. */\nexport interface ResourcesDiscoverEvent {\n\ttype: \"resources_discover\";\n\tcwd: string;\n\treason: \"startup\" | \"reload\";\n}\n\n/** Result from resources_discover event handler */\nexport interface ResourcesDiscoverResult {\n\tskillPaths?: string[];\n\tpromptPaths?: string[];\n\tthemePaths?: string[];\n}\n\n// ============================================================================\n// Session Events\n// ============================================================================\n\n/** Fired when a session is started, loaded, or reloaded */\nexport interface SessionStartEvent {\n\ttype: \"session_start\";\n\t/** Why this session start happened. */\n\treason: \"startup\" | \"reload\" | \"new\" | \"resume\" | \"fork\";\n\t/** Previously active session file. Present for \"new\", \"resume\", and \"fork\". */\n\tpreviousSessionFile?: string;\n}\n\n/** Fired before switching to another session (can be cancelled) */\nexport interface SessionBeforeSwitchEvent {\n\ttype: \"session_before_switch\";\n\treason: \"new\" | \"resume\";\n\ttargetSessionFile?: string;\n}\n\n/** Fired before forking a session (can be cancelled) */\nexport interface SessionBeforeForkEvent {\n\ttype: \"session_before_fork\";\n\tentryId: string;\n\tposition: \"before\" | \"at\";\n}\n\n/** Fired before context compaction (can be cancelled or customized) */\nexport interface SessionBeforeCompactEvent {\n\ttype: \"session_before_compact\";\n\treason: \"manual\" | \"threshold\" | \"overflow\";\n\tparameters: ContextCompactionPreparation[\"parameters\"];\n\tpreparation: ContextCompactionPreparation;\n\tbranchEntries: SessionEntry[];\n\tsignal: AbortSignal;\n}\n\n/** Fired after context compaction */\nexport interface SessionCompactEvent {\n\ttype: \"session_compact\";\n\treason: \"manual\" | \"threshold\" | \"overflow\";\n\tparameters: ContextCompactionPreparation[\"parameters\"];\n\tresult: ContextCompactionResult;\n\tcontextCompactionEntry: ContextCompactionEntry;\n\tfromExtension: boolean;\n}\n\n/** Fired before an extension runtime is torn down due to quit, reload, or session replacement. */\nexport interface SessionShutdownEvent {\n\ttype: \"session_shutdown\";\n\treason: \"quit\" | \"reload\" | \"new\" | \"resume\" | \"fork\";\n\t/** Destination session file when shutting down due to session replacement. */\n\ttargetSessionFile?: string;\n}\n\n/** Preparation data for tree navigation */\nexport interface TreePreparation {\n\ttargetId: string;\n\toldLeafId: string | null;\n\tcommonAncestorId: string | null;\n\tentriesToSummarize: SessionEntry[];\n\tuserWantsSummary: boolean;\n\t/** Custom instructions for summarization */\n\tcustomInstructions?: string;\n\t/** If true, customInstructions replaces the default prompt instead of being appended */\n\treplaceInstructions?: boolean;\n\t/** Label to attach to the branch summary entry */\n\tlabel?: string;\n}\n\n/** Fired before navigating in the session tree (can be cancelled) */\nexport interface SessionBeforeTreeEvent {\n\ttype: \"session_before_tree\";\n\tpreparation: TreePreparation;\n\tsignal: AbortSignal;\n}\n\n/** Fired after navigating in the session tree */\nexport interface SessionTreeEvent {\n\ttype: \"session_tree\";\n\tnewLeafId: string | null;\n\toldLeafId: string | null;\n\tsummaryEntry?: BranchSummaryEntry;\n\tfromExtension?: boolean;\n}\n\nexport type SessionEvent =\n\t| SessionStartEvent\n\t| SessionBeforeSwitchEvent\n\t| SessionBeforeForkEvent\n\t| SessionBeforeCompactEvent\n\t| SessionCompactEvent\n\t| SessionShutdownEvent\n\t| SessionBeforeTreeEvent\n\t| SessionTreeEvent;\n"]}
1
+ {"version":3,"file":"session-events.d.ts","sourceRoot":"","sources":["../../../src/core/extensions/session-events.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ContextCompactionPreparation, ContextCompactionResult } from \"../compaction/index.ts\";\nimport type { BranchSummaryEntry, ContextCompactionEntry, SessionEntry } from \"../session-manager.ts\";\n\n// ============================================================================\n// Resource Events\n// ============================================================================\n\n/** Fired after session_start to allow extensions to provide additional resource paths. */\nexport interface ResourcesDiscoverEvent {\n\ttype: \"resources_discover\";\n\tcwd: string;\n\treason: \"startup\" | \"reload\";\n}\n\n/** Result from resources_discover event handler */\nexport interface ResourcesDiscoverResult {\n\tskillPaths?: string[];\n\tpromptPaths?: string[];\n\tthemePaths?: string[];\n}\n\n// ============================================================================\n// Session Events\n// ============================================================================\n\n/** Fired when a session is started, loaded, or reloaded */\nexport interface SessionStartEvent {\n\ttype: \"session_start\";\n\t/** Why this session start happened. */\n\treason: \"startup\" | \"reload\" | \"new\" | \"resume\" | \"fork\";\n\t/** Previously active session file. Present for \"new\", \"resume\", and \"fork\". */\n\tpreviousSessionFile?: string;\n}\n\n/** Fired when the current session metadata changes. */\nexport interface SessionInfoChangedEvent {\n\ttype: \"session_info_changed\";\n\t/** Current normalized session name. Undefined when the name is cleared. */\n\tname: string | undefined;\n}\n\n/** Fired before switching to another session (can be cancelled) */\nexport interface SessionBeforeSwitchEvent {\n\ttype: \"session_before_switch\";\n\treason: \"new\" | \"resume\";\n\ttargetSessionFile?: string;\n}\n\n/** Fired before forking a session (can be cancelled) */\nexport interface SessionBeforeForkEvent {\n\ttype: \"session_before_fork\";\n\tentryId: string;\n\tposition: \"before\" | \"at\";\n}\n\n/** Fired before context compaction (can be cancelled or customized) */\nexport interface SessionBeforeCompactEvent {\n\ttype: \"session_before_compact\";\n\treason: \"manual\" | \"threshold\" | \"overflow\";\n\tparameters: ContextCompactionPreparation[\"parameters\"];\n\tpreparation: ContextCompactionPreparation;\n\tbranchEntries: SessionEntry[];\n\tsignal: AbortSignal;\n}\n\n/** Fired after context compaction */\nexport interface SessionCompactEvent {\n\ttype: \"session_compact\";\n\treason: \"manual\" | \"threshold\" | \"overflow\";\n\tparameters: ContextCompactionPreparation[\"parameters\"];\n\tresult: ContextCompactionResult;\n\tcontextCompactionEntry: ContextCompactionEntry;\n\tfromExtension: boolean;\n}\n\n/** Fired before an extension runtime is torn down due to quit, reload, or session replacement. */\nexport interface SessionShutdownEvent {\n\ttype: \"session_shutdown\";\n\treason: \"quit\" | \"reload\" | \"new\" | \"resume\" | \"fork\";\n\t/** Destination session file when shutting down due to session replacement. */\n\ttargetSessionFile?: string;\n}\n\n/** Preparation data for tree navigation */\nexport interface TreePreparation {\n\ttargetId: string;\n\toldLeafId: string | null;\n\tcommonAncestorId: string | null;\n\tentriesToSummarize: SessionEntry[];\n\tuserWantsSummary: boolean;\n\t/** Custom instructions for summarization */\n\tcustomInstructions?: string;\n\t/** If true, customInstructions replaces the default prompt instead of being appended */\n\treplaceInstructions?: boolean;\n\t/** Label to attach to the branch summary entry */\n\tlabel?: string;\n}\n\n/** Fired before navigating in the session tree (can be cancelled) */\nexport interface SessionBeforeTreeEvent {\n\ttype: \"session_before_tree\";\n\tpreparation: TreePreparation;\n\tsignal: AbortSignal;\n}\n\n/** Fired after navigating in the session tree */\nexport interface SessionTreeEvent {\n\ttype: \"session_tree\";\n\tnewLeafId: string | null;\n\toldLeafId: string | null;\n\tsummaryEntry?: BranchSummaryEntry;\n\tfromExtension?: boolean;\n}\n\nexport type SessionEvent =\n\t| SessionStartEvent\n\t| SessionInfoChangedEvent\n\t| SessionBeforeSwitchEvent\n\t| SessionBeforeForkEvent\n\t| SessionBeforeCompactEvent\n\t| SessionCompactEvent\n\t| SessionShutdownEvent\n\t| SessionBeforeTreeEvent\n\t| SessionTreeEvent;\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"session-events.js","sourceRoot":"","sources":["../../../src/core/extensions/session-events.ts"],"names":[],"mappings":"","sourcesContent":["import type { ContextCompactionPreparation, ContextCompactionResult } from \"../compaction/index.ts\";\nimport type { BranchSummaryEntry, ContextCompactionEntry, SessionEntry } from \"../session-manager.ts\";\n\n// ============================================================================\n// Resource Events\n// ============================================================================\n\n/** Fired after session_start to allow extensions to provide additional resource paths. */\nexport interface ResourcesDiscoverEvent {\n\ttype: \"resources_discover\";\n\tcwd: string;\n\treason: \"startup\" | \"reload\";\n}\n\n/** Result from resources_discover event handler */\nexport interface ResourcesDiscoverResult {\n\tskillPaths?: string[];\n\tpromptPaths?: string[];\n\tthemePaths?: string[];\n}\n\n// ============================================================================\n// Session Events\n// ============================================================================\n\n/** Fired when a session is started, loaded, or reloaded */\nexport interface SessionStartEvent {\n\ttype: \"session_start\";\n\t/** Why this session start happened. */\n\treason: \"startup\" | \"reload\" | \"new\" | \"resume\" | \"fork\";\n\t/** Previously active session file. Present for \"new\", \"resume\", and \"fork\". */\n\tpreviousSessionFile?: string;\n}\n\n/** Fired before switching to another session (can be cancelled) */\nexport interface SessionBeforeSwitchEvent {\n\ttype: \"session_before_switch\";\n\treason: \"new\" | \"resume\";\n\ttargetSessionFile?: string;\n}\n\n/** Fired before forking a session (can be cancelled) */\nexport interface SessionBeforeForkEvent {\n\ttype: \"session_before_fork\";\n\tentryId: string;\n\tposition: \"before\" | \"at\";\n}\n\n/** Fired before context compaction (can be cancelled or customized) */\nexport interface SessionBeforeCompactEvent {\n\ttype: \"session_before_compact\";\n\treason: \"manual\" | \"threshold\" | \"overflow\";\n\tparameters: ContextCompactionPreparation[\"parameters\"];\n\tpreparation: ContextCompactionPreparation;\n\tbranchEntries: SessionEntry[];\n\tsignal: AbortSignal;\n}\n\n/** Fired after context compaction */\nexport interface SessionCompactEvent {\n\ttype: \"session_compact\";\n\treason: \"manual\" | \"threshold\" | \"overflow\";\n\tparameters: ContextCompactionPreparation[\"parameters\"];\n\tresult: ContextCompactionResult;\n\tcontextCompactionEntry: ContextCompactionEntry;\n\tfromExtension: boolean;\n}\n\n/** Fired before an extension runtime is torn down due to quit, reload, or session replacement. */\nexport interface SessionShutdownEvent {\n\ttype: \"session_shutdown\";\n\treason: \"quit\" | \"reload\" | \"new\" | \"resume\" | \"fork\";\n\t/** Destination session file when shutting down due to session replacement. */\n\ttargetSessionFile?: string;\n}\n\n/** Preparation data for tree navigation */\nexport interface TreePreparation {\n\ttargetId: string;\n\toldLeafId: string | null;\n\tcommonAncestorId: string | null;\n\tentriesToSummarize: SessionEntry[];\n\tuserWantsSummary: boolean;\n\t/** Custom instructions for summarization */\n\tcustomInstructions?: string;\n\t/** If true, customInstructions replaces the default prompt instead of being appended */\n\treplaceInstructions?: boolean;\n\t/** Label to attach to the branch summary entry */\n\tlabel?: string;\n}\n\n/** Fired before navigating in the session tree (can be cancelled) */\nexport interface SessionBeforeTreeEvent {\n\ttype: \"session_before_tree\";\n\tpreparation: TreePreparation;\n\tsignal: AbortSignal;\n}\n\n/** Fired after navigating in the session tree */\nexport interface SessionTreeEvent {\n\ttype: \"session_tree\";\n\tnewLeafId: string | null;\n\toldLeafId: string | null;\n\tsummaryEntry?: BranchSummaryEntry;\n\tfromExtension?: boolean;\n}\n\nexport type SessionEvent =\n\t| SessionStartEvent\n\t| SessionBeforeSwitchEvent\n\t| SessionBeforeForkEvent\n\t| SessionBeforeCompactEvent\n\t| SessionCompactEvent\n\t| SessionShutdownEvent\n\t| SessionBeforeTreeEvent\n\t| SessionTreeEvent;\n"]}
1
+ {"version":3,"file":"session-events.js","sourceRoot":"","sources":["../../../src/core/extensions/session-events.ts"],"names":[],"mappings":"","sourcesContent":["import type { ContextCompactionPreparation, ContextCompactionResult } from \"../compaction/index.ts\";\nimport type { BranchSummaryEntry, ContextCompactionEntry, SessionEntry } from \"../session-manager.ts\";\n\n// ============================================================================\n// Resource Events\n// ============================================================================\n\n/** Fired after session_start to allow extensions to provide additional resource paths. */\nexport interface ResourcesDiscoverEvent {\n\ttype: \"resources_discover\";\n\tcwd: string;\n\treason: \"startup\" | \"reload\";\n}\n\n/** Result from resources_discover event handler */\nexport interface ResourcesDiscoverResult {\n\tskillPaths?: string[];\n\tpromptPaths?: string[];\n\tthemePaths?: string[];\n}\n\n// ============================================================================\n// Session Events\n// ============================================================================\n\n/** Fired when a session is started, loaded, or reloaded */\nexport interface SessionStartEvent {\n\ttype: \"session_start\";\n\t/** Why this session start happened. */\n\treason: \"startup\" | \"reload\" | \"new\" | \"resume\" | \"fork\";\n\t/** Previously active session file. Present for \"new\", \"resume\", and \"fork\". */\n\tpreviousSessionFile?: string;\n}\n\n/** Fired when the current session metadata changes. */\nexport interface SessionInfoChangedEvent {\n\ttype: \"session_info_changed\";\n\t/** Current normalized session name. Undefined when the name is cleared. */\n\tname: string | undefined;\n}\n\n/** Fired before switching to another session (can be cancelled) */\nexport interface SessionBeforeSwitchEvent {\n\ttype: \"session_before_switch\";\n\treason: \"new\" | \"resume\";\n\ttargetSessionFile?: string;\n}\n\n/** Fired before forking a session (can be cancelled) */\nexport interface SessionBeforeForkEvent {\n\ttype: \"session_before_fork\";\n\tentryId: string;\n\tposition: \"before\" | \"at\";\n}\n\n/** Fired before context compaction (can be cancelled or customized) */\nexport interface SessionBeforeCompactEvent {\n\ttype: \"session_before_compact\";\n\treason: \"manual\" | \"threshold\" | \"overflow\";\n\tparameters: ContextCompactionPreparation[\"parameters\"];\n\tpreparation: ContextCompactionPreparation;\n\tbranchEntries: SessionEntry[];\n\tsignal: AbortSignal;\n}\n\n/** Fired after context compaction */\nexport interface SessionCompactEvent {\n\ttype: \"session_compact\";\n\treason: \"manual\" | \"threshold\" | \"overflow\";\n\tparameters: ContextCompactionPreparation[\"parameters\"];\n\tresult: ContextCompactionResult;\n\tcontextCompactionEntry: ContextCompactionEntry;\n\tfromExtension: boolean;\n}\n\n/** Fired before an extension runtime is torn down due to quit, reload, or session replacement. */\nexport interface SessionShutdownEvent {\n\ttype: \"session_shutdown\";\n\treason: \"quit\" | \"reload\" | \"new\" | \"resume\" | \"fork\";\n\t/** Destination session file when shutting down due to session replacement. */\n\ttargetSessionFile?: string;\n}\n\n/** Preparation data for tree navigation */\nexport interface TreePreparation {\n\ttargetId: string;\n\toldLeafId: string | null;\n\tcommonAncestorId: string | null;\n\tentriesToSummarize: SessionEntry[];\n\tuserWantsSummary: boolean;\n\t/** Custom instructions for summarization */\n\tcustomInstructions?: string;\n\t/** If true, customInstructions replaces the default prompt instead of being appended */\n\treplaceInstructions?: boolean;\n\t/** Label to attach to the branch summary entry */\n\tlabel?: string;\n}\n\n/** Fired before navigating in the session tree (can be cancelled) */\nexport interface SessionBeforeTreeEvent {\n\ttype: \"session_before_tree\";\n\tpreparation: TreePreparation;\n\tsignal: AbortSignal;\n}\n\n/** Fired after navigating in the session tree */\nexport interface SessionTreeEvent {\n\ttype: \"session_tree\";\n\tnewLeafId: string | null;\n\toldLeafId: string | null;\n\tsummaryEntry?: BranchSummaryEntry;\n\tfromExtension?: boolean;\n}\n\nexport type SessionEvent =\n\t| SessionStartEvent\n\t| SessionInfoChangedEvent\n\t| SessionBeforeSwitchEvent\n\t| SessionBeforeForkEvent\n\t| SessionBeforeCompactEvent\n\t| SessionCompactEvent\n\t| SessionShutdownEvent\n\t| SessionBeforeTreeEvent\n\t| SessionTreeEvent;\n"]}
@@ -1,3 +1,4 @@
1
+ import * as undici from "undici";
1
2
  export declare const DEFAULT_HTTP_IDLE_TIMEOUT_MS = 600000;
2
3
  export declare const HTTP_IDLE_TIMEOUT_CHOICES: readonly [{
3
4
  readonly label: "30 sec";
@@ -20,6 +21,7 @@ export declare const HTTP_IDLE_TIMEOUT_CHOICES: readonly [{
20
21
  }];
21
22
  export declare function parseHttpIdleTimeoutMs(value: unknown): number | undefined;
22
23
  export declare function formatHttpIdleTimeoutMs(timeoutMs: number): string;
24
+ export declare function createHttpDispatcherOptions(timeoutMs: number): ConstructorParameters<typeof undici.EnvHttpProxyAgent>[0];
23
25
  /**
24
26
  * Configure the global undici dispatcher used by fetch and SDK HTTP clients.
25
27
  *
@@ -1 +1 @@
1
- {"version":3,"file":"http-dispatcher.d.ts","sourceRoot":"","sources":["../../src/core/http-dispatcher.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,4BAA4B,SAAU,CAAC;AAKpD,eAAO,MAAM,yBAAyB;aACnC,KAAK,EAAE,QAAQ;aAAE,SAAS,EAAE,KAAM;;aAClC,KAAK,EAAE,OAAO;aAAE,SAAS,EAAE,KAAM;;aACjC,KAAK,EAAE,OAAO;aAAE,SAAS,EAAE,MAAO;;aAClC,KAAK,EAAE,QAAQ;aAAE,SAAS,EAAE,MAAO;;aACnC,KAAK,EAAE,QAAQ;aAAE,SAAS,EAAE,OAAS;;aACrC,KAAK,EAAE,UAAU;aAAE,SAAS,EAAE,CAAC;EACxB,CAAC;AAEX,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAKzE;AAED,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAMjE;AAED;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CAAC,SAAS,GAAE,MAAqC,GAAG,IAAI,CA+B9F","sourcesContent":["import * as undici from \"undici\";\nimport { installCopilotGeminiReasoningInterceptor } from \"./copilot-gemini-reasoning.ts\";\n\nexport const DEFAULT_HTTP_IDLE_TIMEOUT_MS = 600_000;\n\nconst originalGlobalFetch = globalThis.fetch;\nlet installedGlobalFetch: typeof globalThis.fetch | undefined;\n\nexport const HTTP_IDLE_TIMEOUT_CHOICES = [\n\t{ label: \"30 sec\", timeoutMs: 30_000 },\n\t{ label: \"1 min\", timeoutMs: 60_000 },\n\t{ label: \"5 min\", timeoutMs: 300_000 },\n\t{ label: \"10 min\", timeoutMs: 600_000 },\n\t{ label: \"30 min\", timeoutMs: 1_800_000 },\n\t{ label: \"Disabled\", timeoutMs: 0 },\n] as const;\n\nexport function parseHttpIdleTimeoutMs(value: unknown): number | undefined {\n\tif (typeof value !== \"number\" || !Number.isFinite(value) || value < 0) {\n\t\treturn undefined;\n\t}\n\treturn Math.floor(value);\n}\n\nexport function formatHttpIdleTimeoutMs(timeoutMs: number): string {\n\tconst choice = HTTP_IDLE_TIMEOUT_CHOICES.find((item) => item.timeoutMs === timeoutMs);\n\tif (choice) {\n\t\treturn choice.label;\n\t}\n\treturn `${timeoutMs / 1000} sec`;\n}\n\n/**\n * Configure the global undici dispatcher used by fetch and SDK HTTP clients.\n *\n * Keep HTTP/2 disabled for now because some Node/undici combinations have\n * produced stream-reset crashes, and use a configurable idle timeout so stale\n * connections are eventually reclaimed while long-running requests remain\n * supported. Do not install a fixed connect-phase timeout here: under Pier and\n * other policy/proxy layers, CONNECT establishment can be slower than normal\n * internet egress and should surface through the provider/agent retry path.\n */\nexport function configureHttpDispatcher(timeoutMs: number = DEFAULT_HTTP_IDLE_TIMEOUT_MS): void {\n\tconst normalizedTimeoutMs = parseHttpIdleTimeoutMs(timeoutMs);\n\tif (normalizedTimeoutMs === undefined) {\n\t\tthrow new Error(`Invalid HTTP idle timeout: ${String(timeoutMs)}`);\n\t}\n\n\tundici.setGlobalDispatcher(\n\t\tnew undici.EnvHttpProxyAgent({\n\t\t\tallowH2: false,\n\t\t\tbodyTimeout: normalizedTimeoutMs,\n\t\t\theadersTimeout: normalizedTimeoutMs,\n\t\t}),\n\t);\n\n\t// Keep fetch and the dispatcher on the same undici implementation. Some Node\n\t// releases use a bundled fetch that can ignore the npm undici dispatcher or\n\t// otherwise behave differently from the configured dispatcher used by SDKs.\n\t// If a caller replaced fetch after module load, preserve that deliberate\n\t// override.\n\tconst shouldInstallGlobals = installedGlobalFetch === undefined\n\t\t? globalThis.fetch === originalGlobalFetch\n\t\t: globalThis.fetch === installedGlobalFetch;\n\tif (shouldInstallGlobals) {\n\t\tundici.install?.();\n\t\tinstalledGlobalFetch = globalThis.fetch;\n\t}\n\n\t// Bridge CAPI Gemini thought signatures (`reasoning_opaque`) on the inbound\n\t// SSE stream so multi-turn Copilot Gemini tool use does not stall on empty\n\t// completions. Idempotent and scoped to `*.githubcopilot.com` event streams.\n\tinstallCopilotGeminiReasoningInterceptor();\n}\n"]}
1
+ {"version":3,"file":"http-dispatcher.d.ts","sourceRoot":"","sources":["../../src/core/http-dispatcher.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AAGjC,eAAO,MAAM,4BAA4B,SAAU,CAAC;AAKpD,eAAO,MAAM,yBAAyB;aACnC,KAAK,EAAE,QAAQ;aAAE,SAAS,EAAE,KAAM;;aAClC,KAAK,EAAE,OAAO;aAAE,SAAS,EAAE,KAAM;;aACjC,KAAK,EAAE,OAAO;aAAE,SAAS,EAAE,MAAO;;aAClC,KAAK,EAAE,QAAQ;aAAE,SAAS,EAAE,MAAO;;aACnC,KAAK,EAAE,QAAQ;aAAE,SAAS,EAAE,OAAS;;aACrC,KAAK,EAAE,UAAU;aAAE,SAAS,EAAE,CAAC;EACxB,CAAC;AAEX,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAKzE;AAED,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAMjE;AAED,wBAAgB,2BAA2B,CAAC,SAAS,EAAE,MAAM,GAAG,qBAAqB,CAAC,OAAO,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAWxH;AA+BD;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CAAC,SAAS,GAAE,MAAqC,GAAG,IAAI,CA4B9F","sourcesContent":["import { EventEmitter } from \"node:events\";\nimport * as undici from \"undici\";\nimport { installCopilotGeminiReasoningInterceptor } from \"./copilot-gemini-reasoning.ts\";\n\nexport const DEFAULT_HTTP_IDLE_TIMEOUT_MS = 600_000;\n\nconst originalGlobalFetch = globalThis.fetch;\nlet installedGlobalFetch: typeof globalThis.fetch | undefined;\n\nexport const HTTP_IDLE_TIMEOUT_CHOICES = [\n\t{ label: \"30 sec\", timeoutMs: 30_000 },\n\t{ label: \"1 min\", timeoutMs: 60_000 },\n\t{ label: \"5 min\", timeoutMs: 300_000 },\n\t{ label: \"10 min\", timeoutMs: 600_000 },\n\t{ label: \"30 min\", timeoutMs: 1_800_000 },\n\t{ label: \"Disabled\", timeoutMs: 0 },\n] as const;\n\nexport function parseHttpIdleTimeoutMs(value: unknown): number | undefined {\n\tif (typeof value !== \"number\" || !Number.isFinite(value) || value < 0) {\n\t\treturn undefined;\n\t}\n\treturn Math.floor(value);\n}\n\nexport function formatHttpIdleTimeoutMs(timeoutMs: number): string {\n\tconst choice = HTTP_IDLE_TIMEOUT_CHOICES.find((item) => item.timeoutMs === timeoutMs);\n\tif (choice) {\n\t\treturn choice.label;\n\t}\n\treturn `${timeoutMs / 1000} sec`;\n}\n\nexport function createHttpDispatcherOptions(timeoutMs: number): ConstructorParameters<typeof undici.EnvHttpProxyAgent>[0] {\n\treturn {\n\t\tallowH2: false,\n\t\t// Undici defaults to a 10s connect timeout; disable it so slow\n\t\t// policy/proxy CONNECT establishment follows provider retry handling.\n\t\tconnectTimeout: 0,\n\t\tbodyTimeout: timeoutMs,\n\t\theadersTimeout: timeoutMs,\n\t\tclientFactory: createUndiciClient,\n\t\tfactory: createUndiciOriginDispatcher,\n\t};\n}\n\nconst ignoreUndiciDispatcherError = (_error: unknown): void => {};\n\n// Undici can emit an internal Client \"error\" while terminating a mid-stream\n// fetch body. The body stream still rejects through reader.read(); this listener\n// only prevents EventEmitter's unhandled \"error\" special case from crashing.\nfunction withUndiciErrorListener<T extends undici.Dispatcher>(dispatcher: T): T {\n\tif (dispatcher instanceof EventEmitter) {\n\t\tEventEmitter.prototype.on.call(dispatcher, \"error\", ignoreUndiciDispatcherError);\n\t}\n\treturn dispatcher;\n}\n\nfunction createUndiciClient(origin: string | URL, options: object): undici.Dispatcher {\n\treturn withUndiciErrorListener(new undici.Client(origin, options as undici.Client.Options));\n}\n\nfunction createUndiciOriginDispatcher(origin: string | URL, options: object): undici.Dispatcher {\n\tconst dispatcherOptions = options as undici.Pool.Options;\n\tif (dispatcherOptions.connections === 1) {\n\t\treturn createUndiciClient(origin, dispatcherOptions);\n\t}\n\treturn withUndiciErrorListener(\n\t\tnew undici.Pool(origin, {\n\t\t\t...dispatcherOptions,\n\t\t\tfactory: createUndiciClient,\n\t\t}),\n\t);\n}\n\n/**\n * Configure the global undici dispatcher used by fetch and SDK HTTP clients.\n *\n * Keep HTTP/2 disabled for now because some Node/undici combinations have\n * produced stream-reset crashes, and use a configurable idle timeout so stale\n * connections are eventually reclaimed while long-running requests remain\n * supported. Do not install a fixed connect-phase timeout here: under Pier and\n * other policy/proxy layers, CONNECT establishment can be slower than normal\n * internet egress and should surface through the provider/agent retry path.\n */\nexport function configureHttpDispatcher(timeoutMs: number = DEFAULT_HTTP_IDLE_TIMEOUT_MS): void {\n\tconst normalizedTimeoutMs = parseHttpIdleTimeoutMs(timeoutMs);\n\tif (normalizedTimeoutMs === undefined) {\n\t\tthrow new Error(`Invalid HTTP idle timeout: ${String(timeoutMs)}`);\n\t}\n\n\tconst dispatcher = withUndiciErrorListener(\n\t\tnew undici.EnvHttpProxyAgent(createHttpDispatcherOptions(normalizedTimeoutMs)),\n\t);\n\tundici.setGlobalDispatcher(dispatcher);\n\n\t// Keep fetch and the dispatcher on the same undici implementation. Some Node\n\t// releases use a bundled fetch that can ignore the npm undici dispatcher or\n\t// otherwise behave differently from the configured dispatcher used by SDKs.\n\t// If a caller replaced fetch after module load, preserve that deliberate\n\t// override.\n\tconst shouldInstallGlobals = installedGlobalFetch === undefined\n\t\t? globalThis.fetch === originalGlobalFetch\n\t\t: globalThis.fetch === installedGlobalFetch;\n\tif (shouldInstallGlobals) {\n\t\tundici.install?.();\n\t\tinstalledGlobalFetch = globalThis.fetch;\n\t}\n\n\t// Bridge CAPI Gemini thought signatures (`reasoning_opaque`) on the inbound\n\t// SSE stream so multi-turn Copilot Gemini tool use does not stall on empty\n\t// completions. Idempotent and scoped to `*.githubcopilot.com` event streams.\n\tinstallCopilotGeminiReasoningInterceptor();\n}\n"]}
@@ -1,3 +1,4 @@
1
+ import { EventEmitter } from "node:events";
1
2
  import * as undici from "undici";
2
3
  import { installCopilotGeminiReasoningInterceptor } from "./copilot-gemini-reasoning.js";
3
4
  export const DEFAULT_HTTP_IDLE_TIMEOUT_MS = 600_000;
@@ -24,6 +25,41 @@ export function formatHttpIdleTimeoutMs(timeoutMs) {
24
25
  }
25
26
  return `${timeoutMs / 1000} sec`;
26
27
  }
28
+ export function createHttpDispatcherOptions(timeoutMs) {
29
+ return {
30
+ allowH2: false,
31
+ // Undici defaults to a 10s connect timeout; disable it so slow
32
+ // policy/proxy CONNECT establishment follows provider retry handling.
33
+ connectTimeout: 0,
34
+ bodyTimeout: timeoutMs,
35
+ headersTimeout: timeoutMs,
36
+ clientFactory: createUndiciClient,
37
+ factory: createUndiciOriginDispatcher,
38
+ };
39
+ }
40
+ const ignoreUndiciDispatcherError = (_error) => { };
41
+ // Undici can emit an internal Client "error" while terminating a mid-stream
42
+ // fetch body. The body stream still rejects through reader.read(); this listener
43
+ // only prevents EventEmitter's unhandled "error" special case from crashing.
44
+ function withUndiciErrorListener(dispatcher) {
45
+ if (dispatcher instanceof EventEmitter) {
46
+ EventEmitter.prototype.on.call(dispatcher, "error", ignoreUndiciDispatcherError);
47
+ }
48
+ return dispatcher;
49
+ }
50
+ function createUndiciClient(origin, options) {
51
+ return withUndiciErrorListener(new undici.Client(origin, options));
52
+ }
53
+ function createUndiciOriginDispatcher(origin, options) {
54
+ const dispatcherOptions = options;
55
+ if (dispatcherOptions.connections === 1) {
56
+ return createUndiciClient(origin, dispatcherOptions);
57
+ }
58
+ return withUndiciErrorListener(new undici.Pool(origin, {
59
+ ...dispatcherOptions,
60
+ factory: createUndiciClient,
61
+ }));
62
+ }
27
63
  /**
28
64
  * Configure the global undici dispatcher used by fetch and SDK HTTP clients.
29
65
  *
@@ -39,11 +75,8 @@ export function configureHttpDispatcher(timeoutMs = DEFAULT_HTTP_IDLE_TIMEOUT_MS
39
75
  if (normalizedTimeoutMs === undefined) {
40
76
  throw new Error(`Invalid HTTP idle timeout: ${String(timeoutMs)}`);
41
77
  }
42
- undici.setGlobalDispatcher(new undici.EnvHttpProxyAgent({
43
- allowH2: false,
44
- bodyTimeout: normalizedTimeoutMs,
45
- headersTimeout: normalizedTimeoutMs,
46
- }));
78
+ const dispatcher = withUndiciErrorListener(new undici.EnvHttpProxyAgent(createHttpDispatcherOptions(normalizedTimeoutMs)));
79
+ undici.setGlobalDispatcher(dispatcher);
47
80
  // Keep fetch and the dispatcher on the same undici implementation. Some Node
48
81
  // releases use a bundled fetch that can ignore the npm undici dispatcher or
49
82
  // otherwise behave differently from the configured dispatcher used by SDKs.
@@ -1 +1 @@
1
- {"version":3,"file":"http-dispatcher.js","sourceRoot":"","sources":["../../src/core/http-dispatcher.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AACjC,OAAO,EAAE,wCAAwC,EAAE,MAAM,+BAA+B,CAAC;AAEzF,MAAM,CAAC,MAAM,4BAA4B,GAAG,OAAO,CAAC;AAEpD,MAAM,mBAAmB,GAAG,UAAU,CAAC,KAAK,CAAC;AAC7C,IAAI,oBAAyD,CAAC;AAE9D,MAAM,CAAC,MAAM,yBAAyB,GAAG;IACxC,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE;IACtC,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE;IACrC,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE;IACtC,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE;IACvC,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE;IACzC,EAAE,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC,EAAE;CAC1B,CAAC;AAEX,MAAM,UAAU,sBAAsB,CAAC,KAAc;IACpD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QACvE,OAAO,SAAS,CAAC;IAClB,CAAC;IACD,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,SAAiB;IACxD,MAAM,MAAM,GAAG,yBAAyB,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC;IACtF,IAAI,MAAM,EAAE,CAAC;QACZ,OAAO,MAAM,CAAC,KAAK,CAAC;IACrB,CAAC;IACD,OAAO,GAAG,SAAS,GAAG,IAAI,MAAM,CAAC;AAClC,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,uBAAuB,CAAC,SAAS,GAAW,4BAA4B;IACvF,MAAM,mBAAmB,GAAG,sBAAsB,CAAC,SAAS,CAAC,CAAC;IAC9D,IAAI,mBAAmB,KAAK,SAAS,EAAE,CAAC;QACvC,MAAM,IAAI,KAAK,CAAC,8BAA8B,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;IACpE,CAAC;IAED,MAAM,CAAC,mBAAmB,CACzB,IAAI,MAAM,CAAC,iBAAiB,CAAC;QAC5B,OAAO,EAAE,KAAK;QACd,WAAW,EAAE,mBAAmB;QAChC,cAAc,EAAE,mBAAmB;KACnC,CAAC,CACF,CAAC;IAEF,6EAA6E;IAC7E,4EAA4E;IAC5E,4EAA4E;IAC5E,yEAAyE;IACzE,YAAY;IACZ,MAAM,oBAAoB,GAAG,oBAAoB,KAAK,SAAS;QAC9D,CAAC,CAAC,UAAU,CAAC,KAAK,KAAK,mBAAmB;QAC1C,CAAC,CAAC,UAAU,CAAC,KAAK,KAAK,oBAAoB,CAAC;IAC7C,IAAI,oBAAoB,EAAE,CAAC;QAC1B,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC;QACnB,oBAAoB,GAAG,UAAU,CAAC,KAAK,CAAC;IACzC,CAAC;IAED,4EAA4E;IAC5E,2EAA2E;IAC3E,6EAA6E;IAC7E,wCAAwC,EAAE,CAAC;AAC5C,CAAC","sourcesContent":["import * as undici from \"undici\";\nimport { installCopilotGeminiReasoningInterceptor } from \"./copilot-gemini-reasoning.ts\";\n\nexport const DEFAULT_HTTP_IDLE_TIMEOUT_MS = 600_000;\n\nconst originalGlobalFetch = globalThis.fetch;\nlet installedGlobalFetch: typeof globalThis.fetch | undefined;\n\nexport const HTTP_IDLE_TIMEOUT_CHOICES = [\n\t{ label: \"30 sec\", timeoutMs: 30_000 },\n\t{ label: \"1 min\", timeoutMs: 60_000 },\n\t{ label: \"5 min\", timeoutMs: 300_000 },\n\t{ label: \"10 min\", timeoutMs: 600_000 },\n\t{ label: \"30 min\", timeoutMs: 1_800_000 },\n\t{ label: \"Disabled\", timeoutMs: 0 },\n] as const;\n\nexport function parseHttpIdleTimeoutMs(value: unknown): number | undefined {\n\tif (typeof value !== \"number\" || !Number.isFinite(value) || value < 0) {\n\t\treturn undefined;\n\t}\n\treturn Math.floor(value);\n}\n\nexport function formatHttpIdleTimeoutMs(timeoutMs: number): string {\n\tconst choice = HTTP_IDLE_TIMEOUT_CHOICES.find((item) => item.timeoutMs === timeoutMs);\n\tif (choice) {\n\t\treturn choice.label;\n\t}\n\treturn `${timeoutMs / 1000} sec`;\n}\n\n/**\n * Configure the global undici dispatcher used by fetch and SDK HTTP clients.\n *\n * Keep HTTP/2 disabled for now because some Node/undici combinations have\n * produced stream-reset crashes, and use a configurable idle timeout so stale\n * connections are eventually reclaimed while long-running requests remain\n * supported. Do not install a fixed connect-phase timeout here: under Pier and\n * other policy/proxy layers, CONNECT establishment can be slower than normal\n * internet egress and should surface through the provider/agent retry path.\n */\nexport function configureHttpDispatcher(timeoutMs: number = DEFAULT_HTTP_IDLE_TIMEOUT_MS): void {\n\tconst normalizedTimeoutMs = parseHttpIdleTimeoutMs(timeoutMs);\n\tif (normalizedTimeoutMs === undefined) {\n\t\tthrow new Error(`Invalid HTTP idle timeout: ${String(timeoutMs)}`);\n\t}\n\n\tundici.setGlobalDispatcher(\n\t\tnew undici.EnvHttpProxyAgent({\n\t\t\tallowH2: false,\n\t\t\tbodyTimeout: normalizedTimeoutMs,\n\t\t\theadersTimeout: normalizedTimeoutMs,\n\t\t}),\n\t);\n\n\t// Keep fetch and the dispatcher on the same undici implementation. Some Node\n\t// releases use a bundled fetch that can ignore the npm undici dispatcher or\n\t// otherwise behave differently from the configured dispatcher used by SDKs.\n\t// If a caller replaced fetch after module load, preserve that deliberate\n\t// override.\n\tconst shouldInstallGlobals = installedGlobalFetch === undefined\n\t\t? globalThis.fetch === originalGlobalFetch\n\t\t: globalThis.fetch === installedGlobalFetch;\n\tif (shouldInstallGlobals) {\n\t\tundici.install?.();\n\t\tinstalledGlobalFetch = globalThis.fetch;\n\t}\n\n\t// Bridge CAPI Gemini thought signatures (`reasoning_opaque`) on the inbound\n\t// SSE stream so multi-turn Copilot Gemini tool use does not stall on empty\n\t// completions. Idempotent and scoped to `*.githubcopilot.com` event streams.\n\tinstallCopilotGeminiReasoningInterceptor();\n}\n"]}
1
+ {"version":3,"file":"http-dispatcher.js","sourceRoot":"","sources":["../../src/core/http-dispatcher.ts"],"names":[],"mappings":"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","sourcesContent":["import { EventEmitter } from \"node:events\";\nimport * as undici from \"undici\";\nimport { installCopilotGeminiReasoningInterceptor } from \"./copilot-gemini-reasoning.ts\";\n\nexport const DEFAULT_HTTP_IDLE_TIMEOUT_MS = 600_000;\n\nconst originalGlobalFetch = globalThis.fetch;\nlet installedGlobalFetch: typeof globalThis.fetch | undefined;\n\nexport const HTTP_IDLE_TIMEOUT_CHOICES = [\n\t{ label: \"30 sec\", timeoutMs: 30_000 },\n\t{ label: \"1 min\", timeoutMs: 60_000 },\n\t{ label: \"5 min\", timeoutMs: 300_000 },\n\t{ label: \"10 min\", timeoutMs: 600_000 },\n\t{ label: \"30 min\", timeoutMs: 1_800_000 },\n\t{ label: \"Disabled\", timeoutMs: 0 },\n] as const;\n\nexport function parseHttpIdleTimeoutMs(value: unknown): number | undefined {\n\tif (typeof value !== \"number\" || !Number.isFinite(value) || value < 0) {\n\t\treturn undefined;\n\t}\n\treturn Math.floor(value);\n}\n\nexport function formatHttpIdleTimeoutMs(timeoutMs: number): string {\n\tconst choice = HTTP_IDLE_TIMEOUT_CHOICES.find((item) => item.timeoutMs === timeoutMs);\n\tif (choice) {\n\t\treturn choice.label;\n\t}\n\treturn `${timeoutMs / 1000} sec`;\n}\n\nexport function createHttpDispatcherOptions(timeoutMs: number): ConstructorParameters<typeof undici.EnvHttpProxyAgent>[0] {\n\treturn {\n\t\tallowH2: false,\n\t\t// Undici defaults to a 10s connect timeout; disable it so slow\n\t\t// policy/proxy CONNECT establishment follows provider retry handling.\n\t\tconnectTimeout: 0,\n\t\tbodyTimeout: timeoutMs,\n\t\theadersTimeout: timeoutMs,\n\t\tclientFactory: createUndiciClient,\n\t\tfactory: createUndiciOriginDispatcher,\n\t};\n}\n\nconst ignoreUndiciDispatcherError = (_error: unknown): void => {};\n\n// Undici can emit an internal Client \"error\" while terminating a mid-stream\n// fetch body. The body stream still rejects through reader.read(); this listener\n// only prevents EventEmitter's unhandled \"error\" special case from crashing.\nfunction withUndiciErrorListener<T extends undici.Dispatcher>(dispatcher: T): T {\n\tif (dispatcher instanceof EventEmitter) {\n\t\tEventEmitter.prototype.on.call(dispatcher, \"error\", ignoreUndiciDispatcherError);\n\t}\n\treturn dispatcher;\n}\n\nfunction createUndiciClient(origin: string | URL, options: object): undici.Dispatcher {\n\treturn withUndiciErrorListener(new undici.Client(origin, options as undici.Client.Options));\n}\n\nfunction createUndiciOriginDispatcher(origin: string | URL, options: object): undici.Dispatcher {\n\tconst dispatcherOptions = options as undici.Pool.Options;\n\tif (dispatcherOptions.connections === 1) {\n\t\treturn createUndiciClient(origin, dispatcherOptions);\n\t}\n\treturn withUndiciErrorListener(\n\t\tnew undici.Pool(origin, {\n\t\t\t...dispatcherOptions,\n\t\t\tfactory: createUndiciClient,\n\t\t}),\n\t);\n}\n\n/**\n * Configure the global undici dispatcher used by fetch and SDK HTTP clients.\n *\n * Keep HTTP/2 disabled for now because some Node/undici combinations have\n * produced stream-reset crashes, and use a configurable idle timeout so stale\n * connections are eventually reclaimed while long-running requests remain\n * supported. Do not install a fixed connect-phase timeout here: under Pier and\n * other policy/proxy layers, CONNECT establishment can be slower than normal\n * internet egress and should surface through the provider/agent retry path.\n */\nexport function configureHttpDispatcher(timeoutMs: number = DEFAULT_HTTP_IDLE_TIMEOUT_MS): void {\n\tconst normalizedTimeoutMs = parseHttpIdleTimeoutMs(timeoutMs);\n\tif (normalizedTimeoutMs === undefined) {\n\t\tthrow new Error(`Invalid HTTP idle timeout: ${String(timeoutMs)}`);\n\t}\n\n\tconst dispatcher = withUndiciErrorListener(\n\t\tnew undici.EnvHttpProxyAgent(createHttpDispatcherOptions(normalizedTimeoutMs)),\n\t);\n\tundici.setGlobalDispatcher(dispatcher);\n\n\t// Keep fetch and the dispatcher on the same undici implementation. Some Node\n\t// releases use a bundled fetch that can ignore the npm undici dispatcher or\n\t// otherwise behave differently from the configured dispatcher used by SDKs.\n\t// If a caller replaced fetch after module load, preserve that deliberate\n\t// override.\n\tconst shouldInstallGlobals = installedGlobalFetch === undefined\n\t\t? globalThis.fetch === originalGlobalFetch\n\t\t: globalThis.fetch === installedGlobalFetch;\n\tif (shouldInstallGlobals) {\n\t\tundici.install?.();\n\t\tinstalledGlobalFetch = globalThis.fetch;\n\t}\n\n\t// Bridge CAPI Gemini thought signatures (`reasoning_opaque`) on the inbound\n\t// SSE stream so multi-turn Copilot Gemini tool use does not stall on empty\n\t// completions. Idempotent and scoped to `*.githubcopilot.com` event streams.\n\tinstallCopilotGeminiReasoningInterceptor();\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"model-registry-builtins.d.ts","sourceRoot":"","sources":["../../src/core/model-registry-builtins.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,GAAG,EAIR,KAAK,KAAK,EAEV,MAAM,8BAA8B,CAAC;AAGtC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,KAAK,EAAkB,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAWlF,wBAAgB,iCAAiC,CAChD,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EACjB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,GACzC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAKpC;AAaD,wBAAgB,WAAW,CAC1B,UAAU,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,EAChC,cAAc,EAAE,aAAa,CAAC,QAAQ,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,GAC5D,KAAK,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,GAAG,SAAS,CAiClC;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,QAAQ,EAAE,aAAa,GAAG,KAAK,CAAC,GAAG,CAAC,CAgCzF;AAED,wBAAgB,iBAAiB,CAChC,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,EACxC,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC,GACrD,KAAK,CAAC,GAAG,CAAC,EAAE,CAsBd;AAED,wBAAgB,iBAAiB,CAAC,aAAa,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,EAAE,YAAY,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,KAAK,CAAC,GAAG,CAAC,EAAE,CAWvG","sourcesContent":["import {\n\ttype Api,\n\tgetModels,\n\tgetProviders,\n\ttype KnownProvider,\n\ttype Model,\n\ttype OpenAICompletionsCompat,\n} from \"@earendil-works/pi-ai/compat\";\nimport { normalizeContextWindowOptions, withContextWindowOptions } from \"./context-window.ts\";\nimport { getActiveCopilotModelCatalog } from \"./copilot-model-catalog.ts\";\nimport type { ModelOverride } from \"./model-registry-schemas.ts\";\nimport type { ProviderCompat, ProviderOverride } from \"./model-registry-types.ts\";\n\nconst GITHUB_COPILOT_API_VERSION_HEADER = \"X-GitHub-Api-Version\";\nconst GITHUB_COPILOT_API_VERSION = \"2026-06-01\";\n\nfunction hasHeader(headers: Record<string, string> | undefined, headerName: string): boolean {\n\tif (!headers) return false;\n\tconst normalizedHeaderName = headerName.toLowerCase();\n\treturn Object.keys(headers).some((key) => key.toLowerCase() === normalizedHeaderName);\n}\n\nexport function withGitHubCopilotApiVersionHeader(\n\tmodel: Model<Api>,\n\theaders: Record<string, string> | undefined,\n): Record<string, string> | undefined {\n\tif (model.provider !== \"github-copilot\" || hasHeader(headers, GITHUB_COPILOT_API_VERSION_HEADER)) {\n\t\treturn headers;\n\t}\n\treturn { ...(headers ?? {}), [GITHUB_COPILOT_API_VERSION_HEADER]: GITHUB_COPILOT_API_VERSION };\n}\n\nfunction withCopilotContextWindowOptions(model: Model<Api>): Model<Api> {\n\tif (model.provider !== \"github-copilot\") return model;\n\tconst context = getActiveCopilotModelCatalog().get(model.id);\n\tif (!context) return model;\n\tconst base = { ...model, contextWindow: context.contextWindow, maxInputTokens: context.maxInputTokens };\n\tif (context.contextWindowOptions && context.contextWindowOptions.length > 1) {\n\t\treturn withContextWindowOptions(base, context.contextWindowOptions);\n\t}\n\treturn base;\n}\n\nexport function mergeCompat(\n\tbaseCompat: Model<Api>[\"compat\"],\n\toverrideCompat: ModelOverride[\"compat\"] | Model<Api>[\"compat\"],\n): Model<Api>[\"compat\"] | undefined {\n\tif (!overrideCompat) return baseCompat;\n\n\tconst base = baseCompat as ProviderCompat | undefined;\n\tconst override = overrideCompat as ProviderCompat;\n\tconst merged = { ...base, ...override } as ProviderCompat;\n\n\tconst baseCompletions = base as OpenAICompletionsCompat | undefined;\n\tconst overrideCompletions = override as OpenAICompletionsCompat;\n\tconst mergedCompletions = merged as OpenAICompletionsCompat;\n\n\tif (baseCompletions?.openRouterRouting || overrideCompletions.openRouterRouting) {\n\t\tmergedCompletions.openRouterRouting = {\n\t\t\t...baseCompletions?.openRouterRouting,\n\t\t\t...overrideCompletions.openRouterRouting,\n\t\t};\n\t}\n\n\tif (baseCompletions?.vercelGatewayRouting || overrideCompletions.vercelGatewayRouting) {\n\t\tmergedCompletions.vercelGatewayRouting = {\n\t\t\t...baseCompletions?.vercelGatewayRouting,\n\t\t\t...overrideCompletions.vercelGatewayRouting,\n\t\t};\n\t}\n\n\tif (baseCompletions?.chatTemplateKwargs || overrideCompletions.chatTemplateKwargs) {\n\t\tmergedCompletions.chatTemplateKwargs = {\n\t\t\t...baseCompletions?.chatTemplateKwargs,\n\t\t\t...overrideCompletions.chatTemplateKwargs,\n\t\t};\n\t}\n\n\treturn merged as Model<Api>[\"compat\"];\n}\n\nexport function applyModelOverride(model: Model<Api>, override: ModelOverride): Model<Api> {\n\tconst result = { ...model };\n\n\tif (override.name !== undefined) result.name = override.name;\n\tif (override.reasoning !== undefined) result.reasoning = override.reasoning;\n\tif (override.thinkingLevelMap !== undefined) {\n\t\tresult.thinkingLevelMap = { ...model.thinkingLevelMap, ...override.thinkingLevelMap };\n\t}\n\tif (override.input !== undefined) result.input = override.input as (\"text\" | \"image\")[];\n\tif (override.contextWindow !== undefined) {\n\t\tresult.contextWindow = override.contextWindow;\n\t\tresult.defaultContextWindow = override.contextWindow;\n\t\tif (override.contextWindowOptions === undefined) {\n\t\t\tresult.contextWindowOptions = undefined;\n\t\t}\n\t}\n\tif (override.contextWindowOptions !== undefined) {\n\t\tresult.contextWindowOptions = normalizeContextWindowOptions(override.contextWindowOptions);\n\t}\n\tif (override.maxTokens !== undefined) result.maxTokens = override.maxTokens;\n\n\tif (override.cost) {\n\t\tresult.cost = {\n\t\t\tinput: override.cost.input ?? model.cost.input,\n\t\t\toutput: override.cost.output ?? model.cost.output,\n\t\t\tcacheRead: override.cost.cacheRead ?? model.cost.cacheRead,\n\t\t\tcacheWrite: override.cost.cacheWrite ?? model.cost.cacheWrite,\n\t\t};\n\t}\n\n\tresult.compat = mergeCompat(model.compat, override.compat);\n\treturn result;\n}\n\nexport function loadBuiltInModels(\n\toverrides: Map<string, ProviderOverride>,\n\tmodelOverrides: Map<string, Map<string, ModelOverride>>,\n): Model<Api>[] {\n\treturn getProviders().flatMap((provider) => {\n\t\tconst models = getModels(provider as KnownProvider) as Model<Api>[];\n\t\tconst providerOverride = overrides.get(provider);\n\t\tconst perModelOverrides = modelOverrides.get(provider);\n\n\t\treturn models.map((m) => {\n\t\t\tlet model = m;\n\n\t\t\tif (providerOverride) {\n\t\t\t\tmodel = {\n\t\t\t\t\t...model,\n\t\t\t\t\tbaseUrl: providerOverride.baseUrl ?? model.baseUrl,\n\t\t\t\t\tcompat: mergeCompat(model.compat, providerOverride.compat),\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tmodel = withCopilotContextWindowOptions(model);\n\t\t\tconst modelOverride = perModelOverrides?.get(m.id);\n\t\t\treturn modelOverride ? applyModelOverride(model, modelOverride) : model;\n\t\t});\n\t});\n}\n\nexport function mergeCustomModels(builtInModels: Model<Api>[], customModels: Model<Api>[]): Model<Api>[] {\n\tconst merged = [...builtInModels];\n\tfor (const customModel of customModels) {\n\t\tconst existingIndex = merged.findIndex((m) => m.provider === customModel.provider && m.id === customModel.id);\n\t\tif (existingIndex >= 0) {\n\t\t\tmerged[existingIndex] = customModel;\n\t\t} else {\n\t\t\tmerged.push(customModel);\n\t\t}\n\t}\n\treturn merged;\n}\n"]}
1
+ {"version":3,"file":"model-registry-builtins.d.ts","sourceRoot":"","sources":["../../src/core/model-registry-builtins.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,GAAG,EAIR,KAAK,KAAK,EAEV,MAAM,8BAA8B,CAAC;AAKtC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,KAAK,EAAkB,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAmBlF,wBAAgB,iCAAiC,CAChD,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EACjB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,GACzC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAKpC;AAmCD,wBAAgB,WAAW,CAC1B,UAAU,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,EAChC,cAAc,EAAE,aAAa,CAAC,QAAQ,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,GAC5D,KAAK,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,GAAG,SAAS,CAiClC;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,QAAQ,EAAE,aAAa,GAAG,KAAK,CAAC,GAAG,CAAC,CAgCzF;AAED,wBAAgB,iBAAiB,CAChC,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,EACxC,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC,GACrD,KAAK,CAAC,GAAG,CAAC,EAAE,CAsBd;AAED,wBAAgB,iBAAiB,CAAC,aAAa,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,EAAE,YAAY,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,KAAK,CAAC,GAAG,CAAC,EAAE,CAWvG","sourcesContent":["import {\n\ttype Api,\n\tgetModels,\n\tgetProviders,\n\ttype KnownProvider,\n\ttype Model,\n\ttype OpenAICompletionsCompat,\n} from \"@earendil-works/pi-ai/compat\";\nimport { normalizeContextWindowOptions, withContextWindowOptions } from \"./context-window.ts\";\nimport { copilotApiBaseUrlFromToken, copilotTokenFromEnvironment, DEFAULT_COPILOT_API_BASE_URL, getActiveCopilotModelCatalog } from \"./copilot-model-catalog.ts\";\nimport { copilotTemplateFromModels, copilotThinkingLevelMapFor, synthesizeCopilotCatalogModels } from \"./copilot-model-synthesis.ts\";\nimport { getStaticCopilotModelFallback } from \"./copilot-model-static-fallbacks.ts\";\nimport type { ModelOverride } from \"./model-registry-schemas.ts\";\nimport type { ProviderCompat, ProviderOverride } from \"./model-registry-types.ts\";\n\nconst GITHUB_COPILOT_API_VERSION_HEADER = \"X-GitHub-Api-Version\";\nconst GITHUB_COPILOT_API_VERSION = \"2026-06-01\";\n\nfunction withDynamicGitHubCopilotModels(provider: string, models: Model<Api>[]): Model<Api>[] {\n\tif (provider !== \"github-copilot\") return models;\n\tconst existingIds = new Set(models.map((model) => model.id));\n\tconst template = copilotTemplateFromModels(models);\n\tconst dynamicModels = synthesizeCopilotCatalogModels(getActiveCopilotModelCatalog(), existingIds, template);\n\treturn dynamicModels.length === 0 ? models : [...models, ...dynamicModels];\n}\n\nfunction hasHeader(headers: Record<string, string> | undefined, headerName: string): boolean {\n\tif (!headers) return false;\n\tconst normalizedHeaderName = headerName.toLowerCase();\n\treturn Object.keys(headers).some((key) => key.toLowerCase() === normalizedHeaderName);\n}\n\nexport function withGitHubCopilotApiVersionHeader(\n\tmodel: Model<Api>,\n\theaders: Record<string, string> | undefined,\n): Record<string, string> | undefined {\n\tif (model.provider !== \"github-copilot\" || hasHeader(headers, GITHUB_COPILOT_API_VERSION_HEADER)) {\n\t\treturn headers;\n\t}\n\treturn { ...(headers ?? {}), [GITHUB_COPILOT_API_VERSION_HEADER]: GITHUB_COPILOT_API_VERSION };\n}\n\nfunction withCopilotEnvironmentBaseUrl(model: Model<Api>): Model<Api> {\n\tif (model.provider !== \"github-copilot\") return model;\n\tconst resolvedBaseUrl = copilotApiBaseUrlFromToken(copilotTokenFromEnvironment());\n\tif (resolvedBaseUrl === DEFAULT_COPILOT_API_BASE_URL || resolvedBaseUrl === model.baseUrl) return model;\n\treturn { ...model, baseUrl: resolvedBaseUrl };\n}\n\nfunction withCopilotThinkingLevelMap(model: Model<Api>): Model<Api> {\n\tif (model.provider !== \"github-copilot\") return model;\n\tconst context = getActiveCopilotModelCatalog().get(model.id);\n\tif (!context?.supports?.reasoningEffortLevels) return model;\n\tconst thinkingLevelMap = copilotThinkingLevelMapFor(context, model.api);\n\treturn thinkingLevelMap ? { ...model, thinkingLevelMap } : model;\n}\n\nfunction withCopilotContextWindowOptions(model: Model<Api>): Model<Api> {\n\tif (model.provider !== \"github-copilot\") return model;\n\t// The live CAPI catalog (or its disk cache) is authoritative. Without an\n\t// entry (cold start, fetch failure, offline), fall back to the bundled\n\t// static CAPI snapshot: several bundled pi-ai definitions overstate the\n\t// enforced default-tier window or understate output caps, which lets\n\t// sessions sail past the server-side limits before compaction fires\n\t// (issue #1608). Fallback entries carry the same tier structure as catalog\n\t// entries so long-context (1M-class) tiers stay selectable offline.\n\tconst context = getActiveCopilotModelCatalog().get(model.id) ?? getStaticCopilotModelFallback(model.id);\n\tif (!context) return model;\n\tconst base = { ...model, contextWindow: context.contextWindow, maxInputTokens: context.maxInputTokens, maxTokens: context.maxTokens ?? model.maxTokens };\n\tif (context.contextWindowOptions && context.contextWindowOptions.length > 1) {\n\t\treturn withContextWindowOptions(base, context.contextWindowOptions);\n\t}\n\treturn base;\n}\n\nexport function mergeCompat(\n\tbaseCompat: Model<Api>[\"compat\"],\n\toverrideCompat: ModelOverride[\"compat\"] | Model<Api>[\"compat\"],\n): Model<Api>[\"compat\"] | undefined {\n\tif (!overrideCompat) return baseCompat;\n\n\tconst base = baseCompat as ProviderCompat | undefined;\n\tconst override = overrideCompat as ProviderCompat;\n\tconst merged = { ...base, ...override } as ProviderCompat;\n\n\tconst baseCompletions = base as OpenAICompletionsCompat | undefined;\n\tconst overrideCompletions = override as OpenAICompletionsCompat;\n\tconst mergedCompletions = merged as OpenAICompletionsCompat;\n\n\tif (baseCompletions?.openRouterRouting || overrideCompletions.openRouterRouting) {\n\t\tmergedCompletions.openRouterRouting = {\n\t\t\t...baseCompletions?.openRouterRouting,\n\t\t\t...overrideCompletions.openRouterRouting,\n\t\t};\n\t}\n\n\tif (baseCompletions?.vercelGatewayRouting || overrideCompletions.vercelGatewayRouting) {\n\t\tmergedCompletions.vercelGatewayRouting = {\n\t\t\t...baseCompletions?.vercelGatewayRouting,\n\t\t\t...overrideCompletions.vercelGatewayRouting,\n\t\t};\n\t}\n\n\tif (baseCompletions?.chatTemplateKwargs || overrideCompletions.chatTemplateKwargs) {\n\t\tmergedCompletions.chatTemplateKwargs = {\n\t\t\t...baseCompletions?.chatTemplateKwargs,\n\t\t\t...overrideCompletions.chatTemplateKwargs,\n\t\t};\n\t}\n\n\treturn merged as Model<Api>[\"compat\"];\n}\n\nexport function applyModelOverride(model: Model<Api>, override: ModelOverride): Model<Api> {\n\tconst result = { ...model };\n\n\tif (override.name !== undefined) result.name = override.name;\n\tif (override.reasoning !== undefined) result.reasoning = override.reasoning;\n\tif (override.thinkingLevelMap !== undefined) {\n\t\tresult.thinkingLevelMap = { ...model.thinkingLevelMap, ...override.thinkingLevelMap };\n\t}\n\tif (override.input !== undefined) result.input = override.input as (\"text\" | \"image\")[];\n\tif (override.contextWindow !== undefined) {\n\t\tresult.contextWindow = override.contextWindow;\n\t\tresult.defaultContextWindow = override.contextWindow;\n\t\tif (override.contextWindowOptions === undefined) {\n\t\t\tresult.contextWindowOptions = undefined;\n\t\t}\n\t}\n\tif (override.contextWindowOptions !== undefined) {\n\t\tresult.contextWindowOptions = normalizeContextWindowOptions(override.contextWindowOptions);\n\t}\n\tif (override.maxTokens !== undefined) result.maxTokens = override.maxTokens;\n\n\tif (override.cost) {\n\t\tresult.cost = {\n\t\t\tinput: override.cost.input ?? model.cost.input,\n\t\t\toutput: override.cost.output ?? model.cost.output,\n\t\t\tcacheRead: override.cost.cacheRead ?? model.cost.cacheRead,\n\t\t\tcacheWrite: override.cost.cacheWrite ?? model.cost.cacheWrite,\n\t\t};\n\t}\n\n\tresult.compat = mergeCompat(model.compat, override.compat);\n\treturn result;\n}\n\nexport function loadBuiltInModels(\n\toverrides: Map<string, ProviderOverride>,\n\tmodelOverrides: Map<string, Map<string, ModelOverride>>,\n): Model<Api>[] {\n\treturn getProviders().flatMap((provider) => {\n\t\tconst models = withDynamicGitHubCopilotModels(provider, getModels(provider as KnownProvider) as Model<Api>[]);\n\t\tconst providerOverride = overrides.get(provider);\n\t\tconst perModelOverrides = modelOverrides.get(provider);\n\n\t\treturn models.map((m) => {\n\t\t\tlet model = withCopilotEnvironmentBaseUrl(m);\n\n\t\t\tif (providerOverride) {\n\t\t\t\tmodel = {\n\t\t\t\t\t...model,\n\t\t\t\t\tbaseUrl: providerOverride.baseUrl ?? model.baseUrl,\n\t\t\t\t\tcompat: mergeCompat(model.compat, providerOverride.compat),\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tmodel = withCopilotThinkingLevelMap(withCopilotContextWindowOptions(model));\n\t\t\tconst modelOverride = perModelOverrides?.get(m.id);\n\t\t\treturn modelOverride ? applyModelOverride(model, modelOverride) : model;\n\t\t});\n\t});\n}\n\nexport function mergeCustomModels(builtInModels: Model<Api>[], customModels: Model<Api>[]): Model<Api>[] {\n\tconst merged = [...builtInModels];\n\tfor (const customModel of customModels) {\n\t\tconst existingIndex = merged.findIndex((m) => m.provider === customModel.provider && m.id === customModel.id);\n\t\tif (existingIndex >= 0) {\n\t\t\tmerged[existingIndex] = customModel;\n\t\t} else {\n\t\t\tmerged.push(customModel);\n\t\t}\n\t}\n\treturn merged;\n}\n"]}
@@ -1,8 +1,18 @@
1
1
  import { getModels, getProviders, } from "@earendil-works/pi-ai/compat";
2
2
  import { normalizeContextWindowOptions, withContextWindowOptions } from "./context-window.js";
3
- import { getActiveCopilotModelCatalog } from "./copilot-model-catalog.js";
3
+ import { copilotApiBaseUrlFromToken, copilotTokenFromEnvironment, DEFAULT_COPILOT_API_BASE_URL, getActiveCopilotModelCatalog } from "./copilot-model-catalog.js";
4
+ import { copilotTemplateFromModels, copilotThinkingLevelMapFor, synthesizeCopilotCatalogModels } from "./copilot-model-synthesis.js";
5
+ import { getStaticCopilotModelFallback } from "./copilot-model-static-fallbacks.js";
4
6
  const GITHUB_COPILOT_API_VERSION_HEADER = "X-GitHub-Api-Version";
5
7
  const GITHUB_COPILOT_API_VERSION = "2026-06-01";
8
+ function withDynamicGitHubCopilotModels(provider, models) {
9
+ if (provider !== "github-copilot")
10
+ return models;
11
+ const existingIds = new Set(models.map((model) => model.id));
12
+ const template = copilotTemplateFromModels(models);
13
+ const dynamicModels = synthesizeCopilotCatalogModels(getActiveCopilotModelCatalog(), existingIds, template);
14
+ return dynamicModels.length === 0 ? models : [...models, ...dynamicModels];
15
+ }
6
16
  function hasHeader(headers, headerName) {
7
17
  if (!headers)
8
18
  return false;
@@ -15,13 +25,37 @@ export function withGitHubCopilotApiVersionHeader(model, headers) {
15
25
  }
16
26
  return { ...(headers ?? {}), [GITHUB_COPILOT_API_VERSION_HEADER]: GITHUB_COPILOT_API_VERSION };
17
27
  }
18
- function withCopilotContextWindowOptions(model) {
28
+ function withCopilotEnvironmentBaseUrl(model) {
29
+ if (model.provider !== "github-copilot")
30
+ return model;
31
+ const resolvedBaseUrl = copilotApiBaseUrlFromToken(copilotTokenFromEnvironment());
32
+ if (resolvedBaseUrl === DEFAULT_COPILOT_API_BASE_URL || resolvedBaseUrl === model.baseUrl)
33
+ return model;
34
+ return { ...model, baseUrl: resolvedBaseUrl };
35
+ }
36
+ function withCopilotThinkingLevelMap(model) {
19
37
  if (model.provider !== "github-copilot")
20
38
  return model;
21
39
  const context = getActiveCopilotModelCatalog().get(model.id);
40
+ if (!context?.supports?.reasoningEffortLevels)
41
+ return model;
42
+ const thinkingLevelMap = copilotThinkingLevelMapFor(context, model.api);
43
+ return thinkingLevelMap ? { ...model, thinkingLevelMap } : model;
44
+ }
45
+ function withCopilotContextWindowOptions(model) {
46
+ if (model.provider !== "github-copilot")
47
+ return model;
48
+ // The live CAPI catalog (or its disk cache) is authoritative. Without an
49
+ // entry (cold start, fetch failure, offline), fall back to the bundled
50
+ // static CAPI snapshot: several bundled pi-ai definitions overstate the
51
+ // enforced default-tier window or understate output caps, which lets
52
+ // sessions sail past the server-side limits before compaction fires
53
+ // (issue #1608). Fallback entries carry the same tier structure as catalog
54
+ // entries so long-context (1M-class) tiers stay selectable offline.
55
+ const context = getActiveCopilotModelCatalog().get(model.id) ?? getStaticCopilotModelFallback(model.id);
22
56
  if (!context)
23
57
  return model;
24
- const base = { ...model, contextWindow: context.contextWindow, maxInputTokens: context.maxInputTokens };
58
+ const base = { ...model, contextWindow: context.contextWindow, maxInputTokens: context.maxInputTokens, maxTokens: context.maxTokens ?? model.maxTokens };
25
59
  if (context.contextWindowOptions && context.contextWindowOptions.length > 1) {
26
60
  return withContextWindowOptions(base, context.contextWindowOptions);
27
61
  }
@@ -92,11 +126,11 @@ export function applyModelOverride(model, override) {
92
126
  }
93
127
  export function loadBuiltInModels(overrides, modelOverrides) {
94
128
  return getProviders().flatMap((provider) => {
95
- const models = getModels(provider);
129
+ const models = withDynamicGitHubCopilotModels(provider, getModels(provider));
96
130
  const providerOverride = overrides.get(provider);
97
131
  const perModelOverrides = modelOverrides.get(provider);
98
132
  return models.map((m) => {
99
- let model = m;
133
+ let model = withCopilotEnvironmentBaseUrl(m);
100
134
  if (providerOverride) {
101
135
  model = {
102
136
  ...model,
@@ -104,7 +138,7 @@ export function loadBuiltInModels(overrides, modelOverrides) {
104
138
  compat: mergeCompat(model.compat, providerOverride.compat),
105
139
  };
106
140
  }
107
- model = withCopilotContextWindowOptions(model);
141
+ model = withCopilotThinkingLevelMap(withCopilotContextWindowOptions(model));
108
142
  const modelOverride = perModelOverrides?.get(m.id);
109
143
  return modelOverride ? applyModelOverride(model, modelOverride) : model;
110
144
  });
@@ -1 +1 @@
1
- {"version":3,"file":"model-registry-builtins.js","sourceRoot":"","sources":["../../src/core/model-registry-builtins.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\ttype Api,\n\tgetModels,\n\tgetProviders,\n\ttype KnownProvider,\n\ttype Model,\n\ttype OpenAICompletionsCompat,\n} from \"@earendil-works/pi-ai/compat\";\nimport { normalizeContextWindowOptions, withContextWindowOptions } from \"./context-window.ts\";\nimport { getActiveCopilotModelCatalog } from \"./copilot-model-catalog.ts\";\nimport type { ModelOverride } from \"./model-registry-schemas.ts\";\nimport type { ProviderCompat, ProviderOverride } from \"./model-registry-types.ts\";\n\nconst GITHUB_COPILOT_API_VERSION_HEADER = \"X-GitHub-Api-Version\";\nconst GITHUB_COPILOT_API_VERSION = \"2026-06-01\";\n\nfunction hasHeader(headers: Record<string, string> | undefined, headerName: string): boolean {\n\tif (!headers) return false;\n\tconst normalizedHeaderName = headerName.toLowerCase();\n\treturn Object.keys(headers).some((key) => key.toLowerCase() === normalizedHeaderName);\n}\n\nexport function withGitHubCopilotApiVersionHeader(\n\tmodel: Model<Api>,\n\theaders: Record<string, string> | undefined,\n): Record<string, string> | undefined {\n\tif (model.provider !== \"github-copilot\" || hasHeader(headers, GITHUB_COPILOT_API_VERSION_HEADER)) {\n\t\treturn headers;\n\t}\n\treturn { ...(headers ?? {}), [GITHUB_COPILOT_API_VERSION_HEADER]: GITHUB_COPILOT_API_VERSION };\n}\n\nfunction withCopilotContextWindowOptions(model: Model<Api>): Model<Api> {\n\tif (model.provider !== \"github-copilot\") return model;\n\tconst context = getActiveCopilotModelCatalog().get(model.id);\n\tif (!context) return model;\n\tconst base = { ...model, contextWindow: context.contextWindow, maxInputTokens: context.maxInputTokens };\n\tif (context.contextWindowOptions && context.contextWindowOptions.length > 1) {\n\t\treturn withContextWindowOptions(base, context.contextWindowOptions);\n\t}\n\treturn base;\n}\n\nexport function mergeCompat(\n\tbaseCompat: Model<Api>[\"compat\"],\n\toverrideCompat: ModelOverride[\"compat\"] | Model<Api>[\"compat\"],\n): Model<Api>[\"compat\"] | undefined {\n\tif (!overrideCompat) return baseCompat;\n\n\tconst base = baseCompat as ProviderCompat | undefined;\n\tconst override = overrideCompat as ProviderCompat;\n\tconst merged = { ...base, ...override } as ProviderCompat;\n\n\tconst baseCompletions = base as OpenAICompletionsCompat | undefined;\n\tconst overrideCompletions = override as OpenAICompletionsCompat;\n\tconst mergedCompletions = merged as OpenAICompletionsCompat;\n\n\tif (baseCompletions?.openRouterRouting || overrideCompletions.openRouterRouting) {\n\t\tmergedCompletions.openRouterRouting = {\n\t\t\t...baseCompletions?.openRouterRouting,\n\t\t\t...overrideCompletions.openRouterRouting,\n\t\t};\n\t}\n\n\tif (baseCompletions?.vercelGatewayRouting || overrideCompletions.vercelGatewayRouting) {\n\t\tmergedCompletions.vercelGatewayRouting = {\n\t\t\t...baseCompletions?.vercelGatewayRouting,\n\t\t\t...overrideCompletions.vercelGatewayRouting,\n\t\t};\n\t}\n\n\tif (baseCompletions?.chatTemplateKwargs || overrideCompletions.chatTemplateKwargs) {\n\t\tmergedCompletions.chatTemplateKwargs = {\n\t\t\t...baseCompletions?.chatTemplateKwargs,\n\t\t\t...overrideCompletions.chatTemplateKwargs,\n\t\t};\n\t}\n\n\treturn merged as Model<Api>[\"compat\"];\n}\n\nexport function applyModelOverride(model: Model<Api>, override: ModelOverride): Model<Api> {\n\tconst result = { ...model };\n\n\tif (override.name !== undefined) result.name = override.name;\n\tif (override.reasoning !== undefined) result.reasoning = override.reasoning;\n\tif (override.thinkingLevelMap !== undefined) {\n\t\tresult.thinkingLevelMap = { ...model.thinkingLevelMap, ...override.thinkingLevelMap };\n\t}\n\tif (override.input !== undefined) result.input = override.input as (\"text\" | \"image\")[];\n\tif (override.contextWindow !== undefined) {\n\t\tresult.contextWindow = override.contextWindow;\n\t\tresult.defaultContextWindow = override.contextWindow;\n\t\tif (override.contextWindowOptions === undefined) {\n\t\t\tresult.contextWindowOptions = undefined;\n\t\t}\n\t}\n\tif (override.contextWindowOptions !== undefined) {\n\t\tresult.contextWindowOptions = normalizeContextWindowOptions(override.contextWindowOptions);\n\t}\n\tif (override.maxTokens !== undefined) result.maxTokens = override.maxTokens;\n\n\tif (override.cost) {\n\t\tresult.cost = {\n\t\t\tinput: override.cost.input ?? model.cost.input,\n\t\t\toutput: override.cost.output ?? model.cost.output,\n\t\t\tcacheRead: override.cost.cacheRead ?? model.cost.cacheRead,\n\t\t\tcacheWrite: override.cost.cacheWrite ?? model.cost.cacheWrite,\n\t\t};\n\t}\n\n\tresult.compat = mergeCompat(model.compat, override.compat);\n\treturn result;\n}\n\nexport function loadBuiltInModels(\n\toverrides: Map<string, ProviderOverride>,\n\tmodelOverrides: Map<string, Map<string, ModelOverride>>,\n): Model<Api>[] {\n\treturn getProviders().flatMap((provider) => {\n\t\tconst models = getModels(provider as KnownProvider) as Model<Api>[];\n\t\tconst providerOverride = overrides.get(provider);\n\t\tconst perModelOverrides = modelOverrides.get(provider);\n\n\t\treturn models.map((m) => {\n\t\t\tlet model = m;\n\n\t\t\tif (providerOverride) {\n\t\t\t\tmodel = {\n\t\t\t\t\t...model,\n\t\t\t\t\tbaseUrl: providerOverride.baseUrl ?? model.baseUrl,\n\t\t\t\t\tcompat: mergeCompat(model.compat, providerOverride.compat),\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tmodel = withCopilotContextWindowOptions(model);\n\t\t\tconst modelOverride = perModelOverrides?.get(m.id);\n\t\t\treturn modelOverride ? applyModelOverride(model, modelOverride) : model;\n\t\t});\n\t});\n}\n\nexport function mergeCustomModels(builtInModels: Model<Api>[], customModels: Model<Api>[]): Model<Api>[] {\n\tconst merged = [...builtInModels];\n\tfor (const customModel of customModels) {\n\t\tconst existingIndex = merged.findIndex((m) => m.provider === customModel.provider && m.id === customModel.id);\n\t\tif (existingIndex >= 0) {\n\t\t\tmerged[existingIndex] = customModel;\n\t\t} else {\n\t\t\tmerged.push(customModel);\n\t\t}\n\t}\n\treturn merged;\n}\n"]}
1
+ {"version":3,"file":"model-registry-builtins.js","sourceRoot":"","sources":["../../src/core/model-registry-builtins.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\ttype Api,\n\tgetModels,\n\tgetProviders,\n\ttype KnownProvider,\n\ttype Model,\n\ttype OpenAICompletionsCompat,\n} from \"@earendil-works/pi-ai/compat\";\nimport { normalizeContextWindowOptions, withContextWindowOptions } from \"./context-window.ts\";\nimport { copilotApiBaseUrlFromToken, copilotTokenFromEnvironment, DEFAULT_COPILOT_API_BASE_URL, getActiveCopilotModelCatalog } from \"./copilot-model-catalog.ts\";\nimport { copilotTemplateFromModels, copilotThinkingLevelMapFor, synthesizeCopilotCatalogModels } from \"./copilot-model-synthesis.ts\";\nimport { getStaticCopilotModelFallback } from \"./copilot-model-static-fallbacks.ts\";\nimport type { ModelOverride } from \"./model-registry-schemas.ts\";\nimport type { ProviderCompat, ProviderOverride } from \"./model-registry-types.ts\";\n\nconst GITHUB_COPILOT_API_VERSION_HEADER = \"X-GitHub-Api-Version\";\nconst GITHUB_COPILOT_API_VERSION = \"2026-06-01\";\n\nfunction withDynamicGitHubCopilotModels(provider: string, models: Model<Api>[]): Model<Api>[] {\n\tif (provider !== \"github-copilot\") return models;\n\tconst existingIds = new Set(models.map((model) => model.id));\n\tconst template = copilotTemplateFromModels(models);\n\tconst dynamicModels = synthesizeCopilotCatalogModels(getActiveCopilotModelCatalog(), existingIds, template);\n\treturn dynamicModels.length === 0 ? models : [...models, ...dynamicModels];\n}\n\nfunction hasHeader(headers: Record<string, string> | undefined, headerName: string): boolean {\n\tif (!headers) return false;\n\tconst normalizedHeaderName = headerName.toLowerCase();\n\treturn Object.keys(headers).some((key) => key.toLowerCase() === normalizedHeaderName);\n}\n\nexport function withGitHubCopilotApiVersionHeader(\n\tmodel: Model<Api>,\n\theaders: Record<string, string> | undefined,\n): Record<string, string> | undefined {\n\tif (model.provider !== \"github-copilot\" || hasHeader(headers, GITHUB_COPILOT_API_VERSION_HEADER)) {\n\t\treturn headers;\n\t}\n\treturn { ...(headers ?? {}), [GITHUB_COPILOT_API_VERSION_HEADER]: GITHUB_COPILOT_API_VERSION };\n}\n\nfunction withCopilotEnvironmentBaseUrl(model: Model<Api>): Model<Api> {\n\tif (model.provider !== \"github-copilot\") return model;\n\tconst resolvedBaseUrl = copilotApiBaseUrlFromToken(copilotTokenFromEnvironment());\n\tif (resolvedBaseUrl === DEFAULT_COPILOT_API_BASE_URL || resolvedBaseUrl === model.baseUrl) return model;\n\treturn { ...model, baseUrl: resolvedBaseUrl };\n}\n\nfunction withCopilotThinkingLevelMap(model: Model<Api>): Model<Api> {\n\tif (model.provider !== \"github-copilot\") return model;\n\tconst context = getActiveCopilotModelCatalog().get(model.id);\n\tif (!context?.supports?.reasoningEffortLevels) return model;\n\tconst thinkingLevelMap = copilotThinkingLevelMapFor(context, model.api);\n\treturn thinkingLevelMap ? { ...model, thinkingLevelMap } : model;\n}\n\nfunction withCopilotContextWindowOptions(model: Model<Api>): Model<Api> {\n\tif (model.provider !== \"github-copilot\") return model;\n\t// The live CAPI catalog (or its disk cache) is authoritative. Without an\n\t// entry (cold start, fetch failure, offline), fall back to the bundled\n\t// static CAPI snapshot: several bundled pi-ai definitions overstate the\n\t// enforced default-tier window or understate output caps, which lets\n\t// sessions sail past the server-side limits before compaction fires\n\t// (issue #1608). Fallback entries carry the same tier structure as catalog\n\t// entries so long-context (1M-class) tiers stay selectable offline.\n\tconst context = getActiveCopilotModelCatalog().get(model.id) ?? getStaticCopilotModelFallback(model.id);\n\tif (!context) return model;\n\tconst base = { ...model, contextWindow: context.contextWindow, maxInputTokens: context.maxInputTokens, maxTokens: context.maxTokens ?? model.maxTokens };\n\tif (context.contextWindowOptions && context.contextWindowOptions.length > 1) {\n\t\treturn withContextWindowOptions(base, context.contextWindowOptions);\n\t}\n\treturn base;\n}\n\nexport function mergeCompat(\n\tbaseCompat: Model<Api>[\"compat\"],\n\toverrideCompat: ModelOverride[\"compat\"] | Model<Api>[\"compat\"],\n): Model<Api>[\"compat\"] | undefined {\n\tif (!overrideCompat) return baseCompat;\n\n\tconst base = baseCompat as ProviderCompat | undefined;\n\tconst override = overrideCompat as ProviderCompat;\n\tconst merged = { ...base, ...override } as ProviderCompat;\n\n\tconst baseCompletions = base as OpenAICompletionsCompat | undefined;\n\tconst overrideCompletions = override as OpenAICompletionsCompat;\n\tconst mergedCompletions = merged as OpenAICompletionsCompat;\n\n\tif (baseCompletions?.openRouterRouting || overrideCompletions.openRouterRouting) {\n\t\tmergedCompletions.openRouterRouting = {\n\t\t\t...baseCompletions?.openRouterRouting,\n\t\t\t...overrideCompletions.openRouterRouting,\n\t\t};\n\t}\n\n\tif (baseCompletions?.vercelGatewayRouting || overrideCompletions.vercelGatewayRouting) {\n\t\tmergedCompletions.vercelGatewayRouting = {\n\t\t\t...baseCompletions?.vercelGatewayRouting,\n\t\t\t...overrideCompletions.vercelGatewayRouting,\n\t\t};\n\t}\n\n\tif (baseCompletions?.chatTemplateKwargs || overrideCompletions.chatTemplateKwargs) {\n\t\tmergedCompletions.chatTemplateKwargs = {\n\t\t\t...baseCompletions?.chatTemplateKwargs,\n\t\t\t...overrideCompletions.chatTemplateKwargs,\n\t\t};\n\t}\n\n\treturn merged as Model<Api>[\"compat\"];\n}\n\nexport function applyModelOverride(model: Model<Api>, override: ModelOverride): Model<Api> {\n\tconst result = { ...model };\n\n\tif (override.name !== undefined) result.name = override.name;\n\tif (override.reasoning !== undefined) result.reasoning = override.reasoning;\n\tif (override.thinkingLevelMap !== undefined) {\n\t\tresult.thinkingLevelMap = { ...model.thinkingLevelMap, ...override.thinkingLevelMap };\n\t}\n\tif (override.input !== undefined) result.input = override.input as (\"text\" | \"image\")[];\n\tif (override.contextWindow !== undefined) {\n\t\tresult.contextWindow = override.contextWindow;\n\t\tresult.defaultContextWindow = override.contextWindow;\n\t\tif (override.contextWindowOptions === undefined) {\n\t\t\tresult.contextWindowOptions = undefined;\n\t\t}\n\t}\n\tif (override.contextWindowOptions !== undefined) {\n\t\tresult.contextWindowOptions = normalizeContextWindowOptions(override.contextWindowOptions);\n\t}\n\tif (override.maxTokens !== undefined) result.maxTokens = override.maxTokens;\n\n\tif (override.cost) {\n\t\tresult.cost = {\n\t\t\tinput: override.cost.input ?? model.cost.input,\n\t\t\toutput: override.cost.output ?? model.cost.output,\n\t\t\tcacheRead: override.cost.cacheRead ?? model.cost.cacheRead,\n\t\t\tcacheWrite: override.cost.cacheWrite ?? model.cost.cacheWrite,\n\t\t};\n\t}\n\n\tresult.compat = mergeCompat(model.compat, override.compat);\n\treturn result;\n}\n\nexport function loadBuiltInModels(\n\toverrides: Map<string, ProviderOverride>,\n\tmodelOverrides: Map<string, Map<string, ModelOverride>>,\n): Model<Api>[] {\n\treturn getProviders().flatMap((provider) => {\n\t\tconst models = withDynamicGitHubCopilotModels(provider, getModels(provider as KnownProvider) as Model<Api>[]);\n\t\tconst providerOverride = overrides.get(provider);\n\t\tconst perModelOverrides = modelOverrides.get(provider);\n\n\t\treturn models.map((m) => {\n\t\t\tlet model = withCopilotEnvironmentBaseUrl(m);\n\n\t\t\tif (providerOverride) {\n\t\t\t\tmodel = {\n\t\t\t\t\t...model,\n\t\t\t\t\tbaseUrl: providerOverride.baseUrl ?? model.baseUrl,\n\t\t\t\t\tcompat: mergeCompat(model.compat, providerOverride.compat),\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tmodel = withCopilotThinkingLevelMap(withCopilotContextWindowOptions(model));\n\t\t\tconst modelOverride = perModelOverrides?.get(m.id);\n\t\t\treturn modelOverride ? applyModelOverride(model, modelOverride) : model;\n\t\t});\n\t});\n}\n\nexport function mergeCustomModels(builtInModels: Model<Api>[], customModels: Model<Api>[]): Model<Api>[] {\n\tconst merged = [...builtInModels];\n\tfor (const customModel of customModels) {\n\t\tconst existingIndex = merged.findIndex((m) => m.provider === customModel.provider && m.id === customModel.id);\n\t\tif (existingIndex >= 0) {\n\t\t\tmerged[existingIndex] = customModel;\n\t\t} else {\n\t\t\tmerged.push(customModel);\n\t\t}\n\t}\n\treturn merged;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"model-registry.d.ts","sourceRoot":"","sources":["../../src/core/model-registry.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,KAAK,GAAG,EAAE,KAAK,KAAK,EAAqB,MAAM,8BAA8B,CAAC;AAKvF,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAKjE,OAAO,KAAK,EAAE,mBAAmB,EAAyB,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAEjH,OAAO,EAAE,qBAAqB,EAA2B,MAAM,2BAA2B,CAAC;AAE3F,YAAY,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAE1F,kEAAkE;AAClE,eAAO,MAAM,gBAAgB,8BAAwB,CAAC;AAEtD;;GAEG;AACH,qBAAa,aAAa;IACzB,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,sBAAsB,CAAiD;IAC/E,OAAO,CAAC,mBAAmB,CAAkD;IAC7E,OAAO,CAAC,mBAAmB,CAA+C;IAC1E,OAAO,CAAC,SAAS,CAAiC;IAElD,SAAiB,WAAW,EAAE,WAAW,CAAC;IAC1C,QAAgB,eAAe,CAAW;IAE1C,OAAO,eAQN;IAED,OAAO,CAAC,gCAAgC;IAOxC,MAAM,CAAC,MAAM,CACZ,WAAW,EAAE,WAAW,EACxB,cAAc,GAAE,MAAM,GAAG,MAAM,EAAuC,GACpE,aAAa,CAEf;IAED,MAAM,CAAC,QAAQ,CAAC,WAAW,EAAE,WAAW,GAAG,aAAa,CAEvD;IAED;;OAEG;IACH,OAAO,IAAI,IAAI,CAad;IAED;;OAEG;IACH,QAAQ,IAAI,MAAM,GAAG,SAAS,CAE7B;IAED,OAAO,CAAC,UAAU;IAQlB;;;OAGG;IACH,MAAM,IAAI,KAAK,CAAC,GAAG,CAAC,EAAE,CAErB;IAED;;;OAGG;IACH,YAAY,IAAI,KAAK,CAAC,GAAG,CAAC,EAAE,CAE3B;IAED;;OAEG;IACH,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,SAAS,CAE9D;IAED;;OAEG;IACH,iBAAiB,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,OAAO,CAM5C;IAED,OAAO,CAAC,kBAAkB;IAI1B,OAAO,CAAC,0BAA0B;IAmBlC,OAAO,CAAC,iBAAiB;IASzB;;OAEG;IACG,mBAAmB,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAEzE;IAED;;;OAGG;IACH,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,CAElD;IAED;;OAEG;IACH,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAW/C;IAED;;OAEG;IACG,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAExE;IAED;;OAEG;IACH,YAAY,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,OAAO,CAGvC;IAED;;OAEG;IACH,gBAAgB,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,mBAAmB,GAAG,IAAI,CAKxE;IAED;;OAEG;IACH,+BAA+B,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAOjD;IAED;;OAEG;IACH,kBAAkB,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAI7C;IAED,OAAO,CAAC,wBAAwB;IAahC,OAAO,CAAC,mBAAmB;CAU3B","sourcesContent":["/**\n * Model registry - manages built-in and custom models, provides API key resolution.\n */\n\nimport { type Api, type Model, resetApiProviders } from \"@earendil-works/pi-ai/compat\";\nimport { resetOAuthProviders } from \"@earendil-works/pi-ai/oauth\";\nimport { dirname } from \"node:path\";\nimport { getAgentConfigPaths } from \"../config.ts\";\nimport { normalizePath } from \"../utils/paths.ts\";\nimport type { AuthStatus, AuthStorage } from \"./auth-storage.ts\";\nimport { copilotCatalogCachePath, seedActiveCopilotModelCatalogFromCache } from \"./copilot-model-catalog.ts\";\nimport { getModelRequestAuth, getApiKeyForProviderFromConfig, getProviderAuthStatusFromConfig } from \"./model-registry-auth.ts\";\nimport { applyProviderConfigToModels, migrateLegacyRegisterProviderConfigValues, validateProviderConfig } from \"./model-registry-dynamic.ts\";\nimport { loadModelRegistryModels } from \"./model-registry-loader.ts\";\nimport type { ProviderConfigInput, ProviderRequestConfig, ResolvedRequestAuth } from \"./model-registry-types.ts\";\nimport { BUILT_IN_PROVIDER_DISPLAY_NAMES } from \"./provider-display-names.ts\";\nimport { clearConfigValueCache, isConfigValueConfigured } from \"./resolve-config-value.ts\";\n\nexport type { ProviderConfigInput, ResolvedRequestAuth } from \"./model-registry-types.ts\";\n\n/** Clear the config value command cache. Exported for testing. */\nexport const clearApiKeyCache = clearConfigValueCache;\n\n/**\n * Model registry - loads and manages models, resolves API keys via AuthStorage.\n */\nexport class ModelRegistry {\n\tprivate models: Model<Api>[] = [];\n\tprivate providerRequestConfigs: Map<string, ProviderRequestConfig> = new Map();\n\tprivate modelRequestHeaders: Map<string, Record<string, string>> = new Map();\n\tprivate registeredProviders: Map<string, ProviderConfigInput> = new Map();\n\tprivate loadError: string | undefined = undefined;\n\n\tdeclare readonly authStorage: AuthStorage;\n\tdeclare private modelsJsonPaths: string[];\n\n\tprivate constructor(\n\t\tauthStorage: AuthStorage,\n\t\tmodelsJsonPaths: string[],\n\t) {\n\t\tthis.authStorage = authStorage;\n\t\tthis.modelsJsonPaths = modelsJsonPaths.map((path) => normalizePath(path));\n\t\tthis.seedCopilotModelCatalogFromCache();\n\t\tthis.loadModels();\n\t}\n\n\tprivate seedCopilotModelCatalogFromCache(): void {\n\t\tif (this.modelsJsonPaths.length === 0) return;\n\t\tconst cred = this.authStorage.get(\"github-copilot\");\n\t\tif (!cred || cred.type !== \"oauth\" || typeof cred.access !== \"string\") return;\n\t\tseedActiveCopilotModelCatalogFromCache(cred.access, copilotCatalogCachePath(dirname(this.modelsJsonPaths[0])));\n\t}\n\n\tstatic create(\n\t\tauthStorage: AuthStorage,\n\t\tmodelsJsonPath: string | string[] = getAgentConfigPaths(\"models.json\"),\n\t): ModelRegistry {\n\t\treturn new ModelRegistry(authStorage, Array.isArray(modelsJsonPath) ? modelsJsonPath : [modelsJsonPath]);\n\t}\n\n\tstatic inMemory(authStorage: AuthStorage): ModelRegistry {\n\t\treturn new ModelRegistry(authStorage, []);\n\t}\n\n\t/**\n\t * Reload models from disk (built-in + custom from models.json).\n\t */\n\trefresh(): void {\n\t\tthis.providerRequestConfigs.clear();\n\t\tthis.modelRequestHeaders.clear();\n\t\tthis.loadError = undefined;\n\n\t\tresetApiProviders();\n\t\tresetOAuthProviders();\n\n\t\tthis.loadModels();\n\n\t\tfor (const [providerName, config] of this.registeredProviders.entries()) {\n\t\t\tthis.applyProviderConfig(providerName, config);\n\t\t}\n\t}\n\n\t/**\n\t * Get any error from loading models.json (undefined if no error).\n\t */\n\tgetError(): string | undefined {\n\t\treturn this.loadError;\n\t}\n\n\tprivate loadModels(): void {\n\t\tconst loaded = loadModelRegistryModels(this.authStorage, this.modelsJsonPaths);\n\t\tthis.models = loaded.models;\n\t\tthis.providerRequestConfigs = loaded.providerRequestConfigs;\n\t\tthis.modelRequestHeaders = loaded.modelRequestHeaders;\n\t\tthis.loadError = loaded.loadError;\n\t}\n\n\t/**\n\t * Get all models (built-in + custom).\n\t * If models.json had errors, returns only built-in models.\n\t */\n\tgetAll(): Model<Api>[] {\n\t\treturn this.models;\n\t}\n\n\t/**\n\t * Get only models that have auth configured.\n\t * This is a fast check that doesn't refresh OAuth tokens.\n\t */\n\tgetAvailable(): Model<Api>[] {\n\t\treturn this.models.filter((m) => this.hasConfiguredAuth(m));\n\t}\n\n\t/**\n\t * Find a model by provider and ID.\n\t */\n\tfind(provider: string, modelId: string): Model<Api> | undefined {\n\t\treturn this.models.find((m) => m.provider === provider && m.id === modelId);\n\t}\n\n\t/**\n\t * Get API key for a model.\n\t */\n\thasConfiguredAuth(model: Model<Api>): boolean {\n\t\tconst providerApiKey = this.providerRequestConfigs.get(model.provider)?.apiKey;\n\t\treturn (\n\t\t\tthis.authStorage.hasAuth(model.provider) ||\n\t\t\t(providerApiKey !== undefined && isConfigValueConfigured(providerApiKey))\n\t\t);\n\t}\n\n\tprivate getModelRequestKey(provider: string, modelId: string): string {\n\t\treturn `${provider}:${modelId}`;\n\t}\n\n\tprivate storeProviderRequestConfig(\n\t\tproviderName: string,\n\t\tconfig: {\n\t\t\tapiKey?: string;\n\t\t\theaders?: Record<string, string>;\n\t\t\tauthHeader?: boolean;\n\t\t},\n\t): void {\n\t\tif (!config.apiKey && !config.headers && !config.authHeader) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.providerRequestConfigs.set(providerName, {\n\t\t\tapiKey: config.apiKey,\n\t\t\theaders: config.headers,\n\t\t\tauthHeader: config.authHeader,\n\t\t});\n\t}\n\n\tprivate storeModelHeaders(providerName: string, modelId: string, headers?: Record<string, string>): void {\n\t\tconst key = this.getModelRequestKey(providerName, modelId);\n\t\tif (!headers || Object.keys(headers).length === 0) {\n\t\t\tthis.modelRequestHeaders.delete(key);\n\t\t\treturn;\n\t\t}\n\t\tthis.modelRequestHeaders.set(key, headers);\n\t}\n\n\t/**\n\t * Get API key and request headers for a model.\n\t */\n\tasync getApiKeyAndHeaders(model: Model<Api>): Promise<ResolvedRequestAuth> {\n\t\treturn getModelRequestAuth(model, this.authStorage, this.providerRequestConfigs, this.modelRequestHeaders);\n\t}\n\n\t/**\n\t * Return auth status for a provider, including request auth configured in models.json.\n\t * This intentionally does not execute command-backed config values.\n\t */\n\tgetProviderAuthStatus(provider: string): AuthStatus {\n\t\treturn getProviderAuthStatusFromConfig(provider, this.authStorage, this.providerRequestConfigs);\n\t}\n\n\t/**\n\t * Get display name for a provider.\n\t */\n\tgetProviderDisplayName(provider: string): string {\n\t\tconst registeredProvider = this.registeredProviders.get(provider);\n\t\tconst oauthProvider = this.authStorage.getOAuthProviders().find((p) => p.id === provider);\n\n\t\treturn (\n\t\t\tregisteredProvider?.name ??\n\t\t\tregisteredProvider?.oauth?.name ??\n\t\t\toauthProvider?.name ??\n\t\t\tBUILT_IN_PROVIDER_DISPLAY_NAMES[provider] ??\n\t\t\tprovider\n\t\t);\n\t}\n\n\t/**\n\t * Get API key for a provider.\n\t */\n\tasync getApiKeyForProvider(provider: string): Promise<string | undefined> {\n\t\treturn getApiKeyForProviderFromConfig(provider, this.authStorage, this.providerRequestConfigs);\n\t}\n\n\t/**\n\t * Check if a model is using OAuth credentials (subscription).\n\t */\n\tisUsingOAuth(model: Model<Api>): boolean {\n\t\tconst cred = this.authStorage.get(model.provider);\n\t\treturn cred?.type === \"oauth\";\n\t}\n\n\t/**\n\t * Register a provider dynamically (from extensions).\n\t */\n\tregisterProvider(providerName: string, config: ProviderConfigInput): void {\n\t\tconst migratedConfig = migrateLegacyRegisterProviderConfigValues(providerName, config);\n\t\tvalidateProviderConfig(providerName, migratedConfig);\n\t\tthis.applyProviderConfig(providerName, migratedConfig);\n\t\tthis.upsertRegisteredProvider(providerName, migratedConfig);\n\t}\n\n\t/**\n\t * Check whether extensions have registered custom streamSimple dispatch for an API.\n\t */\n\thasRegisteredStreamSimpleForApi(api: Api): boolean {\n\t\tfor (const config of this.registeredProviders.values()) {\n\t\t\tif (config.api === api && config.streamSimple) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\t/**\n\t * Unregister a previously registered provider.\n\t */\n\tunregisterProvider(providerName: string): void {\n\t\tif (!this.registeredProviders.has(providerName)) return;\n\t\tthis.registeredProviders.delete(providerName);\n\t\tthis.refresh();\n\t}\n\n\tprivate upsertRegisteredProvider(providerName: string, config: ProviderConfigInput): void {\n\t\tconst existing = this.registeredProviders.get(providerName);\n\t\tif (!existing) {\n\t\t\tthis.registeredProviders.set(providerName, config);\n\t\t\treturn;\n\t\t}\n\t\tfor (const k of Object.keys(config) as (keyof ProviderConfigInput)[]) {\n\t\t\tif (config[k] !== undefined) {\n\t\t\t\t(existing as Record<string, unknown>)[k] = config[k];\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate applyProviderConfig(providerName: string, config: ProviderConfigInput): void {\n\t\tthis.models = applyProviderConfigToModels({\n\t\t\tproviderName,\n\t\t\tconfig,\n\t\t\tmodels: this.models,\n\t\t\tauthStorage: this.authStorage,\n\t\t\tstoreProviderRequestConfig: (name, requestConfig) => this.storeProviderRequestConfig(name, requestConfig),\n\t\t\tstoreModelHeaders: (name, modelId, headers) => this.storeModelHeaders(name, modelId, headers),\n\t\t});\n\t}\n}\n"]}
1
+ {"version":3,"file":"model-registry.d.ts","sourceRoot":"","sources":["../../src/core/model-registry.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,KAAK,GAAG,EAAE,KAAK,KAAK,EAAqB,MAAM,8BAA8B,CAAC;AAKvF,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAKjE,OAAO,KAAK,EAAE,mBAAmB,EAAyB,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAEjH,OAAO,EAAE,qBAAqB,EAA2B,MAAM,2BAA2B,CAAC;AAE3F,YAAY,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAE1F,kEAAkE;AAClE,eAAO,MAAM,gBAAgB,8BAAwB,CAAC;AAEtD;;GAEG;AACH,qBAAa,aAAa;IACzB,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,sBAAsB,CAAiD;IAC/E,OAAO,CAAC,mBAAmB,CAAkD;IAC7E,OAAO,CAAC,mBAAmB,CAA+C;IAC1E,OAAO,CAAC,SAAS,CAAiC;IAElD,SAAiB,WAAW,EAAE,WAAW,CAAC;IAC1C,QAAgB,eAAe,CAAW;IAE1C,OAAO,eAQN;IAED,OAAO,CAAC,gCAAgC;IAQxC,MAAM,CAAC,MAAM,CACZ,WAAW,EAAE,WAAW,EACxB,cAAc,GAAE,MAAM,GAAG,MAAM,EAAuC,GACpE,aAAa,CAEf;IAED,MAAM,CAAC,QAAQ,CAAC,WAAW,EAAE,WAAW,GAAG,aAAa,CAEvD;IAED;;OAEG;IACH,OAAO,IAAI,IAAI,CAad;IAED;;OAEG;IACH,QAAQ,IAAI,MAAM,GAAG,SAAS,CAE7B;IAED,OAAO,CAAC,UAAU;IAQlB;;;OAGG;IACH,MAAM,IAAI,KAAK,CAAC,GAAG,CAAC,EAAE,CAErB;IAED;;;OAGG;IACH,YAAY,IAAI,KAAK,CAAC,GAAG,CAAC,EAAE,CAE3B;IAED;;OAEG;IACH,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,SAAS,CAE9D;IAED;;OAEG;IACH,iBAAiB,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,OAAO,CAM5C;IAED,OAAO,CAAC,kBAAkB;IAI1B,OAAO,CAAC,0BAA0B;IAmBlC,OAAO,CAAC,iBAAiB;IASzB;;OAEG;IACG,mBAAmB,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAEzE;IAED;;;OAGG;IACH,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,CAElD;IAED;;OAEG;IACH,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAW/C;IAED;;OAEG;IACG,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAExE;IAED;;OAEG;IACH,YAAY,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,OAAO,CAGvC;IAED;;OAEG;IACH,gBAAgB,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,mBAAmB,GAAG,IAAI,CAKxE;IAED;;OAEG;IACH,+BAA+B,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAOjD;IAED;;OAEG;IACH,kBAAkB,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAI7C;IAED,OAAO,CAAC,wBAAwB;IAahC,OAAO,CAAC,mBAAmB;CAU3B","sourcesContent":["/**\n * Model registry - manages built-in and custom models, provides API key resolution.\n */\n\nimport { type Api, type Model, resetApiProviders } from \"@earendil-works/pi-ai/compat\";\nimport { resetOAuthProviders } from \"@earendil-works/pi-ai/oauth\";\nimport { dirname } from \"node:path\";\nimport { getAgentConfigPaths } from \"../config.ts\";\nimport { normalizePath } from \"../utils/paths.ts\";\nimport type { AuthStatus, AuthStorage } from \"./auth-storage.ts\";\nimport { copilotCatalogCachePath, copilotTokenFromEnvironment, seedActiveCopilotModelCatalogFromCache } from \"./copilot-model-catalog.ts\";\nimport { getModelRequestAuth, getApiKeyForProviderFromConfig, getProviderAuthStatusFromConfig } from \"./model-registry-auth.ts\";\nimport { applyProviderConfigToModels, migrateLegacyRegisterProviderConfigValues, validateProviderConfig } from \"./model-registry-dynamic.ts\";\nimport { loadModelRegistryModels } from \"./model-registry-loader.ts\";\nimport type { ProviderConfigInput, ProviderRequestConfig, ResolvedRequestAuth } from \"./model-registry-types.ts\";\nimport { BUILT_IN_PROVIDER_DISPLAY_NAMES } from \"./provider-display-names.ts\";\nimport { clearConfigValueCache, isConfigValueConfigured } from \"./resolve-config-value.ts\";\n\nexport type { ProviderConfigInput, ResolvedRequestAuth } from \"./model-registry-types.ts\";\n\n/** Clear the config value command cache. Exported for testing. */\nexport const clearApiKeyCache = clearConfigValueCache;\n\n/**\n * Model registry - loads and manages models, resolves API keys via AuthStorage.\n */\nexport class ModelRegistry {\n\tprivate models: Model<Api>[] = [];\n\tprivate providerRequestConfigs: Map<string, ProviderRequestConfig> = new Map();\n\tprivate modelRequestHeaders: Map<string, Record<string, string>> = new Map();\n\tprivate registeredProviders: Map<string, ProviderConfigInput> = new Map();\n\tprivate loadError: string | undefined = undefined;\n\n\tdeclare readonly authStorage: AuthStorage;\n\tdeclare private modelsJsonPaths: string[];\n\n\tprivate constructor(\n\t\tauthStorage: AuthStorage,\n\t\tmodelsJsonPaths: string[],\n\t) {\n\t\tthis.authStorage = authStorage;\n\t\tthis.modelsJsonPaths = modelsJsonPaths.map((path) => normalizePath(path));\n\t\tthis.seedCopilotModelCatalogFromCache();\n\t\tthis.loadModels();\n\t}\n\n\tprivate seedCopilotModelCatalogFromCache(): void {\n\t\tif (this.modelsJsonPaths.length === 0) return;\n\t\tconst cred = this.authStorage.get(\"github-copilot\");\n\t\tconst token = cred?.type === \"oauth\" && typeof cred.access === \"string\" ? cred.access : copilotTokenFromEnvironment();\n\t\tif (!token) return;\n\t\tseedActiveCopilotModelCatalogFromCache(token, copilotCatalogCachePath(dirname(this.modelsJsonPaths[0])));\n\t}\n\n\tstatic create(\n\t\tauthStorage: AuthStorage,\n\t\tmodelsJsonPath: string | string[] = getAgentConfigPaths(\"models.json\"),\n\t): ModelRegistry {\n\t\treturn new ModelRegistry(authStorage, Array.isArray(modelsJsonPath) ? modelsJsonPath : [modelsJsonPath]);\n\t}\n\n\tstatic inMemory(authStorage: AuthStorage): ModelRegistry {\n\t\treturn new ModelRegistry(authStorage, []);\n\t}\n\n\t/**\n\t * Reload models from disk (built-in + custom from models.json).\n\t */\n\trefresh(): void {\n\t\tthis.providerRequestConfigs.clear();\n\t\tthis.modelRequestHeaders.clear();\n\t\tthis.loadError = undefined;\n\n\t\tresetApiProviders();\n\t\tresetOAuthProviders();\n\n\t\tthis.loadModels();\n\n\t\tfor (const [providerName, config] of this.registeredProviders.entries()) {\n\t\t\tthis.applyProviderConfig(providerName, config);\n\t\t}\n\t}\n\n\t/**\n\t * Get any error from loading models.json (undefined if no error).\n\t */\n\tgetError(): string | undefined {\n\t\treturn this.loadError;\n\t}\n\n\tprivate loadModels(): void {\n\t\tconst loaded = loadModelRegistryModels(this.authStorage, this.modelsJsonPaths);\n\t\tthis.models = loaded.models;\n\t\tthis.providerRequestConfigs = loaded.providerRequestConfigs;\n\t\tthis.modelRequestHeaders = loaded.modelRequestHeaders;\n\t\tthis.loadError = loaded.loadError;\n\t}\n\n\t/**\n\t * Get all models (built-in + custom).\n\t * If models.json had errors, returns only built-in models.\n\t */\n\tgetAll(): Model<Api>[] {\n\t\treturn this.models;\n\t}\n\n\t/**\n\t * Get only models that have auth configured.\n\t * This is a fast check that doesn't refresh OAuth tokens.\n\t */\n\tgetAvailable(): Model<Api>[] {\n\t\treturn this.models.filter((m) => this.hasConfiguredAuth(m));\n\t}\n\n\t/**\n\t * Find a model by provider and ID.\n\t */\n\tfind(provider: string, modelId: string): Model<Api> | undefined {\n\t\treturn this.models.find((m) => m.provider === provider && m.id === modelId);\n\t}\n\n\t/**\n\t * Get API key for a model.\n\t */\n\thasConfiguredAuth(model: Model<Api>): boolean {\n\t\tconst providerApiKey = this.providerRequestConfigs.get(model.provider)?.apiKey;\n\t\treturn (\n\t\t\tthis.authStorage.hasAuth(model.provider) ||\n\t\t\t(providerApiKey !== undefined && isConfigValueConfigured(providerApiKey))\n\t\t);\n\t}\n\n\tprivate getModelRequestKey(provider: string, modelId: string): string {\n\t\treturn `${provider}:${modelId}`;\n\t}\n\n\tprivate storeProviderRequestConfig(\n\t\tproviderName: string,\n\t\tconfig: {\n\t\t\tapiKey?: string;\n\t\t\theaders?: Record<string, string>;\n\t\t\tauthHeader?: boolean;\n\t\t},\n\t): void {\n\t\tif (!config.apiKey && !config.headers && !config.authHeader) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.providerRequestConfigs.set(providerName, {\n\t\t\tapiKey: config.apiKey,\n\t\t\theaders: config.headers,\n\t\t\tauthHeader: config.authHeader,\n\t\t});\n\t}\n\n\tprivate storeModelHeaders(providerName: string, modelId: string, headers?: Record<string, string>): void {\n\t\tconst key = this.getModelRequestKey(providerName, modelId);\n\t\tif (!headers || Object.keys(headers).length === 0) {\n\t\t\tthis.modelRequestHeaders.delete(key);\n\t\t\treturn;\n\t\t}\n\t\tthis.modelRequestHeaders.set(key, headers);\n\t}\n\n\t/**\n\t * Get API key and request headers for a model.\n\t */\n\tasync getApiKeyAndHeaders(model: Model<Api>): Promise<ResolvedRequestAuth> {\n\t\treturn getModelRequestAuth(model, this.authStorage, this.providerRequestConfigs, this.modelRequestHeaders);\n\t}\n\n\t/**\n\t * Return auth status for a provider, including request auth configured in models.json.\n\t * This intentionally does not execute command-backed config values.\n\t */\n\tgetProviderAuthStatus(provider: string): AuthStatus {\n\t\treturn getProviderAuthStatusFromConfig(provider, this.authStorage, this.providerRequestConfigs);\n\t}\n\n\t/**\n\t * Get display name for a provider.\n\t */\n\tgetProviderDisplayName(provider: string): string {\n\t\tconst registeredProvider = this.registeredProviders.get(provider);\n\t\tconst oauthProvider = this.authStorage.getOAuthProviders().find((p) => p.id === provider);\n\n\t\treturn (\n\t\t\tregisteredProvider?.name ??\n\t\t\tregisteredProvider?.oauth?.name ??\n\t\t\toauthProvider?.name ??\n\t\t\tBUILT_IN_PROVIDER_DISPLAY_NAMES[provider] ??\n\t\t\tprovider\n\t\t);\n\t}\n\n\t/**\n\t * Get API key for a provider.\n\t */\n\tasync getApiKeyForProvider(provider: string): Promise<string | undefined> {\n\t\treturn getApiKeyForProviderFromConfig(provider, this.authStorage, this.providerRequestConfigs);\n\t}\n\n\t/**\n\t * Check if a model is using OAuth credentials (subscription).\n\t */\n\tisUsingOAuth(model: Model<Api>): boolean {\n\t\tconst cred = this.authStorage.get(model.provider);\n\t\treturn cred?.type === \"oauth\";\n\t}\n\n\t/**\n\t * Register a provider dynamically (from extensions).\n\t */\n\tregisterProvider(providerName: string, config: ProviderConfigInput): void {\n\t\tconst migratedConfig = migrateLegacyRegisterProviderConfigValues(providerName, config);\n\t\tvalidateProviderConfig(providerName, migratedConfig);\n\t\tthis.applyProviderConfig(providerName, migratedConfig);\n\t\tthis.upsertRegisteredProvider(providerName, migratedConfig);\n\t}\n\n\t/**\n\t * Check whether extensions have registered custom streamSimple dispatch for an API.\n\t */\n\thasRegisteredStreamSimpleForApi(api: Api): boolean {\n\t\tfor (const config of this.registeredProviders.values()) {\n\t\t\tif (config.api === api && config.streamSimple) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\t/**\n\t * Unregister a previously registered provider.\n\t */\n\tunregisterProvider(providerName: string): void {\n\t\tif (!this.registeredProviders.has(providerName)) return;\n\t\tthis.registeredProviders.delete(providerName);\n\t\tthis.refresh();\n\t}\n\n\tprivate upsertRegisteredProvider(providerName: string, config: ProviderConfigInput): void {\n\t\tconst existing = this.registeredProviders.get(providerName);\n\t\tif (!existing) {\n\t\t\tthis.registeredProviders.set(providerName, config);\n\t\t\treturn;\n\t\t}\n\t\tfor (const k of Object.keys(config) as (keyof ProviderConfigInput)[]) {\n\t\t\tif (config[k] !== undefined) {\n\t\t\t\t(existing as Record<string, unknown>)[k] = config[k];\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate applyProviderConfig(providerName: string, config: ProviderConfigInput): void {\n\t\tthis.models = applyProviderConfigToModels({\n\t\t\tproviderName,\n\t\t\tconfig,\n\t\t\tmodels: this.models,\n\t\t\tauthStorage: this.authStorage,\n\t\t\tstoreProviderRequestConfig: (name, requestConfig) => this.storeProviderRequestConfig(name, requestConfig),\n\t\t\tstoreModelHeaders: (name, modelId, headers) => this.storeModelHeaders(name, modelId, headers),\n\t\t});\n\t}\n}\n"]}
@@ -6,7 +6,7 @@ import { resetOAuthProviders } from "@earendil-works/pi-ai/oauth";
6
6
  import { dirname } from "node:path";
7
7
  import { getAgentConfigPaths } from "../config.js";
8
8
  import { normalizePath } from "../utils/paths.js";
9
- import { copilotCatalogCachePath, seedActiveCopilotModelCatalogFromCache } from "./copilot-model-catalog.js";
9
+ import { copilotCatalogCachePath, copilotTokenFromEnvironment, seedActiveCopilotModelCatalogFromCache } from "./copilot-model-catalog.js";
10
10
  import { getModelRequestAuth, getApiKeyForProviderFromConfig, getProviderAuthStatusFromConfig } from "./model-registry-auth.js";
11
11
  import { applyProviderConfigToModels, migrateLegacyRegisterProviderConfigValues, validateProviderConfig } from "./model-registry-dynamic.js";
12
12
  import { loadModelRegistryModels } from "./model-registry-loader.js";
@@ -33,9 +33,10 @@ export class ModelRegistry {
33
33
  if (this.modelsJsonPaths.length === 0)
34
34
  return;
35
35
  const cred = this.authStorage.get("github-copilot");
36
- if (!cred || cred.type !== "oauth" || typeof cred.access !== "string")
36
+ const token = cred?.type === "oauth" && typeof cred.access === "string" ? cred.access : copilotTokenFromEnvironment();
37
+ if (!token)
37
38
  return;
38
- seedActiveCopilotModelCatalogFromCache(cred.access, copilotCatalogCachePath(dirname(this.modelsJsonPaths[0])));
39
+ seedActiveCopilotModelCatalogFromCache(token, copilotCatalogCachePath(dirname(this.modelsJsonPaths[0])));
39
40
  }
40
41
  static create(authStorage, modelsJsonPath = getAgentConfigPaths("models.json")) {
41
42
  return new ModelRegistry(authStorage, Array.isArray(modelsJsonPath) ? modelsJsonPath : [modelsJsonPath]);
@@ -1 +1 @@
1
- {"version":3,"file":"model-registry.js","sourceRoot":"","sources":["../../src/core/model-registry.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Model registry - manages built-in and custom models, provides API key resolution.\n */\n\nimport { type Api, type Model, resetApiProviders } from \"@earendil-works/pi-ai/compat\";\nimport { resetOAuthProviders } from \"@earendil-works/pi-ai/oauth\";\nimport { dirname } from \"node:path\";\nimport { getAgentConfigPaths } from \"../config.ts\";\nimport { normalizePath } from \"../utils/paths.ts\";\nimport type { AuthStatus, AuthStorage } from \"./auth-storage.ts\";\nimport { copilotCatalogCachePath, seedActiveCopilotModelCatalogFromCache } from \"./copilot-model-catalog.ts\";\nimport { getModelRequestAuth, getApiKeyForProviderFromConfig, getProviderAuthStatusFromConfig } from \"./model-registry-auth.ts\";\nimport { applyProviderConfigToModels, migrateLegacyRegisterProviderConfigValues, validateProviderConfig } from \"./model-registry-dynamic.ts\";\nimport { loadModelRegistryModels } from \"./model-registry-loader.ts\";\nimport type { ProviderConfigInput, ProviderRequestConfig, ResolvedRequestAuth } from \"./model-registry-types.ts\";\nimport { BUILT_IN_PROVIDER_DISPLAY_NAMES } from \"./provider-display-names.ts\";\nimport { clearConfigValueCache, isConfigValueConfigured } from \"./resolve-config-value.ts\";\n\nexport type { ProviderConfigInput, ResolvedRequestAuth } from \"./model-registry-types.ts\";\n\n/** Clear the config value command cache. Exported for testing. */\nexport const clearApiKeyCache = clearConfigValueCache;\n\n/**\n * Model registry - loads and manages models, resolves API keys via AuthStorage.\n */\nexport class ModelRegistry {\n\tprivate models: Model<Api>[] = [];\n\tprivate providerRequestConfigs: Map<string, ProviderRequestConfig> = new Map();\n\tprivate modelRequestHeaders: Map<string, Record<string, string>> = new Map();\n\tprivate registeredProviders: Map<string, ProviderConfigInput> = new Map();\n\tprivate loadError: string | undefined = undefined;\n\n\tdeclare readonly authStorage: AuthStorage;\n\tdeclare private modelsJsonPaths: string[];\n\n\tprivate constructor(\n\t\tauthStorage: AuthStorage,\n\t\tmodelsJsonPaths: string[],\n\t) {\n\t\tthis.authStorage = authStorage;\n\t\tthis.modelsJsonPaths = modelsJsonPaths.map((path) => normalizePath(path));\n\t\tthis.seedCopilotModelCatalogFromCache();\n\t\tthis.loadModels();\n\t}\n\n\tprivate seedCopilotModelCatalogFromCache(): void {\n\t\tif (this.modelsJsonPaths.length === 0) return;\n\t\tconst cred = this.authStorage.get(\"github-copilot\");\n\t\tif (!cred || cred.type !== \"oauth\" || typeof cred.access !== \"string\") return;\n\t\tseedActiveCopilotModelCatalogFromCache(cred.access, copilotCatalogCachePath(dirname(this.modelsJsonPaths[0])));\n\t}\n\n\tstatic create(\n\t\tauthStorage: AuthStorage,\n\t\tmodelsJsonPath: string | string[] = getAgentConfigPaths(\"models.json\"),\n\t): ModelRegistry {\n\t\treturn new ModelRegistry(authStorage, Array.isArray(modelsJsonPath) ? modelsJsonPath : [modelsJsonPath]);\n\t}\n\n\tstatic inMemory(authStorage: AuthStorage): ModelRegistry {\n\t\treturn new ModelRegistry(authStorage, []);\n\t}\n\n\t/**\n\t * Reload models from disk (built-in + custom from models.json).\n\t */\n\trefresh(): void {\n\t\tthis.providerRequestConfigs.clear();\n\t\tthis.modelRequestHeaders.clear();\n\t\tthis.loadError = undefined;\n\n\t\tresetApiProviders();\n\t\tresetOAuthProviders();\n\n\t\tthis.loadModels();\n\n\t\tfor (const [providerName, config] of this.registeredProviders.entries()) {\n\t\t\tthis.applyProviderConfig(providerName, config);\n\t\t}\n\t}\n\n\t/**\n\t * Get any error from loading models.json (undefined if no error).\n\t */\n\tgetError(): string | undefined {\n\t\treturn this.loadError;\n\t}\n\n\tprivate loadModels(): void {\n\t\tconst loaded = loadModelRegistryModels(this.authStorage, this.modelsJsonPaths);\n\t\tthis.models = loaded.models;\n\t\tthis.providerRequestConfigs = loaded.providerRequestConfigs;\n\t\tthis.modelRequestHeaders = loaded.modelRequestHeaders;\n\t\tthis.loadError = loaded.loadError;\n\t}\n\n\t/**\n\t * Get all models (built-in + custom).\n\t * If models.json had errors, returns only built-in models.\n\t */\n\tgetAll(): Model<Api>[] {\n\t\treturn this.models;\n\t}\n\n\t/**\n\t * Get only models that have auth configured.\n\t * This is a fast check that doesn't refresh OAuth tokens.\n\t */\n\tgetAvailable(): Model<Api>[] {\n\t\treturn this.models.filter((m) => this.hasConfiguredAuth(m));\n\t}\n\n\t/**\n\t * Find a model by provider and ID.\n\t */\n\tfind(provider: string, modelId: string): Model<Api> | undefined {\n\t\treturn this.models.find((m) => m.provider === provider && m.id === modelId);\n\t}\n\n\t/**\n\t * Get API key for a model.\n\t */\n\thasConfiguredAuth(model: Model<Api>): boolean {\n\t\tconst providerApiKey = this.providerRequestConfigs.get(model.provider)?.apiKey;\n\t\treturn (\n\t\t\tthis.authStorage.hasAuth(model.provider) ||\n\t\t\t(providerApiKey !== undefined && isConfigValueConfigured(providerApiKey))\n\t\t);\n\t}\n\n\tprivate getModelRequestKey(provider: string, modelId: string): string {\n\t\treturn `${provider}:${modelId}`;\n\t}\n\n\tprivate storeProviderRequestConfig(\n\t\tproviderName: string,\n\t\tconfig: {\n\t\t\tapiKey?: string;\n\t\t\theaders?: Record<string, string>;\n\t\t\tauthHeader?: boolean;\n\t\t},\n\t): void {\n\t\tif (!config.apiKey && !config.headers && !config.authHeader) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.providerRequestConfigs.set(providerName, {\n\t\t\tapiKey: config.apiKey,\n\t\t\theaders: config.headers,\n\t\t\tauthHeader: config.authHeader,\n\t\t});\n\t}\n\n\tprivate storeModelHeaders(providerName: string, modelId: string, headers?: Record<string, string>): void {\n\t\tconst key = this.getModelRequestKey(providerName, modelId);\n\t\tif (!headers || Object.keys(headers).length === 0) {\n\t\t\tthis.modelRequestHeaders.delete(key);\n\t\t\treturn;\n\t\t}\n\t\tthis.modelRequestHeaders.set(key, headers);\n\t}\n\n\t/**\n\t * Get API key and request headers for a model.\n\t */\n\tasync getApiKeyAndHeaders(model: Model<Api>): Promise<ResolvedRequestAuth> {\n\t\treturn getModelRequestAuth(model, this.authStorage, this.providerRequestConfigs, this.modelRequestHeaders);\n\t}\n\n\t/**\n\t * Return auth status for a provider, including request auth configured in models.json.\n\t * This intentionally does not execute command-backed config values.\n\t */\n\tgetProviderAuthStatus(provider: string): AuthStatus {\n\t\treturn getProviderAuthStatusFromConfig(provider, this.authStorage, this.providerRequestConfigs);\n\t}\n\n\t/**\n\t * Get display name for a provider.\n\t */\n\tgetProviderDisplayName(provider: string): string {\n\t\tconst registeredProvider = this.registeredProviders.get(provider);\n\t\tconst oauthProvider = this.authStorage.getOAuthProviders().find((p) => p.id === provider);\n\n\t\treturn (\n\t\t\tregisteredProvider?.name ??\n\t\t\tregisteredProvider?.oauth?.name ??\n\t\t\toauthProvider?.name ??\n\t\t\tBUILT_IN_PROVIDER_DISPLAY_NAMES[provider] ??\n\t\t\tprovider\n\t\t);\n\t}\n\n\t/**\n\t * Get API key for a provider.\n\t */\n\tasync getApiKeyForProvider(provider: string): Promise<string | undefined> {\n\t\treturn getApiKeyForProviderFromConfig(provider, this.authStorage, this.providerRequestConfigs);\n\t}\n\n\t/**\n\t * Check if a model is using OAuth credentials (subscription).\n\t */\n\tisUsingOAuth(model: Model<Api>): boolean {\n\t\tconst cred = this.authStorage.get(model.provider);\n\t\treturn cred?.type === \"oauth\";\n\t}\n\n\t/**\n\t * Register a provider dynamically (from extensions).\n\t */\n\tregisterProvider(providerName: string, config: ProviderConfigInput): void {\n\t\tconst migratedConfig = migrateLegacyRegisterProviderConfigValues(providerName, config);\n\t\tvalidateProviderConfig(providerName, migratedConfig);\n\t\tthis.applyProviderConfig(providerName, migratedConfig);\n\t\tthis.upsertRegisteredProvider(providerName, migratedConfig);\n\t}\n\n\t/**\n\t * Check whether extensions have registered custom streamSimple dispatch for an API.\n\t */\n\thasRegisteredStreamSimpleForApi(api: Api): boolean {\n\t\tfor (const config of this.registeredProviders.values()) {\n\t\t\tif (config.api === api && config.streamSimple) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\t/**\n\t * Unregister a previously registered provider.\n\t */\n\tunregisterProvider(providerName: string): void {\n\t\tif (!this.registeredProviders.has(providerName)) return;\n\t\tthis.registeredProviders.delete(providerName);\n\t\tthis.refresh();\n\t}\n\n\tprivate upsertRegisteredProvider(providerName: string, config: ProviderConfigInput): void {\n\t\tconst existing = this.registeredProviders.get(providerName);\n\t\tif (!existing) {\n\t\t\tthis.registeredProviders.set(providerName, config);\n\t\t\treturn;\n\t\t}\n\t\tfor (const k of Object.keys(config) as (keyof ProviderConfigInput)[]) {\n\t\t\tif (config[k] !== undefined) {\n\t\t\t\t(existing as Record<string, unknown>)[k] = config[k];\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate applyProviderConfig(providerName: string, config: ProviderConfigInput): void {\n\t\tthis.models = applyProviderConfigToModels({\n\t\t\tproviderName,\n\t\t\tconfig,\n\t\t\tmodels: this.models,\n\t\t\tauthStorage: this.authStorage,\n\t\t\tstoreProviderRequestConfig: (name, requestConfig) => this.storeProviderRequestConfig(name, requestConfig),\n\t\t\tstoreModelHeaders: (name, modelId, headers) => this.storeModelHeaders(name, modelId, headers),\n\t\t});\n\t}\n}\n"]}
1
+ {"version":3,"file":"model-registry.js","sourceRoot":"","sources":["../../src/core/model-registry.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Model registry - manages built-in and custom models, provides API key resolution.\n */\n\nimport { type Api, type Model, resetApiProviders } from \"@earendil-works/pi-ai/compat\";\nimport { resetOAuthProviders } from \"@earendil-works/pi-ai/oauth\";\nimport { dirname } from \"node:path\";\nimport { getAgentConfigPaths } from \"../config.ts\";\nimport { normalizePath } from \"../utils/paths.ts\";\nimport type { AuthStatus, AuthStorage } from \"./auth-storage.ts\";\nimport { copilotCatalogCachePath, copilotTokenFromEnvironment, seedActiveCopilotModelCatalogFromCache } from \"./copilot-model-catalog.ts\";\nimport { getModelRequestAuth, getApiKeyForProviderFromConfig, getProviderAuthStatusFromConfig } from \"./model-registry-auth.ts\";\nimport { applyProviderConfigToModels, migrateLegacyRegisterProviderConfigValues, validateProviderConfig } from \"./model-registry-dynamic.ts\";\nimport { loadModelRegistryModels } from \"./model-registry-loader.ts\";\nimport type { ProviderConfigInput, ProviderRequestConfig, ResolvedRequestAuth } from \"./model-registry-types.ts\";\nimport { BUILT_IN_PROVIDER_DISPLAY_NAMES } from \"./provider-display-names.ts\";\nimport { clearConfigValueCache, isConfigValueConfigured } from \"./resolve-config-value.ts\";\n\nexport type { ProviderConfigInput, ResolvedRequestAuth } from \"./model-registry-types.ts\";\n\n/** Clear the config value command cache. Exported for testing. */\nexport const clearApiKeyCache = clearConfigValueCache;\n\n/**\n * Model registry - loads and manages models, resolves API keys via AuthStorage.\n */\nexport class ModelRegistry {\n\tprivate models: Model<Api>[] = [];\n\tprivate providerRequestConfigs: Map<string, ProviderRequestConfig> = new Map();\n\tprivate modelRequestHeaders: Map<string, Record<string, string>> = new Map();\n\tprivate registeredProviders: Map<string, ProviderConfigInput> = new Map();\n\tprivate loadError: string | undefined = undefined;\n\n\tdeclare readonly authStorage: AuthStorage;\n\tdeclare private modelsJsonPaths: string[];\n\n\tprivate constructor(\n\t\tauthStorage: AuthStorage,\n\t\tmodelsJsonPaths: string[],\n\t) {\n\t\tthis.authStorage = authStorage;\n\t\tthis.modelsJsonPaths = modelsJsonPaths.map((path) => normalizePath(path));\n\t\tthis.seedCopilotModelCatalogFromCache();\n\t\tthis.loadModels();\n\t}\n\n\tprivate seedCopilotModelCatalogFromCache(): void {\n\t\tif (this.modelsJsonPaths.length === 0) return;\n\t\tconst cred = this.authStorage.get(\"github-copilot\");\n\t\tconst token = cred?.type === \"oauth\" && typeof cred.access === \"string\" ? cred.access : copilotTokenFromEnvironment();\n\t\tif (!token) return;\n\t\tseedActiveCopilotModelCatalogFromCache(token, copilotCatalogCachePath(dirname(this.modelsJsonPaths[0])));\n\t}\n\n\tstatic create(\n\t\tauthStorage: AuthStorage,\n\t\tmodelsJsonPath: string | string[] = getAgentConfigPaths(\"models.json\"),\n\t): ModelRegistry {\n\t\treturn new ModelRegistry(authStorage, Array.isArray(modelsJsonPath) ? modelsJsonPath : [modelsJsonPath]);\n\t}\n\n\tstatic inMemory(authStorage: AuthStorage): ModelRegistry {\n\t\treturn new ModelRegistry(authStorage, []);\n\t}\n\n\t/**\n\t * Reload models from disk (built-in + custom from models.json).\n\t */\n\trefresh(): void {\n\t\tthis.providerRequestConfigs.clear();\n\t\tthis.modelRequestHeaders.clear();\n\t\tthis.loadError = undefined;\n\n\t\tresetApiProviders();\n\t\tresetOAuthProviders();\n\n\t\tthis.loadModels();\n\n\t\tfor (const [providerName, config] of this.registeredProviders.entries()) {\n\t\t\tthis.applyProviderConfig(providerName, config);\n\t\t}\n\t}\n\n\t/**\n\t * Get any error from loading models.json (undefined if no error).\n\t */\n\tgetError(): string | undefined {\n\t\treturn this.loadError;\n\t}\n\n\tprivate loadModels(): void {\n\t\tconst loaded = loadModelRegistryModels(this.authStorage, this.modelsJsonPaths);\n\t\tthis.models = loaded.models;\n\t\tthis.providerRequestConfigs = loaded.providerRequestConfigs;\n\t\tthis.modelRequestHeaders = loaded.modelRequestHeaders;\n\t\tthis.loadError = loaded.loadError;\n\t}\n\n\t/**\n\t * Get all models (built-in + custom).\n\t * If models.json had errors, returns only built-in models.\n\t */\n\tgetAll(): Model<Api>[] {\n\t\treturn this.models;\n\t}\n\n\t/**\n\t * Get only models that have auth configured.\n\t * This is a fast check that doesn't refresh OAuth tokens.\n\t */\n\tgetAvailable(): Model<Api>[] {\n\t\treturn this.models.filter((m) => this.hasConfiguredAuth(m));\n\t}\n\n\t/**\n\t * Find a model by provider and ID.\n\t */\n\tfind(provider: string, modelId: string): Model<Api> | undefined {\n\t\treturn this.models.find((m) => m.provider === provider && m.id === modelId);\n\t}\n\n\t/**\n\t * Get API key for a model.\n\t */\n\thasConfiguredAuth(model: Model<Api>): boolean {\n\t\tconst providerApiKey = this.providerRequestConfigs.get(model.provider)?.apiKey;\n\t\treturn (\n\t\t\tthis.authStorage.hasAuth(model.provider) ||\n\t\t\t(providerApiKey !== undefined && isConfigValueConfigured(providerApiKey))\n\t\t);\n\t}\n\n\tprivate getModelRequestKey(provider: string, modelId: string): string {\n\t\treturn `${provider}:${modelId}`;\n\t}\n\n\tprivate storeProviderRequestConfig(\n\t\tproviderName: string,\n\t\tconfig: {\n\t\t\tapiKey?: string;\n\t\t\theaders?: Record<string, string>;\n\t\t\tauthHeader?: boolean;\n\t\t},\n\t): void {\n\t\tif (!config.apiKey && !config.headers && !config.authHeader) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.providerRequestConfigs.set(providerName, {\n\t\t\tapiKey: config.apiKey,\n\t\t\theaders: config.headers,\n\t\t\tauthHeader: config.authHeader,\n\t\t});\n\t}\n\n\tprivate storeModelHeaders(providerName: string, modelId: string, headers?: Record<string, string>): void {\n\t\tconst key = this.getModelRequestKey(providerName, modelId);\n\t\tif (!headers || Object.keys(headers).length === 0) {\n\t\t\tthis.modelRequestHeaders.delete(key);\n\t\t\treturn;\n\t\t}\n\t\tthis.modelRequestHeaders.set(key, headers);\n\t}\n\n\t/**\n\t * Get API key and request headers for a model.\n\t */\n\tasync getApiKeyAndHeaders(model: Model<Api>): Promise<ResolvedRequestAuth> {\n\t\treturn getModelRequestAuth(model, this.authStorage, this.providerRequestConfigs, this.modelRequestHeaders);\n\t}\n\n\t/**\n\t * Return auth status for a provider, including request auth configured in models.json.\n\t * This intentionally does not execute command-backed config values.\n\t */\n\tgetProviderAuthStatus(provider: string): AuthStatus {\n\t\treturn getProviderAuthStatusFromConfig(provider, this.authStorage, this.providerRequestConfigs);\n\t}\n\n\t/**\n\t * Get display name for a provider.\n\t */\n\tgetProviderDisplayName(provider: string): string {\n\t\tconst registeredProvider = this.registeredProviders.get(provider);\n\t\tconst oauthProvider = this.authStorage.getOAuthProviders().find((p) => p.id === provider);\n\n\t\treturn (\n\t\t\tregisteredProvider?.name ??\n\t\t\tregisteredProvider?.oauth?.name ??\n\t\t\toauthProvider?.name ??\n\t\t\tBUILT_IN_PROVIDER_DISPLAY_NAMES[provider] ??\n\t\t\tprovider\n\t\t);\n\t}\n\n\t/**\n\t * Get API key for a provider.\n\t */\n\tasync getApiKeyForProvider(provider: string): Promise<string | undefined> {\n\t\treturn getApiKeyForProviderFromConfig(provider, this.authStorage, this.providerRequestConfigs);\n\t}\n\n\t/**\n\t * Check if a model is using OAuth credentials (subscription).\n\t */\n\tisUsingOAuth(model: Model<Api>): boolean {\n\t\tconst cred = this.authStorage.get(model.provider);\n\t\treturn cred?.type === \"oauth\";\n\t}\n\n\t/**\n\t * Register a provider dynamically (from extensions).\n\t */\n\tregisterProvider(providerName: string, config: ProviderConfigInput): void {\n\t\tconst migratedConfig = migrateLegacyRegisterProviderConfigValues(providerName, config);\n\t\tvalidateProviderConfig(providerName, migratedConfig);\n\t\tthis.applyProviderConfig(providerName, migratedConfig);\n\t\tthis.upsertRegisteredProvider(providerName, migratedConfig);\n\t}\n\n\t/**\n\t * Check whether extensions have registered custom streamSimple dispatch for an API.\n\t */\n\thasRegisteredStreamSimpleForApi(api: Api): boolean {\n\t\tfor (const config of this.registeredProviders.values()) {\n\t\t\tif (config.api === api && config.streamSimple) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\t/**\n\t * Unregister a previously registered provider.\n\t */\n\tunregisterProvider(providerName: string): void {\n\t\tif (!this.registeredProviders.has(providerName)) return;\n\t\tthis.registeredProviders.delete(providerName);\n\t\tthis.refresh();\n\t}\n\n\tprivate upsertRegisteredProvider(providerName: string, config: ProviderConfigInput): void {\n\t\tconst existing = this.registeredProviders.get(providerName);\n\t\tif (!existing) {\n\t\t\tthis.registeredProviders.set(providerName, config);\n\t\t\treturn;\n\t\t}\n\t\tfor (const k of Object.keys(config) as (keyof ProviderConfigInput)[]) {\n\t\t\tif (config[k] !== undefined) {\n\t\t\t\t(existing as Record<string, unknown>)[k] = config[k];\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate applyProviderConfig(providerName: string, config: ProviderConfigInput): void {\n\t\tthis.models = applyProviderConfigToModels({\n\t\t\tproviderName,\n\t\t\tconfig,\n\t\t\tmodels: this.models,\n\t\t\tauthStorage: this.authStorage,\n\t\t\tstoreProviderRequestConfig: (name, requestConfig) => this.storeProviderRequestConfig(name, requestConfig),\n\t\t\tstoreModelHeaders: (name, modelId, headers) => this.storeModelHeaders(name, modelId, headers),\n\t\t});\n\t}\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"model-resolver-defaults.d.ts","sourceRoot":"","sources":["../../src/core/model-resolver-defaults.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,8BAA8B,CAAC;AAE/D,gDAAgD;AAChD,eAAO,MAAM,uBAAuB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAmC1D,CAAC;AAEF,wBAAgB,2BAA2B,CAAC,eAAe,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,SAAS,CASjG","sourcesContent":["import type { Api, Model } from \"@earendil-works/pi-ai/compat\";\n\n/** Default model IDs for each known provider */\nexport const defaultModelPerProvider: Record<string, string> = {\n \"amazon-bedrock\": \"us.anthropic.claude-opus-4-6-v1\",\n anthropic: \"claude-opus-4-8\",\n openai: \"gpt-5.4\",\n \"azure-openai-responses\": \"gpt-5.4\",\n \"openai-codex\": \"gpt-5.5\",\n deepseek: \"deepseek-v4-pro\",\n google: \"gemini-3.1-pro-preview\",\n \"google-vertex\": \"gemini-3.1-pro-preview\",\n \"github-copilot\": \"gpt-5.4\",\n cursor: \"composer-2\",\n openrouter: \"moonshotai/kimi-k2.6\",\n \"vercel-ai-gateway\": \"zai/glm-5.1\",\n xai: \"grok-4.20-0309-reasoning\",\n groq: \"openai/gpt-oss-120b\",\n cerebras: \"zai-glm-4.7\",\n \"ant-ling\": \"Ring-2.6-1T\",\n zai: \"glm-5.1\",\n mistral: \"devstral-medium-latest\",\n minimax: \"MiniMax-M2.7\",\n \"minimax-cn\": \"MiniMax-M2.7\",\n moonshotai: \"kimi-k2.6\",\n \"moonshotai-cn\": \"kimi-k2.6\",\n huggingface: \"moonshotai/Kimi-K2.6\",\n fireworks: \"accounts/fireworks/models/kimi-k2p6\",\n together: \"moonshotai/Kimi-K2.6\",\n opencode: \"kimi-k2.6\",\n \"opencode-go\": \"kimi-k2.6\",\n \"kimi-coding\": \"kimi-for-coding\",\n \"cloudflare-workers-ai\": \"@cf/moonshotai/kimi-k2.6\",\n \"cloudflare-ai-gateway\": \"workers-ai/@cf/moonshotai/kimi-k2.6\",\n xiaomi: \"mimo-v2.5-pro\",\n \"xiaomi-token-plan-cn\": \"mimo-v2.5-pro\",\n \"xiaomi-token-plan-ams\": \"mimo-v2.5-pro\",\n \"xiaomi-token-plan-sgp\": \"mimo-v2.5-pro\",\n};\n\nexport function findPreferredAvailableModel(availableModels: Model<Api>[]): Model<Api> | undefined {\n for (const [provider, defaultId] of Object.entries(defaultModelPerProvider)) {\n const match = availableModels.find((m) => m.provider === provider && m.id === defaultId);\n if (match) {\n return match;\n }\n }\n\n return availableModels[0];\n}\n"]}
1
+ {"version":3,"file":"model-resolver-defaults.d.ts","sourceRoot":"","sources":["../../src/core/model-resolver-defaults.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,8BAA8B,CAAC;AAE/D,gDAAgD;AAChD,eAAO,MAAM,uBAAuB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAmC1D,CAAC;AAEF,wBAAgB,2BAA2B,CAAC,eAAe,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,SAAS,CASjG","sourcesContent":["import type { Api, Model } from \"@earendil-works/pi-ai/compat\";\n\n/** Default model IDs for each known provider */\nexport const defaultModelPerProvider: Record<string, string> = {\n \"amazon-bedrock\": \"us.anthropic.claude-opus-4-6-v1\",\n anthropic: \"claude-opus-4-8\",\n openai: \"gpt-5.5\",\n \"azure-openai-responses\": \"gpt-5.4\",\n \"openai-codex\": \"gpt-5.5\",\n deepseek: \"deepseek-v4-pro\",\n google: \"gemini-3.1-pro-preview\",\n \"google-vertex\": \"gemini-3.1-pro-preview\",\n \"github-copilot\": \"gpt-5.4\",\n cursor: \"composer-2\",\n openrouter: \"moonshotai/kimi-k2.6\",\n \"vercel-ai-gateway\": \"zai/glm-5.1\",\n xai: \"grok-4.20-0309-reasoning\",\n groq: \"openai/gpt-oss-120b\",\n cerebras: \"zai-glm-4.7\",\n \"ant-ling\": \"Ring-2.6-1T\",\n zai: \"glm-5.1\",\n mistral: \"devstral-medium-latest\",\n minimax: \"MiniMax-M2.7\",\n \"minimax-cn\": \"MiniMax-M2.7\",\n moonshotai: \"kimi-k2.6\",\n \"moonshotai-cn\": \"kimi-k2.6\",\n huggingface: \"moonshotai/Kimi-K2.6\",\n fireworks: \"accounts/fireworks/models/kimi-k2p6\",\n together: \"moonshotai/Kimi-K2.6\",\n opencode: \"kimi-k2.6\",\n \"opencode-go\": \"kimi-k2.6\",\n \"kimi-coding\": \"kimi-for-coding\",\n \"cloudflare-workers-ai\": \"@cf/moonshotai/kimi-k2.6\",\n \"cloudflare-ai-gateway\": \"workers-ai/@cf/moonshotai/kimi-k2.6\",\n xiaomi: \"mimo-v2.5-pro\",\n \"xiaomi-token-plan-cn\": \"mimo-v2.5-pro\",\n \"xiaomi-token-plan-ams\": \"mimo-v2.5-pro\",\n \"xiaomi-token-plan-sgp\": \"mimo-v2.5-pro\",\n};\n\nexport function findPreferredAvailableModel(availableModels: Model<Api>[]): Model<Api> | undefined {\n for (const [provider, defaultId] of Object.entries(defaultModelPerProvider)) {\n const match = availableModels.find((m) => m.provider === provider && m.id === defaultId);\n if (match) {\n return match;\n }\n }\n\n return availableModels[0];\n}\n"]}
@@ -2,7 +2,7 @@
2
2
  export const defaultModelPerProvider = {
3
3
  "amazon-bedrock": "us.anthropic.claude-opus-4-6-v1",
4
4
  anthropic: "claude-opus-4-8",
5
- openai: "gpt-5.4",
5
+ openai: "gpt-5.5",
6
6
  "azure-openai-responses": "gpt-5.4",
7
7
  "openai-codex": "gpt-5.5",
8
8
  deepseek: "deepseek-v4-pro",