gsd-pi 2.41.0 → 2.42.0-dev.1df898f

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 (494) hide show
  1. package/README.md +92 -29
  2. package/dist/cli-web-branch.d.ts +6 -0
  3. package/dist/cli-web-branch.js +17 -0
  4. package/dist/cli.js +18 -3
  5. package/dist/loader.js +3 -1
  6. package/dist/onboarding.js +2 -1
  7. package/dist/resource-loader.js +39 -6
  8. package/dist/resources/extensions/async-jobs/async-bash-tool.js +52 -4
  9. package/dist/resources/extensions/async-jobs/await-tool.js +5 -0
  10. package/dist/resources/extensions/async-jobs/index.js +2 -0
  11. package/dist/resources/extensions/gsd/auto/loop.js +89 -1
  12. package/dist/resources/extensions/gsd/auto/phases.js +29 -13
  13. package/dist/resources/extensions/gsd/auto/session.js +6 -0
  14. package/dist/resources/extensions/gsd/auto-dashboard.js +8 -2
  15. package/dist/resources/extensions/gsd/auto-dispatch.js +19 -2
  16. package/dist/resources/extensions/gsd/auto-post-unit.js +7 -0
  17. package/dist/resources/extensions/gsd/auto-prompts.js +3 -16
  18. package/dist/resources/extensions/gsd/auto-recovery.js +12 -4
  19. package/dist/resources/extensions/gsd/auto-start.js +16 -14
  20. package/dist/resources/extensions/gsd/auto-worktree.js +147 -13
  21. package/dist/resources/extensions/gsd/auto.js +64 -2
  22. package/dist/resources/extensions/gsd/bootstrap/db-tools.js +199 -164
  23. package/dist/resources/extensions/gsd/bootstrap/journal-tools.js +62 -0
  24. package/dist/resources/extensions/gsd/bootstrap/register-extension.js +2 -0
  25. package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +25 -3
  26. package/dist/resources/extensions/gsd/bootstrap/tool-call-loop-guard.js +7 -2
  27. package/dist/resources/extensions/gsd/commands/catalog.js +40 -1
  28. package/dist/resources/extensions/gsd/commands/handlers/core.js +1 -0
  29. package/dist/resources/extensions/gsd/commands/handlers/ops.js +5 -0
  30. package/dist/resources/extensions/gsd/commands/handlers/workflow.js +146 -0
  31. package/dist/resources/extensions/gsd/context-injector.js +74 -0
  32. package/dist/resources/extensions/gsd/context-store.js +4 -3
  33. package/dist/resources/extensions/gsd/custom-execution-policy.js +47 -0
  34. package/dist/resources/extensions/gsd/custom-verification.js +145 -0
  35. package/dist/resources/extensions/gsd/custom-workflow-engine.js +164 -0
  36. package/dist/resources/extensions/gsd/dashboard-overlay.js +1 -0
  37. package/dist/resources/extensions/gsd/db-writer.js +5 -2
  38. package/dist/resources/extensions/gsd/definition-loader.js +352 -0
  39. package/dist/resources/extensions/gsd/detection.js +20 -1
  40. package/dist/resources/extensions/gsd/dev-execution-policy.js +24 -0
  41. package/dist/resources/extensions/gsd/dev-workflow-engine.js +82 -0
  42. package/dist/resources/extensions/gsd/doctor-checks.js +31 -1
  43. package/dist/resources/extensions/gsd/doctor-providers.js +10 -0
  44. package/dist/resources/extensions/gsd/doctor.js +11 -1
  45. package/dist/resources/extensions/gsd/engine-resolver.js +40 -0
  46. package/dist/resources/extensions/gsd/engine-types.js +8 -0
  47. package/dist/resources/extensions/gsd/execution-policy.js +8 -0
  48. package/dist/resources/extensions/gsd/exit-command.js +12 -2
  49. package/dist/resources/extensions/gsd/export.js +9 -13
  50. package/dist/resources/extensions/gsd/extension-manifest.json +2 -2
  51. package/dist/resources/extensions/gsd/files.js +28 -11
  52. package/dist/resources/extensions/gsd/forensics.js +94 -3
  53. package/dist/resources/extensions/gsd/git-constants.js +1 -0
  54. package/dist/resources/extensions/gsd/git-service.js +6 -2
  55. package/dist/resources/extensions/gsd/graph.js +225 -0
  56. package/dist/resources/extensions/gsd/gsd-db.js +25 -8
  57. package/dist/resources/extensions/gsd/guided-flow-queue.js +1 -1
  58. package/dist/resources/extensions/gsd/guided-flow.js +7 -3
  59. package/dist/resources/extensions/gsd/journal.js +85 -0
  60. package/dist/resources/extensions/gsd/md-importer.js +5 -0
  61. package/dist/resources/extensions/gsd/milestone-ids.js +1 -1
  62. package/dist/resources/extensions/gsd/native-git-bridge.js +3 -2
  63. package/dist/resources/extensions/gsd/post-unit-hooks.js +24 -412
  64. package/dist/resources/extensions/gsd/preferences-types.js +2 -0
  65. package/dist/resources/extensions/gsd/preferences.js +60 -8
  66. package/dist/resources/extensions/gsd/prompt-loader.js +34 -4
  67. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +11 -10
  68. package/dist/resources/extensions/gsd/prompts/discuss-headless.md +2 -2
  69. package/dist/resources/extensions/gsd/prompts/discuss.md +1 -1
  70. package/dist/resources/extensions/gsd/prompts/forensics.md +12 -5
  71. package/dist/resources/extensions/gsd/prompts/queue.md +1 -1
  72. package/dist/resources/extensions/gsd/repo-identity.js +92 -7
  73. package/dist/resources/extensions/gsd/rule-registry.js +489 -0
  74. package/dist/resources/extensions/gsd/rule-types.js +6 -0
  75. package/dist/resources/extensions/gsd/run-manager.js +134 -0
  76. package/dist/resources/extensions/gsd/service-tier.js +147 -0
  77. package/dist/resources/extensions/gsd/session-lock.js +2 -2
  78. package/dist/resources/extensions/gsd/structured-data-formatter.js +2 -1
  79. package/dist/resources/extensions/gsd/templates/decisions.md +2 -2
  80. package/dist/resources/extensions/gsd/workflow-engine.js +7 -0
  81. package/dist/resources/extensions/gsd/workflow-templates.js +13 -1
  82. package/dist/resources/extensions/gsd/worktree-manager.js +20 -6
  83. package/dist/resources/extensions/gsd/worktree-resolver.js +21 -4
  84. package/dist/resources/extensions/gsd/worktree.js +2 -2
  85. package/dist/resources/extensions/mcp-client/index.js +2 -1
  86. package/dist/resources/extensions/search-the-web/tool-search.js +3 -3
  87. package/dist/resources/extensions/subagent/index.js +7 -3
  88. package/dist/resources/extensions/voice/index.js +4 -4
  89. package/dist/resources/skills/create-workflow/SKILL.md +103 -0
  90. package/dist/resources/skills/create-workflow/references/feature-patterns.md +128 -0
  91. package/dist/resources/skills/create-workflow/references/verification-policies.md +76 -0
  92. package/dist/resources/skills/create-workflow/references/yaml-schema-v1.md +46 -0
  93. package/dist/resources/skills/create-workflow/templates/blog-post-pipeline.yaml +60 -0
  94. package/dist/resources/skills/create-workflow/templates/code-audit.yaml +60 -0
  95. package/dist/resources/skills/create-workflow/templates/release-checklist.yaml +66 -0
  96. package/dist/resources/skills/create-workflow/templates/workflow-definition.yaml +32 -0
  97. package/dist/resources/skills/create-workflow/workflows/create-from-scratch.md +104 -0
  98. package/dist/resources/skills/create-workflow/workflows/create-from-template.md +72 -0
  99. package/dist/web/standalone/.next/BUILD_ID +1 -1
  100. package/dist/web/standalone/.next/app-path-routes-manifest.json +9 -9
  101. package/dist/web/standalone/.next/build-manifest.json +4 -4
  102. package/dist/web/standalone/.next/prerender-manifest.json +3 -3
  103. package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
  104. package/dist/web/standalone/.next/required-server-files.json +3 -3
  105. package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
  106. package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  107. package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
  108. package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
  109. package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  110. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  111. package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  112. package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  113. package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  114. package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  115. package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
  116. package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  117. package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
  118. package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
  119. package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  120. package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  121. package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  122. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  123. package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  124. package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  125. package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
  126. package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
  127. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
  128. package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
  129. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
  130. package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
  131. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
  132. package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
  133. package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
  134. package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
  135. package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
  136. package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
  137. package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
  138. package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
  139. package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
  140. package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
  141. package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
  142. package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
  143. package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
  144. package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
  145. package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
  146. package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
  147. package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
  148. package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
  149. package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
  150. package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
  151. package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
  152. package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
  153. package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
  154. package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
  155. package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
  156. package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
  157. package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
  158. package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
  159. package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
  160. package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
  161. package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
  162. package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
  163. package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
  164. package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
  165. package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
  166. package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  167. package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
  168. package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
  169. package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +5 -5
  170. package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
  171. package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
  172. package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
  173. package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
  174. package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
  175. package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
  176. package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
  177. package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
  178. package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
  179. package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
  180. package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
  181. package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
  182. package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
  183. package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
  184. package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
  185. package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
  186. package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
  187. package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
  188. package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
  189. package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
  190. package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
  191. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
  192. package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
  193. package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
  194. package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
  195. package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
  196. package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
  197. package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
  198. package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
  199. package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
  200. package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  201. package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
  202. package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
  203. package/dist/web/standalone/.next/server/app/index.html +1 -1
  204. package/dist/web/standalone/.next/server/app/index.rsc +4 -4
  205. package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  206. package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
  207. package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  208. package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
  209. package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  210. package/dist/web/standalone/.next/server/app/page.js +2 -2
  211. package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  212. package/dist/web/standalone/.next/server/app-paths-manifest.json +9 -9
  213. package/dist/web/standalone/.next/server/chunks/229.js +3 -3
  214. package/dist/web/standalone/.next/server/chunks/471.js +3 -3
  215. package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
  216. package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
  217. package/dist/web/standalone/.next/server/middleware.js +2 -2
  218. package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
  219. package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
  220. package/dist/web/standalone/.next/server/pages/404.html +1 -1
  221. package/dist/web/standalone/.next/server/pages/500.html +2 -2
  222. package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
  223. package/dist/web/standalone/.next/static/chunks/4024.c195dc1fdd2adbea.js +9 -0
  224. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-f2a7482d42a5614b.js +1 -0
  225. package/dist/web/standalone/.next/static/chunks/app/layout-a16c7a7ecdf0c2cf.js +1 -0
  226. package/dist/web/standalone/.next/static/chunks/app/page-b9367c5ae13b99c6.js +1 -0
  227. package/dist/web/standalone/.next/static/chunks/{main-app-2f2ee7b85712c2bd.js → main-app-fdab67f7802d7832.js} +1 -1
  228. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
  229. package/dist/web/standalone/.next/static/chunks/{webpack-9afaaebf6042a1d7.js → webpack-fa307370fcf9fb2c.js} +1 -1
  230. package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
  231. package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
  232. package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
  233. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
  234. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
  235. package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
  236. package/dist/web/standalone/server.js +1 -1
  237. package/dist/web-mode.d.ts +4 -0
  238. package/dist/web-mode.js +69 -11
  239. package/package.json +1 -1
  240. package/packages/native/src/__tests__/text.test.mjs +33 -0
  241. package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
  242. package/packages/pi-agent-core/dist/agent.js +2 -0
  243. package/packages/pi-agent-core/dist/agent.js.map +1 -1
  244. package/packages/pi-agent-core/dist/types.d.ts +6 -0
  245. package/packages/pi-agent-core/dist/types.d.ts.map +1 -1
  246. package/packages/pi-agent-core/dist/types.js.map +1 -1
  247. package/packages/pi-agent-core/src/agent.test.ts +53 -0
  248. package/packages/pi-agent-core/src/agent.ts +3 -0
  249. package/packages/pi-agent-core/src/types.ts +6 -0
  250. package/packages/pi-agent-core/tsconfig.json +1 -1
  251. package/packages/pi-ai/dist/models.d.ts +5 -3
  252. package/packages/pi-ai/dist/models.d.ts.map +1 -1
  253. package/packages/pi-ai/dist/models.generated.d.ts +801 -1468
  254. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  255. package/packages/pi-ai/dist/models.generated.js +1135 -1588
  256. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  257. package/packages/pi-ai/dist/models.js.map +1 -1
  258. package/packages/pi-ai/dist/utils/oauth/github-copilot.d.ts.map +1 -1
  259. package/packages/pi-ai/dist/utils/oauth/github-copilot.js +60 -2
  260. package/packages/pi-ai/dist/utils/oauth/github-copilot.js.map +1 -1
  261. package/packages/pi-ai/scripts/generate-models.ts +1543 -0
  262. package/packages/pi-ai/src/models.generated.ts +1140 -1593
  263. package/packages/pi-ai/src/models.ts +7 -4
  264. package/packages/pi-ai/src/utils/oauth/github-copilot.ts +74 -2
  265. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  266. package/packages/pi-coding-agent/dist/core/agent-session.js +8 -1
  267. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  268. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +7 -0
  269. package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
  270. package/packages/pi-coding-agent/dist/core/auth-storage.js +29 -2
  271. package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
  272. package/packages/pi-coding-agent/dist/core/auth-storage.test.js +60 -0
  273. package/packages/pi-coding-agent/dist/core/auth-storage.test.js.map +1 -1
  274. package/packages/pi-coding-agent/dist/core/discovery-cache.test.js +3 -1
  275. package/packages/pi-coding-agent/dist/core/discovery-cache.test.js.map +1 -1
  276. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  277. package/packages/pi-coding-agent/dist/core/extensions/loader.js +18 -0
  278. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  279. package/packages/pi-coding-agent/dist/core/lsp/client.d.ts.map +1 -1
  280. package/packages/pi-coding-agent/dist/core/lsp/client.js +23 -0
  281. package/packages/pi-coding-agent/dist/core/lsp/client.js.map +1 -1
  282. package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  283. package/packages/pi-coding-agent/dist/core/model-registry.js +2 -0
  284. package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  285. package/packages/pi-coding-agent/dist/core/package-manager.d.ts +6 -0
  286. package/packages/pi-coding-agent/dist/core/package-manager.d.ts.map +1 -1
  287. package/packages/pi-coding-agent/dist/core/package-manager.js +63 -11
  288. package/packages/pi-coding-agent/dist/core/package-manager.js.map +1 -1
  289. package/packages/pi-coding-agent/dist/core/resource-loader.d.ts +9 -0
  290. package/packages/pi-coding-agent/dist/core/resource-loader.d.ts.map +1 -1
  291. package/packages/pi-coding-agent/dist/core/resource-loader.js +20 -6
  292. package/packages/pi-coding-agent/dist/core/resource-loader.js.map +1 -1
  293. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
  294. package/packages/pi-coding-agent/dist/core/system-prompt.js +6 -5
  295. package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
  296. package/packages/pi-coding-agent/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
  297. package/packages/pi-coding-agent/dist/modes/interactive/components/extension-editor.js +3 -0
  298. package/packages/pi-coding-agent/dist/modes/interactive/components/extension-editor.js.map +1 -1
  299. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
  300. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +9 -6
  301. package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
  302. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  303. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.js +10 -7
  304. package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.js.map +1 -1
  305. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  306. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +34 -10
  307. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  308. package/packages/pi-coding-agent/package.json +1 -1
  309. package/packages/pi-coding-agent/src/core/agent-session.ts +7 -1
  310. package/packages/pi-coding-agent/src/core/auth-storage.test.ts +68 -0
  311. package/packages/pi-coding-agent/src/core/auth-storage.ts +30 -2
  312. package/packages/pi-coding-agent/src/core/discovery-cache.test.ts +4 -2
  313. package/packages/pi-coding-agent/src/core/extensions/loader.ts +18 -0
  314. package/packages/pi-coding-agent/src/core/lsp/client.ts +29 -0
  315. package/packages/pi-coding-agent/src/core/model-registry.ts +3 -0
  316. package/packages/pi-coding-agent/src/core/package-manager.ts +99 -58
  317. package/packages/pi-coding-agent/src/core/resource-loader.ts +24 -6
  318. package/packages/pi-coding-agent/src/core/system-prompt.ts +6 -5
  319. package/packages/pi-coding-agent/src/modes/interactive/components/extension-editor.ts +3 -0
  320. package/packages/pi-coding-agent/src/modes/interactive/components/footer.ts +10 -6
  321. package/packages/pi-coding-agent/src/modes/interactive/components/login-dialog.ts +11 -7
  322. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +36 -11
  323. package/pkg/package.json +1 -1
  324. package/src/resources/extensions/async-jobs/async-bash-timeout.test.ts +122 -0
  325. package/src/resources/extensions/async-jobs/async-bash-tool.ts +40 -4
  326. package/src/resources/extensions/async-jobs/await-tool.test.ts +47 -0
  327. package/src/resources/extensions/async-jobs/await-tool.ts +5 -0
  328. package/src/resources/extensions/async-jobs/index.ts +1 -0
  329. package/src/resources/extensions/async-jobs/job-manager.ts +2 -0
  330. package/src/resources/extensions/gsd/auto/loop-deps.ts +5 -2
  331. package/src/resources/extensions/gsd/auto/loop.ts +101 -1
  332. package/src/resources/extensions/gsd/auto/phases.ts +31 -13
  333. package/src/resources/extensions/gsd/auto/session.ts +6 -0
  334. package/src/resources/extensions/gsd/auto/types.ts +4 -0
  335. package/src/resources/extensions/gsd/auto-dashboard.ts +9 -2
  336. package/src/resources/extensions/gsd/auto-dispatch.ts +25 -5
  337. package/src/resources/extensions/gsd/auto-post-unit.ts +8 -0
  338. package/src/resources/extensions/gsd/auto-prompts.ts +2 -18
  339. package/src/resources/extensions/gsd/auto-recovery.ts +12 -4
  340. package/src/resources/extensions/gsd/auto-start.ts +15 -13
  341. package/src/resources/extensions/gsd/auto-worktree.ts +162 -18
  342. package/src/resources/extensions/gsd/auto.ts +71 -2
  343. package/src/resources/extensions/gsd/bootstrap/db-tools.ts +209 -162
  344. package/src/resources/extensions/gsd/bootstrap/journal-tools.ts +62 -0
  345. package/src/resources/extensions/gsd/bootstrap/register-extension.ts +2 -0
  346. package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +25 -4
  347. package/src/resources/extensions/gsd/bootstrap/tool-call-loop-guard.ts +9 -2
  348. package/src/resources/extensions/gsd/commands/catalog.ts +40 -1
  349. package/src/resources/extensions/gsd/commands/handlers/core.ts +1 -0
  350. package/src/resources/extensions/gsd/commands/handlers/ops.ts +5 -0
  351. package/src/resources/extensions/gsd/commands/handlers/workflow.ts +164 -0
  352. package/src/resources/extensions/gsd/context-injector.ts +100 -0
  353. package/src/resources/extensions/gsd/context-store.ts +4 -3
  354. package/src/resources/extensions/gsd/custom-execution-policy.ts +73 -0
  355. package/src/resources/extensions/gsd/custom-verification.ts +180 -0
  356. package/src/resources/extensions/gsd/custom-workflow-engine.ts +216 -0
  357. package/src/resources/extensions/gsd/dashboard-overlay.ts +1 -0
  358. package/src/resources/extensions/gsd/db-writer.ts +6 -2
  359. package/src/resources/extensions/gsd/definition-loader.ts +462 -0
  360. package/src/resources/extensions/gsd/detection.ts +20 -1
  361. package/src/resources/extensions/gsd/dev-execution-policy.ts +51 -0
  362. package/src/resources/extensions/gsd/dev-workflow-engine.ts +110 -0
  363. package/src/resources/extensions/gsd/doctor-checks.ts +32 -1
  364. package/src/resources/extensions/gsd/doctor-providers.ts +13 -0
  365. package/src/resources/extensions/gsd/doctor-types.ts +1 -0
  366. package/src/resources/extensions/gsd/doctor.ts +12 -1
  367. package/src/resources/extensions/gsd/engine-resolver.ts +57 -0
  368. package/src/resources/extensions/gsd/engine-types.ts +71 -0
  369. package/src/resources/extensions/gsd/execution-policy.ts +43 -0
  370. package/src/resources/extensions/gsd/exit-command.ts +14 -2
  371. package/src/resources/extensions/gsd/export.ts +8 -15
  372. package/src/resources/extensions/gsd/extension-manifest.json +2 -2
  373. package/src/resources/extensions/gsd/files.ts +29 -12
  374. package/src/resources/extensions/gsd/forensics.ts +101 -3
  375. package/src/resources/extensions/gsd/git-constants.ts +1 -0
  376. package/src/resources/extensions/gsd/git-service.ts +5 -5
  377. package/src/resources/extensions/gsd/gitignore.ts +1 -1
  378. package/src/resources/extensions/gsd/graph.ts +312 -0
  379. package/src/resources/extensions/gsd/gsd-db.ts +37 -8
  380. package/src/resources/extensions/gsd/guided-flow-queue.ts +1 -1
  381. package/src/resources/extensions/gsd/guided-flow.ts +7 -3
  382. package/src/resources/extensions/gsd/journal.ts +134 -0
  383. package/src/resources/extensions/gsd/md-importer.ts +6 -0
  384. package/src/resources/extensions/gsd/milestone-ids.ts +1 -1
  385. package/src/resources/extensions/gsd/native-git-bridge.ts +3 -2
  386. package/src/resources/extensions/gsd/post-unit-hooks.ts +24 -462
  387. package/src/resources/extensions/gsd/preferences-types.ts +6 -0
  388. package/src/resources/extensions/gsd/preferences.ts +63 -6
  389. package/src/resources/extensions/gsd/prompt-loader.ts +35 -4
  390. package/src/resources/extensions/gsd/prompts/complete-milestone.md +11 -10
  391. package/src/resources/extensions/gsd/prompts/discuss-headless.md +2 -2
  392. package/src/resources/extensions/gsd/prompts/discuss.md +1 -1
  393. package/src/resources/extensions/gsd/prompts/forensics.md +12 -5
  394. package/src/resources/extensions/gsd/prompts/queue.md +1 -1
  395. package/src/resources/extensions/gsd/repo-identity.ts +95 -7
  396. package/src/resources/extensions/gsd/rule-registry.ts +599 -0
  397. package/src/resources/extensions/gsd/rule-types.ts +68 -0
  398. package/src/resources/extensions/gsd/run-manager.ts +180 -0
  399. package/src/resources/extensions/gsd/service-tier.ts +184 -0
  400. package/src/resources/extensions/gsd/session-lock.ts +2 -2
  401. package/src/resources/extensions/gsd/structured-data-formatter.ts +3 -1
  402. package/src/resources/extensions/gsd/templates/decisions.md +2 -2
  403. package/src/resources/extensions/gsd/tests/activity-log.test.ts +31 -69
  404. package/src/resources/extensions/gsd/tests/auto-loop.test.ts +103 -120
  405. package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +85 -0
  406. package/src/resources/extensions/gsd/tests/auto-secrets-gate.test.ts +2 -2
  407. package/src/resources/extensions/gsd/tests/auto-worktree-milestone-merge.test.ts +202 -0
  408. package/src/resources/extensions/gsd/tests/bundled-workflow-defs.test.ts +180 -0
  409. package/src/resources/extensions/gsd/tests/captures.test.ts +12 -1
  410. package/src/resources/extensions/gsd/tests/commands-workflow-custom.test.ts +283 -0
  411. package/src/resources/extensions/gsd/tests/context-injector.test.ts +313 -0
  412. package/src/resources/extensions/gsd/tests/context-store.test.ts +10 -5
  413. package/src/resources/extensions/gsd/tests/continue-here.test.ts +20 -20
  414. package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +540 -0
  415. package/src/resources/extensions/gsd/tests/custom-verification.test.ts +382 -0
  416. package/src/resources/extensions/gsd/tests/custom-workflow-engine.test.ts +339 -0
  417. package/src/resources/extensions/gsd/tests/dashboard-custom-engine.test.ts +87 -0
  418. package/src/resources/extensions/gsd/tests/db-writer.test.ts +10 -0
  419. package/src/resources/extensions/gsd/tests/definition-loader.test.ts +778 -0
  420. package/src/resources/extensions/gsd/tests/dev-engine-wrapper.test.ts +318 -0
  421. package/src/resources/extensions/gsd/tests/doctor-completion-deferral.test.ts +15 -10
  422. package/src/resources/extensions/gsd/tests/doctor-fixlevel.test.ts +5 -4
  423. package/src/resources/extensions/gsd/tests/doctor-roadmap-summary-atomicity.test.ts +167 -0
  424. package/src/resources/extensions/gsd/tests/doctor-task-done-missing-summary-slice-loop.test.ts +174 -0
  425. package/src/resources/extensions/gsd/tests/e2e-workflow-pipeline-integration.test.ts +476 -0
  426. package/src/resources/extensions/gsd/tests/engine-interfaces-contract.test.ts +271 -0
  427. package/src/resources/extensions/gsd/tests/exit-command.test.ts +55 -0
  428. package/src/resources/extensions/gsd/tests/forensics-dedup.test.ts +48 -0
  429. package/src/resources/extensions/gsd/tests/forensics-issue-routing.test.ts +43 -0
  430. package/src/resources/extensions/gsd/tests/git-locale.test.ts +133 -0
  431. package/src/resources/extensions/gsd/tests/git-service.test.ts +44 -0
  432. package/src/resources/extensions/gsd/tests/graph-operations.test.ts +599 -0
  433. package/src/resources/extensions/gsd/tests/gsd-db.test.ts +8 -1
  434. package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +7 -7
  435. package/src/resources/extensions/gsd/tests/iterate-engine-integration.test.ts +429 -0
  436. package/src/resources/extensions/gsd/tests/journal-integration.test.ts +513 -0
  437. package/src/resources/extensions/gsd/tests/journal-query-tool.test.ts +147 -0
  438. package/src/resources/extensions/gsd/tests/journal.test.ts +341 -0
  439. package/src/resources/extensions/gsd/tests/manifest-status.test.ts +73 -82
  440. package/src/resources/extensions/gsd/tests/md-importer.test.ts +31 -1
  441. package/src/resources/extensions/gsd/tests/memory-store.test.ts +2 -2
  442. package/src/resources/extensions/gsd/tests/milestone-id-reservation.test.ts +1 -1
  443. package/src/resources/extensions/gsd/tests/parsers.test.ts +110 -0
  444. package/src/resources/extensions/gsd/tests/preferences.test.ts +47 -25
  445. package/src/resources/extensions/gsd/tests/prompt-db.test.ts +3 -1
  446. package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +61 -1
  447. package/src/resources/extensions/gsd/tests/routing-history.test.ts +11 -22
  448. package/src/resources/extensions/gsd/tests/rule-registry.test.ts +413 -0
  449. package/src/resources/extensions/gsd/tests/run-manager.test.ts +229 -0
  450. package/src/resources/extensions/gsd/tests/service-tier.test.ts +127 -0
  451. package/src/resources/extensions/gsd/tests/skill-activation.test.ts +56 -3
  452. package/src/resources/extensions/gsd/tests/skill-lifecycle.test.ts +2 -2
  453. package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +102 -0
  454. package/src/resources/extensions/gsd/tests/structured-data-formatter.test.ts +4 -3
  455. package/src/resources/extensions/gsd/tests/symlink-numbered-variants.test.ts +151 -0
  456. package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +45 -0
  457. package/src/resources/extensions/gsd/tests/tool-naming.test.ts +117 -0
  458. package/src/resources/extensions/gsd/tests/triage-dispatch.test.ts +6 -1
  459. package/src/resources/extensions/gsd/tests/verification-gate.test.ts +156 -263
  460. package/src/resources/extensions/gsd/tests/windows-path-normalization.test.ts +99 -0
  461. package/src/resources/extensions/gsd/tests/worktree-db-integration.test.ts +1 -0
  462. package/src/resources/extensions/gsd/tests/worktree-db.test.ts +4 -0
  463. package/src/resources/extensions/gsd/tests/worktree-health-dispatch.test.ts +135 -0
  464. package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +203 -106
  465. package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +79 -5
  466. package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +140 -0
  467. package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +74 -0
  468. package/src/resources/extensions/gsd/types.ts +3 -0
  469. package/src/resources/extensions/gsd/workflow-engine.ts +38 -0
  470. package/src/resources/extensions/gsd/workflow-templates.ts +12 -1
  471. package/src/resources/extensions/gsd/worktree-manager.ts +21 -6
  472. package/src/resources/extensions/gsd/worktree-resolver.ts +32 -12
  473. package/src/resources/extensions/gsd/worktree.ts +2 -2
  474. package/src/resources/extensions/mcp-client/index.ts +5 -1
  475. package/src/resources/extensions/search-the-web/tool-search.ts +3 -3
  476. package/src/resources/extensions/subagent/index.ts +7 -3
  477. package/src/resources/extensions/voice/index.ts +4 -4
  478. package/src/resources/skills/create-workflow/SKILL.md +103 -0
  479. package/src/resources/skills/create-workflow/references/feature-patterns.md +128 -0
  480. package/src/resources/skills/create-workflow/references/verification-policies.md +76 -0
  481. package/src/resources/skills/create-workflow/references/yaml-schema-v1.md +46 -0
  482. package/src/resources/skills/create-workflow/templates/blog-post-pipeline.yaml +60 -0
  483. package/src/resources/skills/create-workflow/templates/code-audit.yaml +60 -0
  484. package/src/resources/skills/create-workflow/templates/release-checklist.yaml +66 -0
  485. package/src/resources/skills/create-workflow/templates/workflow-definition.yaml +32 -0
  486. package/src/resources/skills/create-workflow/workflows/create-from-scratch.md +104 -0
  487. package/src/resources/skills/create-workflow/workflows/create-from-template.md +72 -0
  488. package/dist/web/standalone/.next/static/chunks/4024.279c423e4661ece1.js +0 -9
  489. package/dist/web/standalone/.next/static/chunks/app/_not-found/page-e07acdb7dd069836.js +0 -1
  490. package/dist/web/standalone/.next/static/chunks/app/layout-745c6ed5fea5fb06.js +0 -1
  491. package/dist/web/standalone/.next/static/chunks/app/page-801b53eff6e83579.js +0 -1
  492. package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-e6255954dccfcf0a.js +0 -1
  493. /package/dist/web/standalone/.next/static/{Ute3pMouVczQyT15qrBBO → qw8qDHXOTLUXBq1vEknSz}/_buildManifest.js +0 -0
  494. /package/dist/web/standalone/.next/static/{Ute3pMouVczQyT15qrBBO → qw8qDHXOTLUXBq1vEknSz}/_ssgManifest.js +0 -0
@@ -0,0 +1,1543 @@
1
+ #!/usr/bin/env tsx
2
+
3
+ import { writeFileSync } from "fs";
4
+ import { join, dirname } from "path";
5
+ import { fileURLToPath } from "url";
6
+ import { Api, KnownProvider, Model } from "../src/types.js";
7
+
8
+ const __filename = fileURLToPath(import.meta.url);
9
+ const __dirname = dirname(__filename);
10
+ const packageRoot = join(__dirname, "..");
11
+
12
+ interface ModelsDevModel {
13
+ id: string;
14
+ name: string;
15
+ tool_call?: boolean;
16
+ reasoning?: boolean;
17
+ limit?: {
18
+ context?: number;
19
+ output?: number;
20
+ };
21
+ cost?: {
22
+ input?: number;
23
+ output?: number;
24
+ cache_read?: number;
25
+ cache_write?: number;
26
+ };
27
+ modalities?: {
28
+ input?: string[];
29
+ };
30
+ provider?: {
31
+ npm?: string;
32
+ };
33
+ }
34
+
35
+ interface AiGatewayModel {
36
+ id: string;
37
+ name?: string;
38
+ context_window?: number;
39
+ max_tokens?: number;
40
+ tags?: string[];
41
+ pricing?: {
42
+ input?: string | number;
43
+ output?: string | number;
44
+ input_cache_read?: string | number;
45
+ input_cache_write?: string | number;
46
+ };
47
+ }
48
+
49
+ const COPILOT_STATIC_HEADERS = {
50
+ "User-Agent": "GitHubCopilotChat/0.35.0",
51
+ "Editor-Version": "vscode/1.107.0",
52
+ "Editor-Plugin-Version": "copilot-chat/0.35.0",
53
+ "Copilot-Integration-Id": "vscode-chat",
54
+ } as const;
55
+
56
+ const AI_GATEWAY_MODELS_URL = "https://ai-gateway.vercel.sh/v1";
57
+ const AI_GATEWAY_BASE_URL = "https://ai-gateway.vercel.sh";
58
+
59
+ async function fetchOpenRouterModels(): Promise<Model<any>[]> {
60
+ try {
61
+ console.log("Fetching models from OpenRouter API...");
62
+ const response = await fetch("https://openrouter.ai/api/v1/models");
63
+ const data = await response.json();
64
+
65
+ const models: Model<any>[] = [];
66
+
67
+ for (const model of data.data) {
68
+ // Only include models that support tools
69
+ if (!model.supported_parameters?.includes("tools")) continue;
70
+
71
+ // Parse provider from model ID
72
+ let provider: KnownProvider = "openrouter";
73
+ let modelKey = model.id;
74
+
75
+ modelKey = model.id; // Keep full ID for OpenRouter
76
+
77
+ // Parse input modalities
78
+ const input: ("text" | "image")[] = ["text"];
79
+ if (model.architecture?.modality?.includes("image")) {
80
+ input.push("image");
81
+ }
82
+
83
+ // Convert pricing from $/token to $/million tokens
84
+ const inputCost = parseFloat(model.pricing?.prompt || "0") * 1_000_000;
85
+ const outputCost = parseFloat(model.pricing?.completion || "0") * 1_000_000;
86
+ const cacheReadCost = parseFloat(model.pricing?.input_cache_read || "0") * 1_000_000;
87
+ const cacheWriteCost = parseFloat(model.pricing?.input_cache_write || "0") * 1_000_000;
88
+
89
+ const normalizedModel: Model<any> = {
90
+ id: modelKey,
91
+ name: model.name,
92
+ api: "openai-completions",
93
+ baseUrl: "https://openrouter.ai/api/v1",
94
+ provider,
95
+ reasoning: model.supported_parameters?.includes("reasoning") || false,
96
+ input,
97
+ cost: {
98
+ input: inputCost,
99
+ output: outputCost,
100
+ cacheRead: cacheReadCost,
101
+ cacheWrite: cacheWriteCost,
102
+ },
103
+ contextWindow: model.context_length || 4096,
104
+ maxTokens: model.top_provider?.max_completion_tokens || 4096,
105
+ };
106
+ models.push(normalizedModel);
107
+ }
108
+
109
+ console.log(`Fetched ${models.length} tool-capable models from OpenRouter`);
110
+ return models;
111
+ } catch (error) {
112
+ console.error("Failed to fetch OpenRouter models:", error);
113
+ return [];
114
+ }
115
+ }
116
+
117
+ async function fetchAiGatewayModels(): Promise<Model<any>[]> {
118
+ try {
119
+ console.log("Fetching models from Vercel AI Gateway API...");
120
+ const response = await fetch(`${AI_GATEWAY_MODELS_URL}/models`);
121
+ const data = await response.json();
122
+ const models: Model<any>[] = [];
123
+
124
+ const toNumber = (value: string | number | undefined): number => {
125
+ if (typeof value === "number") {
126
+ return Number.isFinite(value) ? value : 0;
127
+ }
128
+ const parsed = parseFloat(value ?? "0");
129
+ return Number.isFinite(parsed) ? parsed : 0;
130
+ };
131
+
132
+ const items = Array.isArray(data.data) ? (data.data as AiGatewayModel[]) : [];
133
+ for (const model of items) {
134
+ const tags = Array.isArray(model.tags) ? model.tags : [];
135
+ // Only include models that support tools
136
+ if (!tags.includes("tool-use")) continue;
137
+
138
+ const input: ("text" | "image")[] = ["text"];
139
+ if (tags.includes("vision")) {
140
+ input.push("image");
141
+ }
142
+
143
+ const inputCost = toNumber(model.pricing?.input) * 1_000_000;
144
+ const outputCost = toNumber(model.pricing?.output) * 1_000_000;
145
+ const cacheReadCost = toNumber(model.pricing?.input_cache_read) * 1_000_000;
146
+ const cacheWriteCost = toNumber(model.pricing?.input_cache_write) * 1_000_000;
147
+
148
+ models.push({
149
+ id: model.id,
150
+ name: model.name || model.id,
151
+ api: "anthropic-messages",
152
+ baseUrl: AI_GATEWAY_BASE_URL,
153
+ provider: "vercel-ai-gateway",
154
+ reasoning: tags.includes("reasoning"),
155
+ input,
156
+ cost: {
157
+ input: inputCost,
158
+ output: outputCost,
159
+ cacheRead: cacheReadCost,
160
+ cacheWrite: cacheWriteCost,
161
+ },
162
+ contextWindow: model.context_window || 4096,
163
+ maxTokens: model.max_tokens || 4096,
164
+ });
165
+ }
166
+
167
+ console.log(`Fetched ${models.length} tool-capable models from Vercel AI Gateway`);
168
+ return models;
169
+ } catch (error) {
170
+ console.error("Failed to fetch Vercel AI Gateway models:", error);
171
+ return [];
172
+ }
173
+ }
174
+
175
+ async function loadModelsDevData(): Promise<Model<any>[]> {
176
+ try {
177
+ console.log("Fetching models from models.dev API...");
178
+ const response = await fetch("https://models.dev/api.json");
179
+ const data = await response.json();
180
+
181
+ const models: Model<any>[] = [];
182
+
183
+ // Process Amazon Bedrock models
184
+ if (data["amazon-bedrock"]?.models) {
185
+ for (const [modelId, model] of Object.entries(data["amazon-bedrock"].models)) {
186
+ const m = model as ModelsDevModel;
187
+ if (m.tool_call !== true) continue;
188
+
189
+ let id = modelId;
190
+
191
+ if (id.startsWith("ai21.jamba")) {
192
+ // These models doesn't support tool use in streaming mode
193
+ continue;
194
+ }
195
+
196
+ if (id.startsWith("mistral.mistral-7b-instruct-v0")) {
197
+ // These models doesn't support system messages
198
+ continue;
199
+ }
200
+
201
+ models.push({
202
+ id,
203
+ name: m.name || id,
204
+ api: "bedrock-converse-stream" as const,
205
+ provider: "amazon-bedrock" as const,
206
+ baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
207
+ reasoning: m.reasoning === true,
208
+ input: (m.modalities?.input?.includes("image") ? ["text", "image"] : ["text"]) as ("text" | "image")[],
209
+ cost: {
210
+ input: m.cost?.input || 0,
211
+ output: m.cost?.output || 0,
212
+ cacheRead: m.cost?.cache_read || 0,
213
+ cacheWrite: m.cost?.cache_write || 0,
214
+ },
215
+ contextWindow: m.limit?.context || 4096,
216
+ maxTokens: m.limit?.output || 4096,
217
+ });
218
+ }
219
+ }
220
+
221
+ // Process Anthropic models
222
+ if (data.anthropic?.models) {
223
+ for (const [modelId, model] of Object.entries(data.anthropic.models)) {
224
+ const m = model as ModelsDevModel;
225
+ if (m.tool_call !== true) continue;
226
+
227
+ models.push({
228
+ id: modelId,
229
+ name: m.name || modelId,
230
+ api: "anthropic-messages",
231
+ provider: "anthropic",
232
+ baseUrl: "https://api.anthropic.com",
233
+ reasoning: m.reasoning === true,
234
+ input: m.modalities?.input?.includes("image") ? ["text", "image"] : ["text"],
235
+ cost: {
236
+ input: m.cost?.input || 0,
237
+ output: m.cost?.output || 0,
238
+ cacheRead: m.cost?.cache_read || 0,
239
+ cacheWrite: m.cost?.cache_write || 0,
240
+ },
241
+ contextWindow: m.limit?.context || 4096,
242
+ maxTokens: m.limit?.output || 4096,
243
+ });
244
+ }
245
+ }
246
+
247
+ // Process Google models
248
+ if (data.google?.models) {
249
+ for (const [modelId, model] of Object.entries(data.google.models)) {
250
+ const m = model as ModelsDevModel;
251
+ if (m.tool_call !== true) continue;
252
+
253
+ models.push({
254
+ id: modelId,
255
+ name: m.name || modelId,
256
+ api: "google-generative-ai",
257
+ provider: "google",
258
+ baseUrl: "https://generativelanguage.googleapis.com/v1beta",
259
+ reasoning: m.reasoning === true,
260
+ input: m.modalities?.input?.includes("image") ? ["text", "image"] : ["text"],
261
+ cost: {
262
+ input: m.cost?.input || 0,
263
+ output: m.cost?.output || 0,
264
+ cacheRead: m.cost?.cache_read || 0,
265
+ cacheWrite: m.cost?.cache_write || 0,
266
+ },
267
+ contextWindow: m.limit?.context || 4096,
268
+ maxTokens: m.limit?.output || 4096,
269
+ });
270
+ }
271
+ }
272
+
273
+ // Process OpenAI models
274
+ if (data.openai?.models) {
275
+ for (const [modelId, model] of Object.entries(data.openai.models)) {
276
+ const m = model as ModelsDevModel;
277
+ if (m.tool_call !== true) continue;
278
+
279
+ models.push({
280
+ id: modelId,
281
+ name: m.name || modelId,
282
+ api: "openai-responses",
283
+ provider: "openai",
284
+ baseUrl: "https://api.openai.com/v1",
285
+ reasoning: m.reasoning === true,
286
+ input: m.modalities?.input?.includes("image") ? ["text", "image"] : ["text"],
287
+ cost: {
288
+ input: m.cost?.input || 0,
289
+ output: m.cost?.output || 0,
290
+ cacheRead: m.cost?.cache_read || 0,
291
+ cacheWrite: m.cost?.cache_write || 0,
292
+ },
293
+ contextWindow: m.limit?.context || 4096,
294
+ maxTokens: m.limit?.output || 4096,
295
+ });
296
+ }
297
+ }
298
+
299
+ // Process Groq models
300
+ if (data.groq?.models) {
301
+ for (const [modelId, model] of Object.entries(data.groq.models)) {
302
+ const m = model as ModelsDevModel;
303
+ if (m.tool_call !== true) continue;
304
+
305
+ models.push({
306
+ id: modelId,
307
+ name: m.name || modelId,
308
+ api: "openai-completions",
309
+ provider: "groq",
310
+ baseUrl: "https://api.groq.com/openai/v1",
311
+ reasoning: m.reasoning === true,
312
+ input: m.modalities?.input?.includes("image") ? ["text", "image"] : ["text"],
313
+ cost: {
314
+ input: m.cost?.input || 0,
315
+ output: m.cost?.output || 0,
316
+ cacheRead: m.cost?.cache_read || 0,
317
+ cacheWrite: m.cost?.cache_write || 0,
318
+ },
319
+ contextWindow: m.limit?.context || 4096,
320
+ maxTokens: m.limit?.output || 4096,
321
+ });
322
+ }
323
+ }
324
+
325
+ // Process Cerebras models
326
+ if (data.cerebras?.models) {
327
+ for (const [modelId, model] of Object.entries(data.cerebras.models)) {
328
+ const m = model as ModelsDevModel;
329
+ if (m.tool_call !== true) continue;
330
+
331
+ models.push({
332
+ id: modelId,
333
+ name: m.name || modelId,
334
+ api: "openai-completions",
335
+ provider: "cerebras",
336
+ baseUrl: "https://api.cerebras.ai/v1",
337
+ reasoning: m.reasoning === true,
338
+ input: m.modalities?.input?.includes("image") ? ["text", "image"] : ["text"],
339
+ cost: {
340
+ input: m.cost?.input || 0,
341
+ output: m.cost?.output || 0,
342
+ cacheRead: m.cost?.cache_read || 0,
343
+ cacheWrite: m.cost?.cache_write || 0,
344
+ },
345
+ contextWindow: m.limit?.context || 4096,
346
+ maxTokens: m.limit?.output || 4096,
347
+ });
348
+ }
349
+ }
350
+
351
+ // Process xAi models
352
+ if (data.xai?.models) {
353
+ for (const [modelId, model] of Object.entries(data.xai.models)) {
354
+ const m = model as ModelsDevModel;
355
+ if (m.tool_call !== true) continue;
356
+
357
+ models.push({
358
+ id: modelId,
359
+ name: m.name || modelId,
360
+ api: "openai-completions",
361
+ provider: "xai",
362
+ baseUrl: "https://api.x.ai/v1",
363
+ reasoning: m.reasoning === true,
364
+ input: m.modalities?.input?.includes("image") ? ["text", "image"] : ["text"],
365
+ cost: {
366
+ input: m.cost?.input || 0,
367
+ output: m.cost?.output || 0,
368
+ cacheRead: m.cost?.cache_read || 0,
369
+ cacheWrite: m.cost?.cache_write || 0,
370
+ },
371
+ contextWindow: m.limit?.context || 4096,
372
+ maxTokens: m.limit?.output || 4096,
373
+ });
374
+ }
375
+ }
376
+
377
+ // Process zAi models
378
+ if (data.zai?.models) {
379
+ for (const [modelId, model] of Object.entries(data.zai.models)) {
380
+ const m = model as ModelsDevModel;
381
+ if (m.tool_call !== true) continue;
382
+ const supportsImage = m.modalities?.input?.includes("image")
383
+
384
+ models.push({
385
+ id: modelId,
386
+ name: m.name || modelId,
387
+ api: "openai-completions",
388
+ provider: "zai",
389
+ baseUrl: "https://api.z.ai/api/coding/paas/v4",
390
+ reasoning: m.reasoning === true,
391
+ input: supportsImage ? ["text", "image"] : ["text"],
392
+ cost: {
393
+ input: m.cost?.input || 0,
394
+ output: m.cost?.output || 0,
395
+ cacheRead: m.cost?.cache_read || 0,
396
+ cacheWrite: m.cost?.cache_write || 0,
397
+ },
398
+ compat: {
399
+ supportsDeveloperRole: false,
400
+ thinkingFormat: "zai",
401
+ },
402
+ contextWindow: m.limit?.context || 4096,
403
+ maxTokens: m.limit?.output || 4096,
404
+ });
405
+ }
406
+ }
407
+
408
+ // Process Mistral models
409
+ if (data.mistral?.models) {
410
+ for (const [modelId, model] of Object.entries(data.mistral.models)) {
411
+ const m = model as ModelsDevModel;
412
+ if (m.tool_call !== true) continue;
413
+
414
+ models.push({
415
+ id: modelId,
416
+ name: m.name || modelId,
417
+ api: "mistral-conversations",
418
+ provider: "mistral",
419
+ baseUrl: "https://api.mistral.ai",
420
+ reasoning: m.reasoning === true,
421
+ input: m.modalities?.input?.includes("image") ? ["text", "image"] : ["text"],
422
+ cost: {
423
+ input: m.cost?.input || 0,
424
+ output: m.cost?.output || 0,
425
+ cacheRead: m.cost?.cache_read || 0,
426
+ cacheWrite: m.cost?.cache_write || 0,
427
+ },
428
+ contextWindow: m.limit?.context || 4096,
429
+ maxTokens: m.limit?.output || 4096,
430
+ });
431
+ }
432
+ }
433
+
434
+ // Process Hugging Face models
435
+ if (data.huggingface?.models) {
436
+ for (const [modelId, model] of Object.entries(data.huggingface.models)) {
437
+ const m = model as ModelsDevModel;
438
+ if (m.tool_call !== true) continue;
439
+
440
+ models.push({
441
+ id: modelId,
442
+ name: m.name || modelId,
443
+ api: "openai-completions",
444
+ provider: "huggingface",
445
+ baseUrl: "https://router.huggingface.co/v1",
446
+ reasoning: m.reasoning === true,
447
+ input: m.modalities?.input?.includes("image") ? ["text", "image"] : ["text"],
448
+ cost: {
449
+ input: m.cost?.input || 0,
450
+ output: m.cost?.output || 0,
451
+ cacheRead: m.cost?.cache_read || 0,
452
+ cacheWrite: m.cost?.cache_write || 0,
453
+ },
454
+ compat: {
455
+ supportsDeveloperRole: false,
456
+ },
457
+ contextWindow: m.limit?.context || 4096,
458
+ maxTokens: m.limit?.output || 4096,
459
+ });
460
+ }
461
+ }
462
+
463
+ // Process OpenCode models (Zen and Go)
464
+ // API mapping based on provider.npm field:
465
+ // - @ai-sdk/openai → openai-responses
466
+ // - @ai-sdk/anthropic → anthropic-messages
467
+ // - @ai-sdk/google → google-generative-ai
468
+ // - null/undefined/@ai-sdk/openai-compatible → openai-completions
469
+ const opencodeVariants = [
470
+ { key: "opencode", provider: "opencode", basePath: "https://opencode.ai/zen" },
471
+ { key: "opencode-go", provider: "opencode-go", basePath: "https://opencode.ai/zen/go" },
472
+ ] as const;
473
+
474
+ for (const variant of opencodeVariants) {
475
+ if (!data[variant.key]?.models) continue;
476
+
477
+ for (const [modelId, model] of Object.entries(data[variant.key].models)) {
478
+ const m = model as ModelsDevModel & { status?: string };
479
+ if (m.tool_call !== true) continue;
480
+ if (m.status === "deprecated") continue;
481
+
482
+ const npm = m.provider?.npm;
483
+ let api: Api;
484
+ let baseUrl: string;
485
+
486
+ if (npm === "@ai-sdk/openai") {
487
+ api = "openai-responses";
488
+ baseUrl = `${variant.basePath}/v1`;
489
+ } else if (npm === "@ai-sdk/anthropic") {
490
+ api = "anthropic-messages";
491
+ // Anthropic SDK appends /v1/messages to baseURL
492
+ baseUrl = variant.basePath;
493
+ } else if (npm === "@ai-sdk/google") {
494
+ api = "google-generative-ai";
495
+ baseUrl = `${variant.basePath}/v1`;
496
+ } else {
497
+ // null, undefined, or @ai-sdk/openai-compatible
498
+ api = "openai-completions";
499
+ baseUrl = `${variant.basePath}/v1`;
500
+ }
501
+
502
+ models.push({
503
+ id: modelId,
504
+ name: m.name || modelId,
505
+ api,
506
+ provider: variant.provider,
507
+ baseUrl,
508
+ reasoning: m.reasoning === true,
509
+ input: m.modalities?.input?.includes("image") ? ["text", "image"] : ["text"],
510
+ cost: {
511
+ input: m.cost?.input || 0,
512
+ output: m.cost?.output || 0,
513
+ cacheRead: m.cost?.cache_read || 0,
514
+ cacheWrite: m.cost?.cache_write || 0,
515
+ },
516
+ contextWindow: m.limit?.context || 4096,
517
+ maxTokens: m.limit?.output || 4096,
518
+ });
519
+ }
520
+ }
521
+
522
+ // Process GitHub Copilot models
523
+ if (data["github-copilot"]?.models) {
524
+ for (const [modelId, model] of Object.entries(data["github-copilot"].models)) {
525
+ const m = model as ModelsDevModel & { status?: string };
526
+ if (m.tool_call !== true) continue;
527
+ if (m.status === "deprecated") continue;
528
+
529
+ // Claude 4.x models route to Anthropic Messages API
530
+ const isCopilotClaude4 = /^claude-(haiku|sonnet|opus)-4([.\-]|$)/.test(modelId);
531
+ // gpt-5 models require responses API, others use completions
532
+ const needsResponsesApi = modelId.startsWith("gpt-5") || modelId.startsWith("oswe");
533
+
534
+ const api: Api = isCopilotClaude4
535
+ ? "anthropic-messages"
536
+ : needsResponsesApi
537
+ ? "openai-responses"
538
+ : "openai-completions";
539
+
540
+ const copilotModel: Model<any> = {
541
+ id: modelId,
542
+ name: m.name || modelId,
543
+ api,
544
+ provider: "github-copilot",
545
+ baseUrl: "https://api.individual.githubcopilot.com",
546
+ reasoning: m.reasoning === true,
547
+ input: m.modalities?.input?.includes("image") ? ["text", "image"] : ["text"],
548
+ cost: {
549
+ input: m.cost?.input || 0,
550
+ output: m.cost?.output || 0,
551
+ cacheRead: m.cost?.cache_read || 0,
552
+ cacheWrite: m.cost?.cache_write || 0,
553
+ },
554
+ contextWindow: m.limit?.context || 128000,
555
+ maxTokens: m.limit?.output || 8192,
556
+ headers: { ...COPILOT_STATIC_HEADERS },
557
+ // compat only applies to openai-completions
558
+ ...(api === "openai-completions" ? {
559
+ compat: {
560
+ supportsStore: false,
561
+ supportsDeveloperRole: false,
562
+ supportsReasoningEffort: false,
563
+ },
564
+ } : {}),
565
+ };
566
+
567
+ models.push(copilotModel);
568
+ }
569
+ }
570
+
571
+ // Process MiniMax models
572
+ const minimaxVariants = [
573
+ { key: "minimax", provider: "minimax", baseUrl: "https://api.minimax.io/anthropic" },
574
+ { key: "minimax-cn", provider: "minimax-cn", baseUrl: "https://api.minimaxi.com/anthropic" },
575
+ ] as const;
576
+
577
+ for (const { key, provider, baseUrl } of minimaxVariants) {
578
+ if (data[key]?.models) {
579
+ for (const [modelId, model] of Object.entries(data[key].models)) {
580
+ const m = model as ModelsDevModel;
581
+ if (m.tool_call !== true) continue;
582
+
583
+ models.push({
584
+ id: modelId,
585
+ name: m.name || modelId,
586
+ api: "anthropic-messages",
587
+ provider,
588
+ // MiniMax's Anthropic-compatible API - SDK appends /v1/messages
589
+ baseUrl,
590
+ reasoning: m.reasoning === true,
591
+ input: m.modalities?.input?.includes("image") ? ["text", "image"] : ["text"],
592
+ cost: {
593
+ input: m.cost?.input || 0,
594
+ output: m.cost?.output || 0,
595
+ cacheRead: m.cost?.cache_read || 0,
596
+ cacheWrite: m.cost?.cache_write || 0,
597
+ },
598
+ contextWindow: m.limit?.context || 4096,
599
+ maxTokens: m.limit?.output || 4096,
600
+ });
601
+ }
602
+ }
603
+ }
604
+
605
+ // Process Kimi For Coding models
606
+ if (data["kimi-for-coding"]?.models) {
607
+ for (const [modelId, model] of Object.entries(data["kimi-for-coding"].models)) {
608
+ const m = model as ModelsDevModel;
609
+ if (m.tool_call !== true) continue;
610
+
611
+ models.push({
612
+ id: modelId,
613
+ name: m.name || modelId,
614
+ api: "anthropic-messages",
615
+ provider: "kimi-coding",
616
+ // Kimi For Coding's Anthropic-compatible API - SDK appends /v1/messages
617
+ baseUrl: "https://api.kimi.com/coding",
618
+ reasoning: m.reasoning === true,
619
+ input: m.modalities?.input?.includes("image") ? ["text", "image"] : ["text"],
620
+ cost: {
621
+ input: m.cost?.input || 0,
622
+ output: m.cost?.output || 0,
623
+ cacheRead: m.cost?.cache_read || 0,
624
+ cacheWrite: m.cost?.cache_write || 0,
625
+ },
626
+ contextWindow: m.limit?.context || 4096,
627
+ maxTokens: m.limit?.output || 4096,
628
+ });
629
+ }
630
+ }
631
+
632
+ console.log(`Loaded ${models.length} tool-capable models from models.dev`);
633
+ return models;
634
+ } catch (error) {
635
+ console.error("Failed to load models.dev data:", error);
636
+ return [];
637
+ }
638
+ }
639
+
640
+ async function generateModels() {
641
+ // Fetch models from both sources
642
+ // models.dev: Anthropic, Google, OpenAI, Groq, Cerebras
643
+ // OpenRouter: xAI and other providers (excluding Anthropic, Google, OpenAI)
644
+ // AI Gateway: OpenAI-compatible catalog with tool-capable models
645
+ const modelsDevModels = await loadModelsDevData();
646
+ const openRouterModels = await fetchOpenRouterModels();
647
+ const aiGatewayModels = await fetchAiGatewayModels();
648
+
649
+ // Combine models (models.dev has priority)
650
+ const allModels = [...modelsDevModels, ...openRouterModels, ...aiGatewayModels].filter(
651
+ (model) =>
652
+ !((model.provider === "opencode" || model.provider === "opencode-go") && model.id === "gpt-5.3-codex-spark"),
653
+ );
654
+
655
+ // Fix incorrect cache pricing for Claude Opus 4.5 from models.dev
656
+ // models.dev has 3x the correct pricing (1.5/18.75 instead of 0.5/6.25)
657
+ const opus45 = allModels.find(m => m.provider === "anthropic" && m.id === "claude-opus-4-5");
658
+ if (opus45) {
659
+ opus45.cost.cacheRead = 0.5;
660
+ opus45.cost.cacheWrite = 6.25;
661
+ }
662
+
663
+ // Temporary overrides until upstream model metadata is corrected.
664
+ for (const candidate of allModels) {
665
+ if (candidate.provider === "amazon-bedrock" && candidate.id.includes("anthropic.claude-opus-4-6-v1")) {
666
+ candidate.cost.cacheRead = 0.5;
667
+ candidate.cost.cacheWrite = 6.25;
668
+ candidate.contextWindow = 1000000;
669
+ }
670
+ if (candidate.provider === "amazon-bedrock" && candidate.id.includes("anthropic.claude-sonnet-4-6")) {
671
+ candidate.contextWindow = 1000000;
672
+ }
673
+ if (
674
+ (candidate.provider === "anthropic" ||
675
+ candidate.provider === "opencode" ||
676
+ candidate.provider === "opencode-go") &&
677
+ (candidate.id === "claude-opus-4-6" ||
678
+ candidate.id === "claude-sonnet-4-6" ||
679
+ candidate.id === "claude-opus-4.6" ||
680
+ candidate.id === "claude-sonnet-4.6")
681
+ ) {
682
+ candidate.contextWindow = 1000000;
683
+ }
684
+ if (
685
+ candidate.provider === "google-antigravity" &&
686
+ (candidate.id === "claude-opus-4-6-thinking" || candidate.id === "claude-sonnet-4-6")
687
+ ) {
688
+ candidate.contextWindow = 1000000;
689
+ }
690
+ // OpenCode variants list Claude Sonnet 4/4.5 with 1M context, actual limit is 200K
691
+ if (
692
+ (candidate.provider === "opencode" || candidate.provider === "opencode-go") &&
693
+ (candidate.id === "claude-sonnet-4-5" || candidate.id === "claude-sonnet-4")
694
+ ) {
695
+ candidate.contextWindow = 200000;
696
+ }
697
+ if ((candidate.provider === "opencode" || candidate.provider === "opencode-go") && candidate.id === "gpt-5.4") {
698
+ candidate.contextWindow = 272000;
699
+ candidate.maxTokens = 128000;
700
+ }
701
+ if (candidate.provider === "openai" && candidate.id === "gpt-5.4") {
702
+ candidate.contextWindow = 272000;
703
+ candidate.maxTokens = 128000;
704
+ }
705
+ // Keep selected OpenRouter model metadata stable until upstream settles.
706
+ if (candidate.provider === "openrouter" && candidate.id === "moonshotai/kimi-k2.5") {
707
+ candidate.cost.input = 0.41;
708
+ candidate.cost.output = 2.06;
709
+ candidate.cost.cacheRead = 0.07;
710
+ candidate.maxTokens = 4096;
711
+ }
712
+ if (candidate.provider === "openrouter" && candidate.id === "z-ai/glm-5") {
713
+ candidate.cost.input = 0.6;
714
+ candidate.cost.output = 1.9;
715
+ candidate.cost.cacheRead = 0.119;
716
+ }
717
+ }
718
+
719
+
720
+ // Add missing EU Opus 4.6 profile
721
+ if (!allModels.some((m) => m.provider === "amazon-bedrock" && m.id === "eu.anthropic.claude-opus-4-6-v1")) {
722
+ allModels.push({
723
+ id: "eu.anthropic.claude-opus-4-6-v1",
724
+ name: "Claude Opus 4.6 (EU)",
725
+ api: "bedrock-converse-stream",
726
+ provider: "amazon-bedrock",
727
+ baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com",
728
+ reasoning: true,
729
+ input: ["text", "image"],
730
+ cost: {
731
+ input: 5,
732
+ output: 25,
733
+ cacheRead: 0.5,
734
+ cacheWrite: 6.25,
735
+ },
736
+ contextWindow: 1000000,
737
+ maxTokens: 128000,
738
+ });
739
+ }
740
+
741
+ // Add missing Claude Opus 4.6
742
+ if (!allModels.some(m => m.provider === "anthropic" && m.id === "claude-opus-4-6")) {
743
+ allModels.push({
744
+ id: "claude-opus-4-6",
745
+ name: "Claude Opus 4.6",
746
+ api: "anthropic-messages",
747
+ baseUrl: "https://api.anthropic.com",
748
+ provider: "anthropic",
749
+ reasoning: true,
750
+ input: ["text", "image"],
751
+ cost: {
752
+ input: 5,
753
+ output: 25,
754
+ cacheRead: 0.5,
755
+ cacheWrite: 6.25,
756
+ },
757
+ contextWindow: 1000000,
758
+ maxTokens: 128000,
759
+ });
760
+ }
761
+
762
+ // Add missing Claude Sonnet 4.6
763
+ if (!allModels.some(m => m.provider === "anthropic" && m.id === "claude-sonnet-4-6")) {
764
+ allModels.push({
765
+ id: "claude-sonnet-4-6",
766
+ name: "Claude Sonnet 4.6",
767
+ api: "anthropic-messages",
768
+ baseUrl: "https://api.anthropic.com",
769
+ provider: "anthropic",
770
+ reasoning: true,
771
+ input: ["text", "image"],
772
+ cost: {
773
+ input: 3,
774
+ output: 15,
775
+ cacheRead: 0.3,
776
+ cacheWrite: 3.75,
777
+ },
778
+ contextWindow: 1000000,
779
+ maxTokens: 64000,
780
+ });
781
+ }
782
+
783
+ // Add missing Gemini 3.1 Flash Lite Preview until models.dev includes it.
784
+ if (!allModels.some((m) => m.provider === "google" && m.id === "gemini-3.1-flash-lite-preview")) {
785
+ allModels.push({
786
+ id: "gemini-3.1-flash-lite-preview",
787
+ name: "Gemini 3.1 Flash Lite Preview",
788
+ api: "google-generative-ai",
789
+ baseUrl: "https://generativelanguage.googleapis.com/v1beta",
790
+ provider: "google",
791
+ reasoning: true,
792
+ input: ["text", "image"],
793
+ cost: {
794
+ input: 0,
795
+ output: 0,
796
+ cacheRead: 0,
797
+ cacheWrite: 0,
798
+ },
799
+ contextWindow: 1048576,
800
+ maxTokens: 65536,
801
+ });
802
+ }
803
+
804
+ // Add missing gpt models
805
+ if (!allModels.some(m => m.provider === "openai" && m.id === "gpt-5-chat-latest")) {
806
+ allModels.push({
807
+ id: "gpt-5-chat-latest",
808
+ name: "GPT-5 Chat Latest",
809
+ api: "openai-responses",
810
+ baseUrl: "https://api.openai.com/v1",
811
+ provider: "openai",
812
+ reasoning: false,
813
+ input: ["text", "image"],
814
+ cost: {
815
+ input: 1.25,
816
+ output: 10,
817
+ cacheRead: 0.125,
818
+ cacheWrite: 0,
819
+ },
820
+ contextWindow: 128000,
821
+ maxTokens: 16384,
822
+ });
823
+ }
824
+
825
+ if (!allModels.some(m => m.provider === "openai" && m.id === "gpt-5.1-codex")) {
826
+ allModels.push({
827
+ id: "gpt-5.1-codex",
828
+ name: "GPT-5.1 Codex",
829
+ api: "openai-responses",
830
+ baseUrl: "https://api.openai.com/v1",
831
+ provider: "openai",
832
+ reasoning: true,
833
+ input: ["text", "image"],
834
+ cost: {
835
+ input: 1.25,
836
+ output: 5,
837
+ cacheRead: 0.125,
838
+ cacheWrite: 1.25,
839
+ },
840
+ contextWindow: 400000,
841
+ maxTokens: 128000,
842
+ });
843
+ }
844
+
845
+ if (!allModels.some(m => m.provider === "openai" && m.id === "gpt-5.1-codex-max")) {
846
+ allModels.push({
847
+ id: "gpt-5.1-codex-max",
848
+ name: "GPT-5.1 Codex Max",
849
+ api: "openai-responses",
850
+ baseUrl: "https://api.openai.com/v1",
851
+ provider: "openai",
852
+ reasoning: true,
853
+ input: ["text", "image"],
854
+ cost: {
855
+ input: 1.25,
856
+ output: 10,
857
+ cacheRead: 0.125,
858
+ cacheWrite: 0,
859
+ },
860
+ contextWindow: 400000,
861
+ maxTokens: 128000,
862
+ });
863
+ }
864
+
865
+ if (!allModels.some(m => m.provider === "openai" && m.id === "gpt-5.3-codex-spark")) {
866
+ allModels.push({
867
+ id: "gpt-5.3-codex-spark",
868
+ name: "GPT-5.3 Codex Spark",
869
+ api: "openai-responses",
870
+ baseUrl: "https://api.openai.com/v1",
871
+ provider: "openai",
872
+ reasoning: true,
873
+ input: ["text"],
874
+ cost: {
875
+ input: 0,
876
+ output: 0,
877
+ cacheRead: 0,
878
+ cacheWrite: 0,
879
+ },
880
+ contextWindow: 128000,
881
+ maxTokens: 16384,
882
+ });
883
+ }
884
+
885
+ // Add missing GitHub Copilot GPT-5.3 models until models.dev includes them.
886
+ const copilotBaseModel = allModels.find(
887
+ (m) => m.provider === "github-copilot" && m.id === "gpt-5.2-codex",
888
+ );
889
+ if (copilotBaseModel) {
890
+ if (!allModels.some((m) => m.provider === "github-copilot" && m.id === "gpt-5.3-codex")) {
891
+ allModels.push({
892
+ ...copilotBaseModel,
893
+ id: "gpt-5.3-codex",
894
+ name: "GPT-5.3 Codex",
895
+ });
896
+ }
897
+ }
898
+
899
+ if (!allModels.some((m) => m.provider === "openai" && m.id === "gpt-5.4")) {
900
+ allModels.push({
901
+ id: "gpt-5.4",
902
+ name: "GPT-5.4",
903
+ api: "openai-responses",
904
+ baseUrl: "https://api.openai.com/v1",
905
+ provider: "openai",
906
+ reasoning: true,
907
+ input: ["text", "image"],
908
+ cost: {
909
+ input: 2.5,
910
+ output: 15,
911
+ cacheRead: 0.25,
912
+ cacheWrite: 0,
913
+ },
914
+ contextWindow: 272000,
915
+ maxTokens: 128000,
916
+ });
917
+ }
918
+
919
+ // OpenAI Codex (ChatGPT OAuth) models
920
+ // NOTE: These are not fetched from models.dev; we keep a small, explicit list to avoid aliases.
921
+ // Context window is based on observed server limits (400s above ~272k), not marketing numbers.
922
+ const CODEX_BASE_URL = "https://chatgpt.com/backend-api";
923
+ const CODEX_CONTEXT = 272000;
924
+ const CODEX_MAX_TOKENS = 128000;
925
+ const codexModels: Model<"openai-codex-responses">[] = [
926
+ {
927
+ id: "gpt-5.1",
928
+ name: "GPT-5.1",
929
+ api: "openai-codex-responses",
930
+ provider: "openai-codex",
931
+ baseUrl: CODEX_BASE_URL,
932
+ reasoning: true,
933
+ input: ["text", "image"],
934
+ cost: { input: 1.25, output: 10, cacheRead: 0.125, cacheWrite: 0 },
935
+ contextWindow: CODEX_CONTEXT,
936
+ maxTokens: CODEX_MAX_TOKENS,
937
+ },
938
+ {
939
+ id: "gpt-5.1-codex-max",
940
+ name: "GPT-5.1 Codex Max",
941
+ api: "openai-codex-responses",
942
+ provider: "openai-codex",
943
+ baseUrl: CODEX_BASE_URL,
944
+ reasoning: true,
945
+ input: ["text", "image"],
946
+ cost: { input: 1.25, output: 10, cacheRead: 0.125, cacheWrite: 0 },
947
+ contextWindow: CODEX_CONTEXT,
948
+ maxTokens: CODEX_MAX_TOKENS,
949
+ },
950
+ {
951
+ id: "gpt-5.1-codex-mini",
952
+ name: "GPT-5.1 Codex Mini",
953
+ api: "openai-codex-responses",
954
+ provider: "openai-codex",
955
+ baseUrl: CODEX_BASE_URL,
956
+ reasoning: true,
957
+ input: ["text", "image"],
958
+ cost: { input: 0.25, output: 2, cacheRead: 0.025, cacheWrite: 0 },
959
+ contextWindow: CODEX_CONTEXT,
960
+ maxTokens: CODEX_MAX_TOKENS,
961
+ },
962
+ {
963
+ id: "gpt-5.2",
964
+ name: "GPT-5.2",
965
+ api: "openai-codex-responses",
966
+ provider: "openai-codex",
967
+ baseUrl: CODEX_BASE_URL,
968
+ reasoning: true,
969
+ input: ["text", "image"],
970
+ cost: { input: 1.75, output: 14, cacheRead: 0.175, cacheWrite: 0 },
971
+ contextWindow: CODEX_CONTEXT,
972
+ maxTokens: CODEX_MAX_TOKENS,
973
+ },
974
+ {
975
+ id: "gpt-5.2-codex",
976
+ name: "GPT-5.2 Codex",
977
+ api: "openai-codex-responses",
978
+ provider: "openai-codex",
979
+ baseUrl: CODEX_BASE_URL,
980
+ reasoning: true,
981
+ input: ["text", "image"],
982
+ cost: { input: 1.75, output: 14, cacheRead: 0.175, cacheWrite: 0 },
983
+ contextWindow: CODEX_CONTEXT,
984
+ maxTokens: CODEX_MAX_TOKENS,
985
+ },
986
+ {
987
+ id: "gpt-5.3-codex",
988
+ name: "GPT-5.3 Codex",
989
+ api: "openai-codex-responses",
990
+ provider: "openai-codex",
991
+ baseUrl: CODEX_BASE_URL,
992
+ reasoning: true,
993
+ input: ["text", "image"],
994
+ cost: { input: 1.75, output: 14, cacheRead: 0.175, cacheWrite: 0 },
995
+ contextWindow: CODEX_CONTEXT,
996
+ maxTokens: CODEX_MAX_TOKENS,
997
+ },
998
+ {
999
+ id: "gpt-5.4",
1000
+ name: "GPT-5.4",
1001
+ api: "openai-codex-responses",
1002
+ provider: "openai-codex",
1003
+ baseUrl: CODEX_BASE_URL,
1004
+ reasoning: true,
1005
+ input: ["text", "image"],
1006
+ cost: { input: 2.5, output: 15, cacheRead: 0.25, cacheWrite: 0 },
1007
+ contextWindow: CODEX_CONTEXT,
1008
+ maxTokens: CODEX_MAX_TOKENS,
1009
+ },
1010
+ {
1011
+ id: "gpt-5.3-codex-spark",
1012
+ name: "GPT-5.3 Codex Spark",
1013
+ api: "openai-codex-responses",
1014
+ provider: "openai-codex",
1015
+ baseUrl: CODEX_BASE_URL,
1016
+ reasoning: true,
1017
+ input: ["text"],
1018
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
1019
+ contextWindow: 128000,
1020
+ maxTokens: CODEX_MAX_TOKENS,
1021
+ },
1022
+ ];
1023
+ allModels.push(...codexModels);
1024
+
1025
+ // Add missing Grok models
1026
+ if (!allModels.some(m => m.provider === "xai" && m.id === "grok-code-fast-1")) {
1027
+ allModels.push({
1028
+ id: "grok-code-fast-1",
1029
+ name: "Grok Code Fast 1",
1030
+ api: "openai-completions",
1031
+ baseUrl: "https://api.x.ai/v1",
1032
+ provider: "xai",
1033
+ reasoning: false,
1034
+ input: ["text"],
1035
+ cost: {
1036
+ input: 0.2,
1037
+ output: 1.5,
1038
+ cacheRead: 0.02,
1039
+ cacheWrite: 0,
1040
+ },
1041
+ contextWindow: 32768,
1042
+ maxTokens: 8192,
1043
+ });
1044
+ }
1045
+
1046
+ // Add "auto" alias for openrouter/auto
1047
+ if (!allModels.some(m => m.provider === "openrouter" && m.id === "auto")) {
1048
+ allModels.push({
1049
+ id: "auto",
1050
+ name: "Auto",
1051
+ api: "openai-completions",
1052
+ provider: "openrouter",
1053
+ baseUrl: "https://openrouter.ai/api/v1",
1054
+ reasoning: true,
1055
+ input: ["text", "image"],
1056
+ cost: {
1057
+ // we dont know about the costs because OpenRouter auto routes to different models
1058
+ // and then charges you for the underlying used model
1059
+ input:0,
1060
+ output:0,
1061
+ cacheRead:0,
1062
+ cacheWrite:0,
1063
+ },
1064
+ contextWindow: 2000000,
1065
+ maxTokens: 30000,
1066
+ });
1067
+ }
1068
+
1069
+ // Google Cloud Code Assist models (Gemini CLI)
1070
+ // Uses production endpoint, standard Gemini models only
1071
+ const CLOUD_CODE_ASSIST_ENDPOINT = "https://cloudcode-pa.googleapis.com";
1072
+ const cloudCodeAssistModels: Model<"google-gemini-cli">[] = [
1073
+ {
1074
+ id: "gemini-2.5-pro",
1075
+ name: "Gemini 2.5 Pro (Cloud Code Assist)",
1076
+ api: "google-gemini-cli",
1077
+ provider: "google-gemini-cli",
1078
+ baseUrl: CLOUD_CODE_ASSIST_ENDPOINT,
1079
+ reasoning: true,
1080
+ input: ["text", "image"],
1081
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
1082
+ contextWindow: 1048576,
1083
+ maxTokens: 65535,
1084
+ },
1085
+ {
1086
+ id: "gemini-2.5-flash",
1087
+ name: "Gemini 2.5 Flash (Cloud Code Assist)",
1088
+ api: "google-gemini-cli",
1089
+ provider: "google-gemini-cli",
1090
+ baseUrl: CLOUD_CODE_ASSIST_ENDPOINT,
1091
+ reasoning: true,
1092
+ input: ["text", "image"],
1093
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
1094
+ contextWindow: 1048576,
1095
+ maxTokens: 65535,
1096
+ },
1097
+ {
1098
+ id: "gemini-2.0-flash",
1099
+ name: "Gemini 2.0 Flash (Cloud Code Assist)",
1100
+ api: "google-gemini-cli",
1101
+ provider: "google-gemini-cli",
1102
+ baseUrl: CLOUD_CODE_ASSIST_ENDPOINT,
1103
+ reasoning: false,
1104
+ input: ["text", "image"],
1105
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
1106
+ contextWindow: 1048576,
1107
+ maxTokens: 8192,
1108
+ },
1109
+ {
1110
+ id: "gemini-3-pro-preview",
1111
+ name: "Gemini 3 Pro Preview (Cloud Code Assist)",
1112
+ api: "google-gemini-cli",
1113
+ provider: "google-gemini-cli",
1114
+ baseUrl: CLOUD_CODE_ASSIST_ENDPOINT,
1115
+ reasoning: true,
1116
+ input: ["text", "image"],
1117
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
1118
+ contextWindow: 1048576,
1119
+ maxTokens: 65535,
1120
+ },
1121
+ {
1122
+ id: "gemini-3-flash-preview",
1123
+ name: "Gemini 3 Flash Preview (Cloud Code Assist)",
1124
+ api: "google-gemini-cli",
1125
+ provider: "google-gemini-cli",
1126
+ baseUrl: CLOUD_CODE_ASSIST_ENDPOINT,
1127
+ reasoning: true,
1128
+ input: ["text", "image"],
1129
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
1130
+ contextWindow: 1048576,
1131
+ maxTokens: 65535,
1132
+ },
1133
+ {
1134
+ id: "gemini-3.1-pro-preview",
1135
+ name: "Gemini 3.1 Pro Preview (Cloud Code Assist)",
1136
+ api: "google-gemini-cli",
1137
+ provider: "google-gemini-cli",
1138
+ baseUrl: CLOUD_CODE_ASSIST_ENDPOINT,
1139
+ reasoning: true,
1140
+ input: ["text", "image"],
1141
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
1142
+ contextWindow: 1048576,
1143
+ maxTokens: 65535,
1144
+ },
1145
+ ];
1146
+ allModels.push(...cloudCodeAssistModels);
1147
+
1148
+ // Antigravity models (Gemini 3, Claude, GPT-OSS via Google Cloud)
1149
+ // Uses sandbox endpoint and different OAuth credentials for access to additional models
1150
+ const ANTIGRAVITY_ENDPOINT = "https://daily-cloudcode-pa.sandbox.googleapis.com";
1151
+ const antigravityModels: Model<"google-gemini-cli">[] = [
1152
+ {
1153
+ id: "gemini-3.1-pro-high",
1154
+ name: "Gemini 3.1 Pro High (Antigravity)",
1155
+ api: "google-gemini-cli",
1156
+ provider: "google-antigravity",
1157
+ baseUrl: ANTIGRAVITY_ENDPOINT,
1158
+ reasoning: true,
1159
+ input: ["text", "image"],
1160
+ // the Model type doesn't seem to support having extended-context costs, so I'm just using the pricing for <200k input
1161
+ cost: { input: 2, output: 12, cacheRead: 0.2, cacheWrite: 2.375 },
1162
+ contextWindow: 1048576,
1163
+ maxTokens: 65535,
1164
+ },
1165
+ {
1166
+ id: "gemini-3.1-pro-low",
1167
+ name: "Gemini 3.1 Pro Low (Antigravity)",
1168
+ api: "google-gemini-cli",
1169
+ provider: "google-antigravity",
1170
+ baseUrl: ANTIGRAVITY_ENDPOINT,
1171
+ reasoning: true,
1172
+ input: ["text", "image"],
1173
+ // the Model type doesn't seem to support having extended-context costs, so I'm just using the pricing for <200k input
1174
+ cost: { input: 2, output: 12, cacheRead: 0.2, cacheWrite: 2.375 },
1175
+ contextWindow: 1048576,
1176
+ maxTokens: 65535,
1177
+ },
1178
+ {
1179
+ id: "gemini-3-flash",
1180
+ name: "Gemini 3 Flash (Antigravity)",
1181
+ api: "google-gemini-cli",
1182
+ provider: "google-antigravity",
1183
+ baseUrl: ANTIGRAVITY_ENDPOINT,
1184
+ reasoning: true,
1185
+ input: ["text", "image"],
1186
+ cost: { input: 0.5, output: 3, cacheRead: 0.5, cacheWrite: 0 },
1187
+ contextWindow: 1048576,
1188
+ maxTokens: 65535,
1189
+ },
1190
+ {
1191
+ id: "claude-sonnet-4-5",
1192
+ name: "Claude Sonnet 4.5 (Antigravity)",
1193
+ api: "google-gemini-cli",
1194
+ provider: "google-antigravity",
1195
+ baseUrl: ANTIGRAVITY_ENDPOINT,
1196
+ reasoning: false,
1197
+ input: ["text", "image"],
1198
+ cost: { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 },
1199
+ contextWindow: 200000,
1200
+ maxTokens: 64000,
1201
+ },
1202
+ {
1203
+ id: "claude-sonnet-4-5-thinking",
1204
+ name: "Claude Sonnet 4.5 Thinking (Antigravity)",
1205
+ api: "google-gemini-cli",
1206
+ provider: "google-antigravity",
1207
+ baseUrl: ANTIGRAVITY_ENDPOINT,
1208
+ reasoning: true,
1209
+ input: ["text", "image"],
1210
+ cost: { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 },
1211
+ contextWindow: 200000,
1212
+ maxTokens: 64000,
1213
+ },
1214
+ {
1215
+ id: "claude-opus-4-5-thinking",
1216
+ name: "Claude Opus 4.5 Thinking (Antigravity)",
1217
+ api: "google-gemini-cli",
1218
+ provider: "google-antigravity",
1219
+ baseUrl: ANTIGRAVITY_ENDPOINT,
1220
+ reasoning: true,
1221
+ input: ["text", "image"],
1222
+ cost: { input: 5, output: 25, cacheRead: 0.5, cacheWrite: 6.25 },
1223
+ contextWindow: 200000,
1224
+ maxTokens: 64000,
1225
+ },
1226
+ {
1227
+ id: "claude-opus-4-6-thinking",
1228
+ name: "Claude Opus 4.6 Thinking (Antigravity)",
1229
+ api: "google-gemini-cli",
1230
+ provider: "google-antigravity",
1231
+ baseUrl: ANTIGRAVITY_ENDPOINT,
1232
+ reasoning: true,
1233
+ input: ["text", "image"],
1234
+ cost: { input: 5, output: 25, cacheRead: 0.5, cacheWrite: 6.25 },
1235
+ contextWindow: 200000,
1236
+ maxTokens: 128000,
1237
+ },
1238
+ {
1239
+ id: "claude-sonnet-4-6",
1240
+ name: "Claude Sonnet 4.6 (Antigravity)",
1241
+ api: "google-gemini-cli",
1242
+ provider: "google-antigravity",
1243
+ baseUrl: ANTIGRAVITY_ENDPOINT,
1244
+ reasoning: true,
1245
+ input: ["text", "image"],
1246
+ cost: { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 },
1247
+ contextWindow: 200000,
1248
+ maxTokens: 64000,
1249
+ },
1250
+ {
1251
+ id: "gpt-oss-120b-medium",
1252
+ name: "GPT-OSS 120B Medium (Antigravity)",
1253
+ api: "google-gemini-cli",
1254
+ provider: "google-antigravity",
1255
+ baseUrl: ANTIGRAVITY_ENDPOINT,
1256
+ reasoning: false,
1257
+ input: ["text"],
1258
+ cost: { input: 0.09, output: 0.36, cacheRead: 0, cacheWrite: 0 },
1259
+ contextWindow: 131072,
1260
+ maxTokens: 32768,
1261
+ },
1262
+ ];
1263
+ allModels.push(...antigravityModels);
1264
+
1265
+ const VERTEX_BASE_URL = "https://{location}-aiplatform.googleapis.com";
1266
+ const vertexModels: Model<"google-vertex">[] = [
1267
+ {
1268
+ id: "gemini-3-pro-preview",
1269
+ name: "Gemini 3 Pro Preview (Vertex)",
1270
+ api: "google-vertex",
1271
+ provider: "google-vertex",
1272
+ baseUrl: VERTEX_BASE_URL,
1273
+ reasoning: true,
1274
+ input: ["text", "image"],
1275
+ cost: { input: 2, output: 12, cacheRead: 0.2, cacheWrite: 0 },
1276
+ contextWindow: 1000000,
1277
+ maxTokens: 64000,
1278
+ },
1279
+ {
1280
+ id: "gemini-3.1-pro-preview",
1281
+ name: "Gemini 3.1 Pro Preview (Vertex)",
1282
+ api: "google-vertex",
1283
+ provider: "google-vertex",
1284
+ baseUrl: VERTEX_BASE_URL,
1285
+ reasoning: true,
1286
+ input: ["text", "image"],
1287
+ cost: { input: 2, output: 12, cacheRead: 0.2, cacheWrite: 0 },
1288
+ contextWindow: 1048576,
1289
+ maxTokens: 65536,
1290
+ },
1291
+ {
1292
+ id: "gemini-3-flash-preview",
1293
+ name: "Gemini 3 Flash Preview (Vertex)",
1294
+ api: "google-vertex",
1295
+ provider: "google-vertex",
1296
+ baseUrl: VERTEX_BASE_URL,
1297
+ reasoning: true,
1298
+ input: ["text", "image"],
1299
+ cost: { input: 0.5, output: 3, cacheRead: 0.05, cacheWrite: 0 },
1300
+ contextWindow: 1048576,
1301
+ maxTokens: 65536,
1302
+ },
1303
+ {
1304
+ id: "gemini-2.0-flash",
1305
+ name: "Gemini 2.0 Flash (Vertex)",
1306
+ api: "google-vertex",
1307
+ provider: "google-vertex",
1308
+ baseUrl: VERTEX_BASE_URL,
1309
+ reasoning: false,
1310
+ input: ["text", "image"],
1311
+ cost: { input: 0.15, output: 0.6, cacheRead: 0.0375, cacheWrite: 0 },
1312
+ contextWindow: 1048576,
1313
+ maxTokens: 8192,
1314
+ },
1315
+ {
1316
+ id: "gemini-2.0-flash-lite",
1317
+ name: "Gemini 2.0 Flash Lite (Vertex)",
1318
+ api: "google-vertex",
1319
+ provider: "google-vertex",
1320
+ baseUrl: VERTEX_BASE_URL,
1321
+ reasoning: true,
1322
+ input: ["text", "image"],
1323
+ cost: { input: 0.075, output: 0.3, cacheRead: 0.01875, cacheWrite: 0 },
1324
+ contextWindow: 1048576,
1325
+ maxTokens: 65536,
1326
+ },
1327
+ {
1328
+ id: "gemini-2.5-pro",
1329
+ name: "Gemini 2.5 Pro (Vertex)",
1330
+ api: "google-vertex",
1331
+ provider: "google-vertex",
1332
+ baseUrl: VERTEX_BASE_URL,
1333
+ reasoning: true,
1334
+ input: ["text", "image"],
1335
+ cost: { input: 1.25, output: 10, cacheRead: 0.125, cacheWrite: 0 },
1336
+ contextWindow: 1048576,
1337
+ maxTokens: 65536,
1338
+ },
1339
+ {
1340
+ id: "gemini-2.5-flash",
1341
+ name: "Gemini 2.5 Flash (Vertex)",
1342
+ api: "google-vertex",
1343
+ provider: "google-vertex",
1344
+ baseUrl: VERTEX_BASE_URL,
1345
+ reasoning: true,
1346
+ input: ["text", "image"],
1347
+ cost: { input: 0.3, output: 2.5, cacheRead: 0.03, cacheWrite: 0 },
1348
+ contextWindow: 1048576,
1349
+ maxTokens: 65536,
1350
+ },
1351
+ {
1352
+ id: "gemini-2.5-flash-lite-preview-09-2025",
1353
+ name: "Gemini 2.5 Flash Lite Preview 09-25 (Vertex)",
1354
+ api: "google-vertex",
1355
+ provider: "google-vertex",
1356
+ baseUrl: VERTEX_BASE_URL,
1357
+ reasoning: true,
1358
+ input: ["text", "image"],
1359
+ cost: { input: 0.1, output: 0.4, cacheRead: 0.01, cacheWrite: 0 },
1360
+ contextWindow: 1048576,
1361
+ maxTokens: 65536,
1362
+ },
1363
+ {
1364
+ id: "gemini-2.5-flash-lite",
1365
+ name: "Gemini 2.5 Flash Lite (Vertex)",
1366
+ api: "google-vertex",
1367
+ provider: "google-vertex",
1368
+ baseUrl: VERTEX_BASE_URL,
1369
+ reasoning: true,
1370
+ input: ["text", "image"],
1371
+ cost: { input: 0.1, output: 0.4, cacheRead: 0.01, cacheWrite: 0 },
1372
+ contextWindow: 1048576,
1373
+ maxTokens: 65536,
1374
+ },
1375
+ {
1376
+ id: "gemini-1.5-pro",
1377
+ name: "Gemini 1.5 Pro (Vertex)",
1378
+ api: "google-vertex",
1379
+ provider: "google-vertex",
1380
+ baseUrl: VERTEX_BASE_URL,
1381
+ reasoning: false,
1382
+ input: ["text", "image"],
1383
+ cost: { input: 1.25, output: 5, cacheRead: 0.3125, cacheWrite: 0 },
1384
+ contextWindow: 1000000,
1385
+ maxTokens: 8192,
1386
+ },
1387
+ {
1388
+ id: "gemini-1.5-flash",
1389
+ name: "Gemini 1.5 Flash (Vertex)",
1390
+ api: "google-vertex",
1391
+ provider: "google-vertex",
1392
+ baseUrl: VERTEX_BASE_URL,
1393
+ reasoning: false,
1394
+ input: ["text", "image"],
1395
+ cost: { input: 0.075, output: 0.3, cacheRead: 0.01875, cacheWrite: 0 },
1396
+ contextWindow: 1000000,
1397
+ maxTokens: 8192,
1398
+ },
1399
+ {
1400
+ id: "gemini-1.5-flash-8b",
1401
+ name: "Gemini 1.5 Flash-8B (Vertex)",
1402
+ api: "google-vertex",
1403
+ provider: "google-vertex",
1404
+ baseUrl: VERTEX_BASE_URL,
1405
+ reasoning: false,
1406
+ input: ["text", "image"],
1407
+ cost: { input: 0.0375, output: 0.15, cacheRead: 0.01, cacheWrite: 0 },
1408
+ contextWindow: 1000000,
1409
+ maxTokens: 8192,
1410
+ },
1411
+ ];
1412
+ allModels.push(...vertexModels);
1413
+
1414
+ // Kimi For Coding models (Moonshot AI's Anthropic-compatible coding API)
1415
+ // Static fallback in case models.dev doesn't have them yet
1416
+ const KIMI_CODING_BASE_URL = "https://api.kimi.com/coding";
1417
+ const kimiCodingModels: Model<"anthropic-messages">[] = [
1418
+ {
1419
+ id: "kimi-k2-thinking",
1420
+ name: "Kimi K2 Thinking",
1421
+ api: "anthropic-messages",
1422
+ provider: "kimi-coding",
1423
+ baseUrl: KIMI_CODING_BASE_URL,
1424
+ reasoning: true,
1425
+ input: ["text"],
1426
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
1427
+ contextWindow: 262144,
1428
+ maxTokens: 32768,
1429
+ },
1430
+ {
1431
+ id: "k2p5",
1432
+ name: "Kimi K2.5",
1433
+ api: "anthropic-messages",
1434
+ provider: "kimi-coding",
1435
+ baseUrl: KIMI_CODING_BASE_URL,
1436
+ reasoning: true,
1437
+ input: ["text"],
1438
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
1439
+ contextWindow: 262144,
1440
+ maxTokens: 32768,
1441
+ },
1442
+ ];
1443
+ // Only add if not already present from models.dev
1444
+ for (const model of kimiCodingModels) {
1445
+ if (!allModels.some(m => m.provider === "kimi-coding" && m.id === model.id)) {
1446
+ allModels.push(model);
1447
+ }
1448
+ }
1449
+
1450
+ const azureOpenAiModels: Model<Api>[] = allModels
1451
+ .filter((model) => model.provider === "openai" && model.api === "openai-responses")
1452
+ .map((model) => ({
1453
+ ...model,
1454
+ api: "azure-openai-responses",
1455
+ provider: "azure-openai-responses",
1456
+ baseUrl: "",
1457
+ }));
1458
+ allModels.push(...azureOpenAiModels);
1459
+
1460
+ // Group by provider and deduplicate by model ID
1461
+ const providers: Record<string, Record<string, Model<any>>> = {};
1462
+ for (const model of allModels) {
1463
+ if (!providers[model.provider]) {
1464
+ providers[model.provider] = {};
1465
+ }
1466
+ // Use model ID as key to automatically deduplicate
1467
+ // Only add if not already present (models.dev takes priority over OpenRouter)
1468
+ if (!providers[model.provider][model.id]) {
1469
+ providers[model.provider][model.id] = model;
1470
+ }
1471
+ }
1472
+
1473
+ // Generate TypeScript file
1474
+ let output = `// This file is auto-generated by scripts/generate-models.ts
1475
+ // Do not edit manually - run 'npm run generate-models' to update
1476
+
1477
+ import type { Model } from "./types.js";
1478
+
1479
+ export const MODELS = {
1480
+ `;
1481
+
1482
+ // Generate provider sections (sorted for deterministic output)
1483
+ const sortedProviderIds = Object.keys(providers).sort();
1484
+ for (const providerId of sortedProviderIds) {
1485
+ const models = providers[providerId];
1486
+ output += `\t${JSON.stringify(providerId)}: {\n`;
1487
+
1488
+ const sortedModelIds = Object.keys(models).sort();
1489
+ for (const modelId of sortedModelIds) {
1490
+ const model = models[modelId];
1491
+ output += `\t\t"${model.id}": {\n`;
1492
+ output += `\t\t\tid: "${model.id}",\n`;
1493
+ output += `\t\t\tname: "${model.name}",\n`;
1494
+ output += `\t\t\tapi: "${model.api}",\n`;
1495
+ output += `\t\t\tprovider: "${model.provider}",\n`;
1496
+ if (model.baseUrl !== undefined) {
1497
+ output += `\t\t\tbaseUrl: "${model.baseUrl}",\n`;
1498
+ }
1499
+ if (model.headers) {
1500
+ output += `\t\t\theaders: ${JSON.stringify(model.headers)},\n`;
1501
+ }
1502
+ if (model.compat) {
1503
+ output += ` compat: ${JSON.stringify(model.compat)},
1504
+ `;
1505
+ }
1506
+ output += `\t\t\treasoning: ${model.reasoning},\n`;
1507
+ output += `\t\t\tinput: [${model.input.map(i => `"${i}"`).join(", ")}],\n`;
1508
+ output += `\t\t\tcost: {\n`;
1509
+ output += `\t\t\t\tinput: ${model.cost.input},\n`;
1510
+ output += `\t\t\t\toutput: ${model.cost.output},\n`;
1511
+ output += `\t\t\t\tcacheRead: ${model.cost.cacheRead},\n`;
1512
+ output += `\t\t\t\tcacheWrite: ${model.cost.cacheWrite},\n`;
1513
+ output += `\t\t\t},\n`;
1514
+ output += `\t\t\tcontextWindow: ${model.contextWindow},\n`;
1515
+ output += `\t\t\tmaxTokens: ${model.maxTokens},\n`;
1516
+ output += `\t\t} satisfies Model<"${model.api}">,\n`;
1517
+ }
1518
+
1519
+ output += `\t},\n`;
1520
+ }
1521
+
1522
+ output += `} as const;
1523
+ `;
1524
+
1525
+ // Write file
1526
+ writeFileSync(join(packageRoot, "src/models.generated.ts"), output);
1527
+ console.log("Generated src/models.generated.ts");
1528
+
1529
+ // Print statistics
1530
+ const totalModels = allModels.length;
1531
+ const reasoningModels = allModels.filter(m => m.reasoning).length;
1532
+
1533
+ console.log(`\nModel Statistics:`);
1534
+ console.log(` Total tool-capable models: ${totalModels}`);
1535
+ console.log(` Reasoning-capable models: ${reasoningModels}`);
1536
+
1537
+ for (const [provider, models] of Object.entries(providers)) {
1538
+ console.log(` ${provider}: ${Object.keys(models).length} models`);
1539
+ }
1540
+ }
1541
+
1542
+ // Run the generator
1543
+ generateModels().catch(console.error);