@gajae-code/ai 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (349) hide show
  1. package/CHANGELOG.md +2644 -0
  2. package/README.md +1181 -0
  3. package/dist/types/api-registry.d.ts +30 -0
  4. package/dist/types/auth-broker/client.d.ts +66 -0
  5. package/dist/types/auth-broker/index.d.ts +5 -0
  6. package/dist/types/auth-broker/refresher.d.ts +25 -0
  7. package/dist/types/auth-broker/remote-store.d.ts +96 -0
  8. package/dist/types/auth-broker/server.d.ts +32 -0
  9. package/dist/types/auth-broker/types.d.ts +105 -0
  10. package/dist/types/auth-broker/wire-schemas.d.ts +412 -0
  11. package/dist/types/auth-gateway/http.d.ts +39 -0
  12. package/dist/types/auth-gateway/index.d.ts +3 -0
  13. package/dist/types/auth-gateway/server.d.ts +17 -0
  14. package/dist/types/auth-gateway/types.d.ts +115 -0
  15. package/dist/types/auth-storage.d.ts +641 -0
  16. package/dist/types/cli.d.ts +2 -0
  17. package/dist/types/index.d.ts +49 -0
  18. package/dist/types/model-cache.d.ts +17 -0
  19. package/dist/types/model-manager.d.ts +62 -0
  20. package/dist/types/model-thinking.d.ts +71 -0
  21. package/dist/types/models.d.ts +12 -0
  22. package/dist/types/provider-details.d.ts +24 -0
  23. package/dist/types/provider-models/bundled-references.d.ts +4 -0
  24. package/dist/types/provider-models/descriptors.d.ts +48 -0
  25. package/dist/types/provider-models/google.d.ts +20 -0
  26. package/dist/types/provider-models/index.d.ts +5 -0
  27. package/dist/types/provider-models/ollama.d.ts +7 -0
  28. package/dist/types/provider-models/openai-compat.d.ts +237 -0
  29. package/dist/types/provider-models/special.d.ts +16 -0
  30. package/dist/types/providers/amazon-bedrock.d.ts +36 -0
  31. package/dist/types/providers/anthropic-messages-server-schema.d.ts +450 -0
  32. package/dist/types/providers/anthropic-messages-server.d.ts +17 -0
  33. package/dist/types/providers/anthropic.d.ts +188 -0
  34. package/dist/types/providers/aws-credentials.d.ts +43 -0
  35. package/dist/types/providers/aws-eventstream.d.ts +38 -0
  36. package/dist/types/providers/aws-sigv4.d.ts +55 -0
  37. package/dist/types/providers/azure-openai-responses.d.ts +15 -0
  38. package/dist/types/providers/cursor/gen/agent_pb.d.ts +13022 -0
  39. package/dist/types/providers/cursor.d.ts +42 -0
  40. package/dist/types/providers/error-message.d.ts +27 -0
  41. package/dist/types/providers/github-copilot-headers.d.ts +40 -0
  42. package/dist/types/providers/gitlab-duo.d.ts +27 -0
  43. package/dist/types/providers/google-auth.d.ts +24 -0
  44. package/dist/types/providers/google-gemini-cli.d.ts +72 -0
  45. package/dist/types/providers/google-gemini-headers.d.ts +18 -0
  46. package/dist/types/providers/google-shared.d.ts +163 -0
  47. package/dist/types/providers/google-types.d.ts +138 -0
  48. package/dist/types/providers/google-vertex.d.ts +7 -0
  49. package/dist/types/providers/google.d.ts +4 -0
  50. package/dist/types/providers/grammar.d.ts +1 -0
  51. package/dist/types/providers/kimi.d.ts +27 -0
  52. package/dist/types/providers/mock.d.ts +175 -0
  53. package/dist/types/providers/ollama.d.ts +6 -0
  54. package/dist/types/providers/openai-anthropic-shim.d.ts +31 -0
  55. package/dist/types/providers/openai-chat-server-schema.d.ts +814 -0
  56. package/dist/types/providers/openai-chat-server.d.ts +16 -0
  57. package/dist/types/providers/openai-codex/constants.d.ts +26 -0
  58. package/dist/types/providers/openai-codex/request-transformer.d.ts +49 -0
  59. package/dist/types/providers/openai-codex/response-handler.d.ts +17 -0
  60. package/dist/types/providers/openai-codex-responses.d.ts +67 -0
  61. package/dist/types/providers/openai-completions-compat.d.ts +25 -0
  62. package/dist/types/providers/openai-completions.d.ts +33 -0
  63. package/dist/types/providers/openai-responses-server-schema.d.ts +392 -0
  64. package/dist/types/providers/openai-responses-server.d.ts +17 -0
  65. package/dist/types/providers/openai-responses-shared.d.ts +89 -0
  66. package/dist/types/providers/openai-responses.d.ts +32 -0
  67. package/dist/types/providers/pi-native-client.d.ts +13 -0
  68. package/dist/types/providers/pi-native-server.d.ts +68 -0
  69. package/dist/types/providers/register-builtins.d.ts +31 -0
  70. package/dist/types/providers/synthetic.d.ts +26 -0
  71. package/dist/types/providers/transform-messages.d.ts +12 -0
  72. package/dist/types/providers/vision-guard.d.ts +8 -0
  73. package/dist/types/rate-limit-utils.d.ts +19 -0
  74. package/dist/types/stream.d.ts +24 -0
  75. package/dist/types/types.d.ts +746 -0
  76. package/dist/types/usage/claude.d.ts +3 -0
  77. package/dist/types/usage/gemini.d.ts +2 -0
  78. package/dist/types/usage/github-copilot.d.ts +7 -0
  79. package/dist/types/usage/google-antigravity.d.ts +2 -0
  80. package/dist/types/usage/kimi.d.ts +2 -0
  81. package/dist/types/usage/minimax-code.d.ts +2 -0
  82. package/dist/types/usage/openai-codex.d.ts +3 -0
  83. package/dist/types/usage/shared.d.ts +1 -0
  84. package/dist/types/usage/zai.d.ts +2 -0
  85. package/dist/types/usage.d.ts +258 -0
  86. package/dist/types/utils/abort.d.ts +19 -0
  87. package/dist/types/utils/anthropic-auth.d.ts +31 -0
  88. package/dist/types/utils/discovery/antigravity.d.ts +61 -0
  89. package/dist/types/utils/discovery/codex.d.ts +38 -0
  90. package/dist/types/utils/discovery/cursor.d.ts +23 -0
  91. package/dist/types/utils/discovery/gemini.d.ts +25 -0
  92. package/dist/types/utils/discovery/index.d.ts +4 -0
  93. package/dist/types/utils/discovery/openai-compatible.d.ts +72 -0
  94. package/dist/types/utils/event-stream.d.ts +28 -0
  95. package/dist/types/utils/fireworks-model-id.d.ts +10 -0
  96. package/dist/types/utils/foundry.d.ts +1 -0
  97. package/dist/types/utils/h2-fetch.d.ts +22 -0
  98. package/dist/types/utils/http-inspector.d.ts +31 -0
  99. package/dist/types/utils/idle-iterator.d.ts +67 -0
  100. package/dist/types/utils/json-parse.d.ts +10 -0
  101. package/dist/types/utils/oauth/alibaba-coding-plan.d.ts +18 -0
  102. package/dist/types/utils/oauth/anthropic.d.ts +22 -0
  103. package/dist/types/utils/oauth/api-key-login.d.ts +35 -0
  104. package/dist/types/utils/oauth/api-key-validation.d.ts +27 -0
  105. package/dist/types/utils/oauth/callback-server.d.ts +57 -0
  106. package/dist/types/utils/oauth/cerebras.d.ts +1 -0
  107. package/dist/types/utils/oauth/cloudflare-ai-gateway.d.ts +18 -0
  108. package/dist/types/utils/oauth/cursor.d.ts +15 -0
  109. package/dist/types/utils/oauth/deepseek.d.ts +10 -0
  110. package/dist/types/utils/oauth/firepass.d.ts +1 -0
  111. package/dist/types/utils/oauth/fireworks.d.ts +1 -0
  112. package/dist/types/utils/oauth/github-copilot.d.ts +38 -0
  113. package/dist/types/utils/oauth/gitlab-duo.d.ts +3 -0
  114. package/dist/types/utils/oauth/google-antigravity.d.ts +11 -0
  115. package/dist/types/utils/oauth/google-gemini-cli.d.ts +10 -0
  116. package/dist/types/utils/oauth/google-oauth-shared.d.ts +28 -0
  117. package/dist/types/utils/oauth/huggingface.d.ts +19 -0
  118. package/dist/types/utils/oauth/index.d.ts +38 -0
  119. package/dist/types/utils/oauth/kagi.d.ts +17 -0
  120. package/dist/types/utils/oauth/kilo.d.ts +5 -0
  121. package/dist/types/utils/oauth/kimi.d.ts +21 -0
  122. package/dist/types/utils/oauth/litellm.d.ts +18 -0
  123. package/dist/types/utils/oauth/lm-studio.d.ts +17 -0
  124. package/dist/types/utils/oauth/minimax-code.d.ts +28 -0
  125. package/dist/types/utils/oauth/moonshot.d.ts +1 -0
  126. package/dist/types/utils/oauth/nanogpt.d.ts +1 -0
  127. package/dist/types/utils/oauth/nvidia.d.ts +18 -0
  128. package/dist/types/utils/oauth/ollama-cloud.d.ts +2 -0
  129. package/dist/types/utils/oauth/ollama.d.ts +18 -0
  130. package/dist/types/utils/oauth/openai-codex.d.ts +21 -0
  131. package/dist/types/utils/oauth/opencode.d.ts +18 -0
  132. package/dist/types/utils/oauth/parallel.d.ts +17 -0
  133. package/dist/types/utils/oauth/perplexity.d.ts +9 -0
  134. package/dist/types/utils/oauth/pkce.d.ts +8 -0
  135. package/dist/types/utils/oauth/qianfan.d.ts +17 -0
  136. package/dist/types/utils/oauth/qwen-portal.d.ts +19 -0
  137. package/dist/types/utils/oauth/synthetic.d.ts +1 -0
  138. package/dist/types/utils/oauth/tavily.d.ts +17 -0
  139. package/dist/types/utils/oauth/together.d.ts +1 -0
  140. package/dist/types/utils/oauth/types.d.ts +44 -0
  141. package/dist/types/utils/oauth/venice.d.ts +18 -0
  142. package/dist/types/utils/oauth/vercel-ai-gateway.d.ts +18 -0
  143. package/dist/types/utils/oauth/vllm.d.ts +16 -0
  144. package/dist/types/utils/oauth/xiaomi.d.ts +19 -0
  145. package/dist/types/utils/oauth/zai.d.ts +18 -0
  146. package/dist/types/utils/oauth/zenmux.d.ts +1 -0
  147. package/dist/types/utils/overflow.d.ts +54 -0
  148. package/dist/types/utils/parse-bind.d.ts +23 -0
  149. package/dist/types/utils/provider-response.d.ts +3 -0
  150. package/dist/types/utils/retry-after.d.ts +3 -0
  151. package/dist/types/utils/retry.d.ts +26 -0
  152. package/dist/types/utils/schema/adapt.d.ts +24 -0
  153. package/dist/types/utils/schema/compatibility.d.ts +30 -0
  154. package/dist/types/utils/schema/dereference.d.ts +11 -0
  155. package/dist/types/utils/schema/draft.d.ts +10 -0
  156. package/dist/types/utils/schema/equality.d.ts +4 -0
  157. package/dist/types/utils/schema/fields.d.ts +49 -0
  158. package/dist/types/utils/schema/index.d.ts +13 -0
  159. package/dist/types/utils/schema/json-schema-validator.d.ts +12 -0
  160. package/dist/types/utils/schema/meta-validator.d.ts +2 -0
  161. package/dist/types/utils/schema/normalize.d.ts +93 -0
  162. package/dist/types/utils/schema/spill.d.ts +8 -0
  163. package/dist/types/utils/schema/stamps.d.ts +25 -0
  164. package/dist/types/utils/schema/types.d.ts +4 -0
  165. package/dist/types/utils/schema/wire.d.ts +54 -0
  166. package/dist/types/utils/schema/zod-decontaminate.d.ts +31 -0
  167. package/dist/types/utils/sse-debug.d.ts +10 -0
  168. package/dist/types/utils/tool-call-healing.d.ts +71 -0
  169. package/dist/types/utils/tool-choice.d.ts +50 -0
  170. package/dist/types/utils/validation.d.ts +17 -0
  171. package/dist/types/utils.d.ts +28 -0
  172. package/package.json +146 -0
  173. package/src/api-registry.ts +96 -0
  174. package/src/auth-broker/client.ts +358 -0
  175. package/src/auth-broker/index.ts +5 -0
  176. package/src/auth-broker/refresher.ts +127 -0
  177. package/src/auth-broker/remote-store.ts +623 -0
  178. package/src/auth-broker/server.ts +644 -0
  179. package/src/auth-broker/types.ts +127 -0
  180. package/src/auth-broker/wire-schemas.ts +200 -0
  181. package/src/auth-gateway/http.ts +194 -0
  182. package/src/auth-gateway/index.ts +3 -0
  183. package/src/auth-gateway/server.ts +717 -0
  184. package/src/auth-gateway/types.ts +134 -0
  185. package/src/auth-storage.ts +4104 -0
  186. package/src/cli.ts +262 -0
  187. package/src/index.ts +54 -0
  188. package/src/model-cache.ts +129 -0
  189. package/src/model-manager.ts +450 -0
  190. package/src/model-thinking.ts +691 -0
  191. package/src/models.json +73853 -0
  192. package/src/models.json.d.ts +9 -0
  193. package/src/models.ts +56 -0
  194. package/src/prompts/turn-aborted-guidance.md +4 -0
  195. package/src/provider-details.ts +90 -0
  196. package/src/provider-models/bundled-references.ts +38 -0
  197. package/src/provider-models/descriptors.ts +308 -0
  198. package/src/provider-models/google.ts +91 -0
  199. package/src/provider-models/index.ts +5 -0
  200. package/src/provider-models/ollama.ts +153 -0
  201. package/src/provider-models/openai-compat.ts +2275 -0
  202. package/src/provider-models/special.ts +67 -0
  203. package/src/providers/amazon-bedrock.ts +849 -0
  204. package/src/providers/anthropic-messages-server-schema.ts +229 -0
  205. package/src/providers/anthropic-messages-server.ts +677 -0
  206. package/src/providers/anthropic.ts +2696 -0
  207. package/src/providers/aws-credentials.ts +501 -0
  208. package/src/providers/aws-eventstream.ts +185 -0
  209. package/src/providers/aws-sigv4.ts +218 -0
  210. package/src/providers/azure-openai-responses.ts +337 -0
  211. package/src/providers/cursor/gen/agent_pb.ts +15274 -0
  212. package/src/providers/cursor/proto/agent.proto +3526 -0
  213. package/src/providers/cursor/proto/buf.gen.yaml +6 -0
  214. package/src/providers/cursor/proto/buf.yaml +17 -0
  215. package/src/providers/cursor.ts +2561 -0
  216. package/src/providers/error-message.ts +21 -0
  217. package/src/providers/github-copilot-headers.ts +140 -0
  218. package/src/providers/gitlab-duo.ts +372 -0
  219. package/src/providers/google-auth.ts +252 -0
  220. package/src/providers/google-gemini-cli.ts +795 -0
  221. package/src/providers/google-gemini-headers.ts +41 -0
  222. package/src/providers/google-shared.ts +902 -0
  223. package/src/providers/google-types.ts +167 -0
  224. package/src/providers/google-vertex.ts +88 -0
  225. package/src/providers/google.ts +41 -0
  226. package/src/providers/grammar.ts +70 -0
  227. package/src/providers/kimi.ts +52 -0
  228. package/src/providers/mock.ts +500 -0
  229. package/src/providers/ollama.ts +544 -0
  230. package/src/providers/openai-anthropic-shim.ts +138 -0
  231. package/src/providers/openai-chat-server-schema.ts +243 -0
  232. package/src/providers/openai-chat-server.ts +628 -0
  233. package/src/providers/openai-codex/constants.ts +43 -0
  234. package/src/providers/openai-codex/request-transformer.ts +161 -0
  235. package/src/providers/openai-codex/response-handler.ts +81 -0
  236. package/src/providers/openai-codex-responses.ts +2598 -0
  237. package/src/providers/openai-completions-compat.ts +279 -0
  238. package/src/providers/openai-completions.ts +1853 -0
  239. package/src/providers/openai-responses-server-schema.ts +290 -0
  240. package/src/providers/openai-responses-server.ts +1183 -0
  241. package/src/providers/openai-responses-shared.ts +800 -0
  242. package/src/providers/openai-responses.ts +621 -0
  243. package/src/providers/pi-native-client.ts +228 -0
  244. package/src/providers/pi-native-server.ts +210 -0
  245. package/src/providers/register-builtins.ts +412 -0
  246. package/src/providers/synthetic.ts +50 -0
  247. package/src/providers/transform-messages.ts +309 -0
  248. package/src/providers/vision-guard.ts +31 -0
  249. package/src/rate-limit-utils.ts +84 -0
  250. package/src/stream.ts +895 -0
  251. package/src/types.ts +884 -0
  252. package/src/usage/claude.ts +431 -0
  253. package/src/usage/gemini.ts +250 -0
  254. package/src/usage/github-copilot.ts +421 -0
  255. package/src/usage/google-antigravity.ts +201 -0
  256. package/src/usage/kimi.ts +271 -0
  257. package/src/usage/minimax-code.ts +31 -0
  258. package/src/usage/openai-codex.ts +503 -0
  259. package/src/usage/shared.ts +10 -0
  260. package/src/usage/zai.ts +247 -0
  261. package/src/usage.ts +183 -0
  262. package/src/utils/abort.ts +51 -0
  263. package/src/utils/anthropic-auth.ts +87 -0
  264. package/src/utils/discovery/antigravity.ts +261 -0
  265. package/src/utils/discovery/codex.ts +371 -0
  266. package/src/utils/discovery/cursor.ts +306 -0
  267. package/src/utils/discovery/gemini.ts +248 -0
  268. package/src/utils/discovery/index.ts +4 -0
  269. package/src/utils/discovery/openai-compatible.ts +224 -0
  270. package/src/utils/event-stream.ts +142 -0
  271. package/src/utils/fireworks-model-id.ts +30 -0
  272. package/src/utils/foundry.ts +8 -0
  273. package/src/utils/h2-fetch.ts +60 -0
  274. package/src/utils/http-inspector.ts +176 -0
  275. package/src/utils/idle-iterator.ts +250 -0
  276. package/src/utils/json-parse.ts +148 -0
  277. package/src/utils/oauth/alibaba-coding-plan.ts +59 -0
  278. package/src/utils/oauth/anthropic.ts +200 -0
  279. package/src/utils/oauth/api-key-login.ts +87 -0
  280. package/src/utils/oauth/api-key-validation.ts +92 -0
  281. package/src/utils/oauth/callback-server.ts +276 -0
  282. package/src/utils/oauth/cerebras.ts +16 -0
  283. package/src/utils/oauth/cloudflare-ai-gateway.ts +48 -0
  284. package/src/utils/oauth/cursor.ts +157 -0
  285. package/src/utils/oauth/deepseek.ts +53 -0
  286. package/src/utils/oauth/firepass.ts +24 -0
  287. package/src/utils/oauth/fireworks.ts +15 -0
  288. package/src/utils/oauth/github-copilot.ts +362 -0
  289. package/src/utils/oauth/gitlab-duo.ts +123 -0
  290. package/src/utils/oauth/google-antigravity.ts +200 -0
  291. package/src/utils/oauth/google-gemini-cli.ts +256 -0
  292. package/src/utils/oauth/google-oauth-shared.ts +110 -0
  293. package/src/utils/oauth/huggingface.ts +62 -0
  294. package/src/utils/oauth/index.ts +444 -0
  295. package/src/utils/oauth/kagi.ts +47 -0
  296. package/src/utils/oauth/kilo.ts +87 -0
  297. package/src/utils/oauth/kimi.ts +254 -0
  298. package/src/utils/oauth/litellm.ts +47 -0
  299. package/src/utils/oauth/lm-studio.ts +38 -0
  300. package/src/utils/oauth/minimax-code.ts +78 -0
  301. package/src/utils/oauth/moonshot.ts +16 -0
  302. package/src/utils/oauth/nanogpt.ts +15 -0
  303. package/src/utils/oauth/nvidia.ts +70 -0
  304. package/src/utils/oauth/oauth.html +199 -0
  305. package/src/utils/oauth/ollama-cloud.ts +28 -0
  306. package/src/utils/oauth/ollama.ts +47 -0
  307. package/src/utils/oauth/openai-codex.ts +299 -0
  308. package/src/utils/oauth/opencode.ts +49 -0
  309. package/src/utils/oauth/parallel.ts +46 -0
  310. package/src/utils/oauth/perplexity.ts +206 -0
  311. package/src/utils/oauth/pkce.ts +18 -0
  312. package/src/utils/oauth/qianfan.ts +58 -0
  313. package/src/utils/oauth/qwen-portal.ts +60 -0
  314. package/src/utils/oauth/synthetic.ts +16 -0
  315. package/src/utils/oauth/tavily.ts +46 -0
  316. package/src/utils/oauth/together.ts +16 -0
  317. package/src/utils/oauth/types.ts +94 -0
  318. package/src/utils/oauth/venice.ts +59 -0
  319. package/src/utils/oauth/vercel-ai-gateway.ts +47 -0
  320. package/src/utils/oauth/vllm.ts +40 -0
  321. package/src/utils/oauth/xiaomi.ts +137 -0
  322. package/src/utils/oauth/zai.ts +60 -0
  323. package/src/utils/oauth/zenmux.ts +15 -0
  324. package/src/utils/overflow.ts +137 -0
  325. package/src/utils/parse-bind.ts +54 -0
  326. package/src/utils/provider-response.ts +30 -0
  327. package/src/utils/retry-after.ts +110 -0
  328. package/src/utils/retry.ts +54 -0
  329. package/src/utils/schema/CONSTRAINTS.md +164 -0
  330. package/src/utils/schema/adapt.ts +36 -0
  331. package/src/utils/schema/compatibility.ts +435 -0
  332. package/src/utils/schema/dereference.ts +98 -0
  333. package/src/utils/schema/draft.ts +341 -0
  334. package/src/utils/schema/equality.ts +97 -0
  335. package/src/utils/schema/fields.ts +190 -0
  336. package/src/utils/schema/index.ts +13 -0
  337. package/src/utils/schema/json-schema-validator.ts +577 -0
  338. package/src/utils/schema/meta-validator.ts +167 -0
  339. package/src/utils/schema/normalize.ts +1588 -0
  340. package/src/utils/schema/spill.ts +43 -0
  341. package/src/utils/schema/stamps.ts +97 -0
  342. package/src/utils/schema/types.ts +11 -0
  343. package/src/utils/schema/wire.ts +213 -0
  344. package/src/utils/schema/zod-decontaminate.ts +331 -0
  345. package/src/utils/sse-debug.ts +289 -0
  346. package/src/utils/tool-call-healing.ts +271 -0
  347. package/src/utils/tool-choice.ts +99 -0
  348. package/src/utils/validation.ts +1019 -0
  349. package/src/utils.ts +166 -0
@@ -0,0 +1,261 @@
1
+ import * as z from "zod/v4";
2
+ import { getAntigravityUserAgent } from "../../providers/google-gemini-headers";
3
+ import type { Model } from "../../types";
4
+ import { toPositiveNumber } from "../../utils";
5
+
6
+ const DEFAULT_ANTIGRAVITY_DISCOVERY_ENDPOINTS = [
7
+ "https://daily-cloudcode-pa.googleapis.com",
8
+ "https://daily-cloudcode-pa.sandbox.googleapis.com",
9
+ ] as const;
10
+ const FETCH_AVAILABLE_MODELS_PATH = "/v1internal:fetchAvailableModels";
11
+
12
+ const DEFAULT_CONTEXT_WINDOW = 200_000;
13
+ const DEFAULT_MAX_TOKENS = 64_000;
14
+ const ANTIGRAVITY_DISCOVERY_DENYLIST = new Set([
15
+ "chat_20706",
16
+ "chat_23310",
17
+ "gemini-2.5-flash-thinking",
18
+ "gemini-3-pro-low",
19
+ "gemini-2.5-pro",
20
+ ]);
21
+
22
+ /**
23
+ * Raw model metadata returned by Antigravity's `fetchAvailableModels` endpoint.
24
+ */
25
+ export interface AntigravityDiscoveryApiModel {
26
+ displayName?: string;
27
+ supportsImages?: boolean;
28
+ supportsThinking?: boolean;
29
+ thinkingBudget?: number;
30
+ recommended?: boolean;
31
+ maxTokens?: number;
32
+ maxOutputTokens?: number;
33
+ model?: string;
34
+ apiProvider?: string;
35
+ modelProvider?: string;
36
+ isInternal?: boolean;
37
+ supportsVideo?: boolean;
38
+ }
39
+
40
+ /**
41
+ * Grouping metadata used by Antigravity to surface recommended model ids.
42
+ */
43
+ export interface AntigravityDiscoveryAgentModelGroup {
44
+ modelIds?: string[];
45
+ }
46
+
47
+ /**
48
+ * Sort/group metadata used by Antigravity to surface recommended model ids.
49
+ */
50
+ export interface AntigravityDiscoveryAgentModelSort {
51
+ groups?: AntigravityDiscoveryAgentModelGroup[];
52
+ }
53
+
54
+ /**
55
+ * Response payload returned by Antigravity's `fetchAvailableModels` endpoint.
56
+ */
57
+ export interface AntigravityDiscoveryApiResponse {
58
+ models?: Record<string, AntigravityDiscoveryApiModel>;
59
+ agentModelSorts?: AntigravityDiscoveryAgentModelSort[];
60
+ }
61
+ const AntigravityDiscoveryApiModelSchema: z.ZodType<AntigravityDiscoveryApiModel> = z
62
+ .object({
63
+ displayName: z.preprocess(value => (typeof value === "string" ? value : undefined), z.string().optional()),
64
+ supportsImages: z.preprocess(value => (typeof value === "boolean" ? value : undefined), z.boolean().optional()),
65
+ supportsThinking: z.preprocess(value => (typeof value === "boolean" ? value : undefined), z.boolean().optional()),
66
+ thinkingBudget: z.preprocess(
67
+ value => (typeof value === "number" && Number.isFinite(value) ? value : undefined),
68
+ z.number().optional(),
69
+ ),
70
+ recommended: z.preprocess(value => (typeof value === "boolean" ? value : undefined), z.boolean().optional()),
71
+ maxTokens: z.preprocess(
72
+ value => (typeof value === "number" && Number.isFinite(value) ? value : undefined),
73
+ z.number().optional(),
74
+ ),
75
+ maxOutputTokens: z.preprocess(
76
+ value => (typeof value === "number" && Number.isFinite(value) ? value : undefined),
77
+ z.number().optional(),
78
+ ),
79
+ model: z.preprocess(value => (typeof value === "string" ? value : undefined), z.string().optional()),
80
+ apiProvider: z.preprocess(value => (typeof value === "string" ? value : undefined), z.string().optional()),
81
+ modelProvider: z.preprocess(value => (typeof value === "string" ? value : undefined), z.string().optional()),
82
+ isInternal: z.preprocess(value => (typeof value === "boolean" ? value : undefined), z.boolean().optional()),
83
+ supportsVideo: z.preprocess(value => (typeof value === "boolean" ? value : undefined), z.boolean().optional()),
84
+ })
85
+ .loose();
86
+ const AntigravityDiscoveryAgentModelGroupSchema: z.ZodType<AntigravityDiscoveryAgentModelGroup> = z
87
+ .object({
88
+ modelIds: z.preprocess(
89
+ value =>
90
+ Array.isArray(value)
91
+ ? value.filter((modelId): modelId is string => typeof modelId === "string")
92
+ : undefined,
93
+ z.array(z.string()).optional(),
94
+ ),
95
+ })
96
+ .loose();
97
+ const AntigravityDiscoveryAgentModelSortSchema: z.ZodType<AntigravityDiscoveryAgentModelSort> = z
98
+ .object({
99
+ groups: z.preprocess(
100
+ value => (Array.isArray(value) ? value : undefined),
101
+ z
102
+ .array(z.unknown())
103
+ .transform(groups =>
104
+ groups.flatMap(group => {
105
+ const parsedGroup = AntigravityDiscoveryAgentModelGroupSchema.safeParse(group);
106
+ return parsedGroup.success ? [parsedGroup.data] : [];
107
+ }),
108
+ )
109
+ .optional(),
110
+ ),
111
+ })
112
+ .loose();
113
+ const AntigravityDiscoveryApiResponseSchema: z.ZodType<AntigravityDiscoveryApiResponse> = z
114
+ .object({
115
+ models: z.preprocess(
116
+ value => (typeof value === "object" && value !== null ? value : undefined),
117
+ z
118
+ .record(z.string(), z.unknown())
119
+ .transform(models => {
120
+ const normalized: Record<string, AntigravityDiscoveryApiModel> = {};
121
+ for (const [modelId, modelValue] of Object.entries(models)) {
122
+ if (typeof modelValue !== "object" || modelValue === null) {
123
+ continue;
124
+ }
125
+ const parsedModel = AntigravityDiscoveryApiModelSchema.safeParse(modelValue);
126
+ if (parsedModel.success) {
127
+ normalized[modelId] = parsedModel.data;
128
+ }
129
+ }
130
+ return normalized;
131
+ })
132
+ .optional(),
133
+ ),
134
+ agentModelSorts: z.preprocess(
135
+ value => (Array.isArray(value) ? value : undefined),
136
+ z
137
+ .array(z.unknown())
138
+ .transform(sorts =>
139
+ sorts.flatMap(sort => {
140
+ const parsedSort = AntigravityDiscoveryAgentModelSortSchema.safeParse(sort);
141
+ return parsedSort.success ? [parsedSort.data] : [];
142
+ }),
143
+ )
144
+ .optional(),
145
+ ),
146
+ })
147
+ .loose();
148
+
149
+ /**
150
+ * Options for fetching Antigravity discovery models.
151
+ */
152
+ export interface FetchAntigravityDiscoveryModelsOptions {
153
+ /** OAuth access token used as `Authorization: Bearer <token>`. */
154
+ token: string;
155
+ /** Optional endpoint override. Defaults to Antigravity fallback endpoints. */
156
+ endpoint?: string;
157
+ /** Deprecated and ignored for antigravity discovery parity. */
158
+ project?: string;
159
+ /** Optional user agent override. */
160
+ userAgent?: string;
161
+ /** Optional abort signal for request cancellation. */
162
+ signal?: AbortSignal;
163
+ /** Optional fetch implementation override for tests. */
164
+ fetcher?: typeof fetch;
165
+ }
166
+
167
+ /**
168
+ * Fetches discoverable Antigravity models and normalizes them into canonical model entries.
169
+ *
170
+ * Returns `null` on network/payload/auth failures.
171
+ * Returns `[]` only when the endpoint responds successfully with no usable models.
172
+ */
173
+ export async function fetchAntigravityDiscoveryModels(
174
+ options: FetchAntigravityDiscoveryModelsOptions,
175
+ ): Promise<Model<"google-gemini-cli">[] | null> {
176
+ const fetcher = options.fetcher ?? fetch;
177
+ const endpoints = options.endpoint
178
+ ? [trimTrailingSlashes(options.endpoint)]
179
+ : DEFAULT_ANTIGRAVITY_DISCOVERY_ENDPOINTS.map(trimTrailingSlashes);
180
+
181
+ for (const endpoint of endpoints) {
182
+ let response: Response;
183
+ try {
184
+ response = await fetcher(`${endpoint}${FETCH_AVAILABLE_MODELS_PATH}`, {
185
+ method: "POST",
186
+ headers: {
187
+ Authorization: `Bearer ${options.token}`,
188
+ "Content-Type": "application/json",
189
+ "User-Agent": options.userAgent ?? getAntigravityUserAgent(),
190
+ },
191
+ body: JSON.stringify({}),
192
+ signal: options.signal,
193
+ });
194
+ } catch {
195
+ continue;
196
+ }
197
+
198
+ if (!response.ok) {
199
+ continue;
200
+ }
201
+
202
+ let payload: unknown;
203
+ try {
204
+ payload = await response.json();
205
+ } catch {
206
+ continue;
207
+ }
208
+
209
+ const parsed = parseAntigravityDiscoveryResponse(payload);
210
+ if (!parsed) {
211
+ continue;
212
+ }
213
+
214
+ const models: Model<"google-gemini-cli">[] = [];
215
+
216
+ for (const [modelId, model] of Object.entries(parsed.models ?? {})) {
217
+ if (ANTIGRAVITY_DISCOVERY_DENYLIST.has(modelId)) {
218
+ continue;
219
+ }
220
+ if (model.isInternal === true) {
221
+ continue;
222
+ }
223
+
224
+ const supportsImages = model.supportsImages === true;
225
+ models.push({
226
+ id: modelId,
227
+ name: model.displayName ? `${model.displayName} (Antigravity)` : modelId,
228
+ api: "google-gemini-cli",
229
+ provider: "google-antigravity",
230
+ baseUrl: endpoint,
231
+ reasoning: model.supportsThinking === true,
232
+ input: supportsImages ? ["text", "image"] : ["text"],
233
+ cost: {
234
+ input: 0,
235
+ output: 0,
236
+ cacheRead: 0,
237
+ cacheWrite: 0,
238
+ },
239
+ contextWindow: toPositiveNumber(model.maxTokens, DEFAULT_CONTEXT_WINDOW),
240
+ maxTokens: toPositiveNumber(model.maxOutputTokens, DEFAULT_MAX_TOKENS),
241
+ });
242
+ }
243
+
244
+ models.sort((a, b) => a.name.localeCompare(b.name) || a.id.localeCompare(b.id));
245
+ return models;
246
+ }
247
+
248
+ return null;
249
+ }
250
+
251
+ function parseAntigravityDiscoveryResponse(value: unknown): AntigravityDiscoveryApiResponse | null {
252
+ const parsed = AntigravityDiscoveryApiResponseSchema.safeParse(value);
253
+ if (!parsed.success) {
254
+ return null;
255
+ }
256
+ return parsed.data;
257
+ }
258
+
259
+ function trimTrailingSlashes(value: string): string {
260
+ return value.replace(/\/+$/, "");
261
+ }
@@ -0,0 +1,371 @@
1
+ import * as z from "zod/v4";
2
+ import { CODEX_BASE_URL, OPENAI_HEADER_VALUES, OPENAI_HEADERS } from "../../providers/openai-codex/constants";
3
+ import type { Model } from "../../types";
4
+ import { isRecord } from "../../utils";
5
+
6
+ const DEFAULT_MODEL_LIST_PATHS = ["/codex/models", "/models"] as const;
7
+ const DEFAULT_CONTEXT_WINDOW = 272_000;
8
+ const DEFAULT_MAX_TOKENS = 128_000;
9
+ const DEFAULT_CODEX_CLIENT_VERSION = "0.99.0";
10
+ const NPM_CODEX_LATEST_URL = "https://registry.npmjs.org/@openai%2Fcodex/latest";
11
+
12
+ const codexReasoningPresetSchema = z
13
+ .object({
14
+ effort: z.unknown().optional(),
15
+ })
16
+ .loose();
17
+
18
+ const codexModelEntrySchema = z
19
+ .object({
20
+ slug: z.unknown().optional(),
21
+ id: z.unknown().optional(),
22
+ display_name: z.unknown().optional(),
23
+ context_window: z.unknown().optional(),
24
+ default_reasoning_level: z.unknown().optional(),
25
+ supported_reasoning_levels: z.unknown().optional(),
26
+ input_modalities: z.unknown().optional(),
27
+ supported_in_api: z.unknown().optional(),
28
+ priority: z.unknown().optional(),
29
+ prefer_websockets: z.unknown().optional(),
30
+ })
31
+ .loose();
32
+
33
+ const codexModelsResponseSchema = z
34
+ .object({
35
+ models: z.array(z.unknown()).optional(),
36
+ data: z.array(z.unknown()).optional(),
37
+ })
38
+ .loose();
39
+
40
+ type CodexModelEntry = z.infer<typeof codexModelEntrySchema>;
41
+
42
+ interface NormalizedCodexModel {
43
+ model: Model<"openai-codex-responses">;
44
+ priority: number;
45
+ }
46
+
47
+ /**
48
+ * Fetch options for OpenAI code provider model discovery.
49
+ */
50
+ export interface CodexModelDiscoveryOptions {
51
+ /** OAuth access token used for `Authorization: Bearer ...`. */
52
+ accessToken: string;
53
+ /** ChatGPT account id value used for `chatgpt-account-id` header. */
54
+ accountId?: string;
55
+ /** Base URL for OpenAI code backend backend. Defaults to `https://chatgpt.com/backend-api`. */
56
+ baseUrl?: string;
57
+ /** Optional client version attached as `client_version` query parameter. */
58
+ clientVersion?: string;
59
+ /** Optional endpoint path candidates. Defaults to `/OpenAI code backend/models`, then `/models`. */
60
+ paths?: readonly string[];
61
+ /** Additional headers merged on top of required OpenAI code backend headers. */
62
+ headers?: Record<string, string>;
63
+ /** Abort signal for network request cancellation. */
64
+ signal?: AbortSignal;
65
+ /** Optional fetch implementation override for tests. */
66
+ fetchFn?: typeof fetch;
67
+ /** Optional registry fetch implementation override for client version lookup. */
68
+ registryFetchFn?: typeof fetch;
69
+ }
70
+
71
+ /**
72
+ * Normalized OpenAI code backend discovery response.
73
+ */
74
+ export interface CodexModelDiscoveryResult {
75
+ models: Model<"openai-codex-responses">[];
76
+ etag?: string;
77
+ }
78
+
79
+ /**
80
+ * Fetches model metadata from OpenAI code backend backend and normalizes it for pi model management.
81
+ *
82
+ * Returns `null` when no supported model-list route can be fetched/parsed.
83
+ * Returns `{ models: [] }` when a route succeeds but yields no usable models.
84
+ */
85
+ export async function fetchCodexModels(options: CodexModelDiscoveryOptions): Promise<CodexModelDiscoveryResult | null> {
86
+ const fetchFn = options.fetchFn ?? fetch;
87
+ const baseUrl = normalizeBaseUrl(options.baseUrl);
88
+ const paths = normalizePaths(options.paths);
89
+ const headers = buildCodexHeaders(options);
90
+ const clientVersion = await resolveCodexClientVersion(
91
+ options.clientVersion,
92
+ options.registryFetchFn ?? fetchFn,
93
+ options.signal,
94
+ );
95
+
96
+ let sawSuccessfulResponse = false;
97
+ for (const path of paths) {
98
+ const requestUrl = buildModelsUrl(baseUrl, path, clientVersion);
99
+ let response: Response;
100
+ try {
101
+ response = await fetchFn(requestUrl, {
102
+ method: "GET",
103
+ headers,
104
+ signal: options.signal,
105
+ });
106
+ } catch {
107
+ continue;
108
+ }
109
+
110
+ if (!response.ok) {
111
+ continue;
112
+ }
113
+
114
+ let payload: unknown;
115
+ try {
116
+ payload = await response.json();
117
+ } catch {
118
+ continue;
119
+ }
120
+
121
+ const models = normalizeCodexModels(payload, baseUrl);
122
+ if (models === null) {
123
+ continue;
124
+ }
125
+ sawSuccessfulResponse = true;
126
+ const etag = getResponseEtag(response.headers);
127
+ return etag ? { models, etag } : { models };
128
+ }
129
+ return sawSuccessfulResponse ? { models: [] } : null;
130
+ }
131
+
132
+ function normalizeBaseUrl(baseUrl: string | undefined): string {
133
+ const raw = (baseUrl ?? CODEX_BASE_URL).trim();
134
+ if (!raw) {
135
+ return CODEX_BASE_URL;
136
+ }
137
+ return raw.replace(/\/+$/, "");
138
+ }
139
+
140
+ function normalizePaths(paths: readonly string[] | undefined): string[] {
141
+ if (!paths || paths.length === 0) {
142
+ return [...DEFAULT_MODEL_LIST_PATHS];
143
+ }
144
+ const normalized = paths
145
+ .map(path => path.trim())
146
+ .filter(path => path.length > 0)
147
+ .map(path => (path.startsWith("/") ? path : `/${path}`));
148
+ return normalized.length > 0 ? normalized : [...DEFAULT_MODEL_LIST_PATHS];
149
+ }
150
+
151
+ function buildModelsUrl(baseUrl: string, path: string, clientVersion: string | undefined): string {
152
+ const url = new URL(`${baseUrl}${path}`);
153
+ if (clientVersion && clientVersion.trim().length > 0) {
154
+ url.searchParams.set("client_version", clientVersion.trim());
155
+ }
156
+ return url.toString();
157
+ }
158
+
159
+ function buildCodexHeaders(options: CodexModelDiscoveryOptions): Headers {
160
+ const headers = new Headers(options.headers);
161
+ headers.set("Authorization", `Bearer ${options.accessToken}`);
162
+ if (options.accountId && options.accountId.trim().length > 0) {
163
+ headers.set(OPENAI_HEADERS.ACCOUNT_ID, options.accountId);
164
+ }
165
+ headers.set(OPENAI_HEADERS.BETA, OPENAI_HEADER_VALUES.BETA_RESPONSES);
166
+ headers.set(OPENAI_HEADERS.ORIGINATOR, OPENAI_HEADER_VALUES.ORIGINATOR_CODEX);
167
+ headers.set("accept", "application/json");
168
+ return headers;
169
+ }
170
+
171
+ async function resolveCodexClientVersion(
172
+ clientVersion: string | undefined,
173
+ fetchFn: typeof fetch,
174
+ signal: AbortSignal | undefined,
175
+ ): Promise<string> {
176
+ const normalizedClientVersion = normalizeClientVersion(clientVersion);
177
+ if (normalizedClientVersion) {
178
+ return normalizedClientVersion;
179
+ }
180
+ try {
181
+ const response = await fetchFn(NPM_CODEX_LATEST_URL, {
182
+ method: "GET",
183
+ headers: { Accept: "application/json" },
184
+ signal,
185
+ });
186
+ if (!response.ok) {
187
+ return DEFAULT_CODEX_CLIENT_VERSION;
188
+ }
189
+ const payload: unknown = await response.json();
190
+ if (!isRecord(payload)) {
191
+ return DEFAULT_CODEX_CLIENT_VERSION;
192
+ }
193
+ const npmVersion = normalizeClientVersion(payload.version);
194
+ return npmVersion ?? DEFAULT_CODEX_CLIENT_VERSION;
195
+ } catch (error) {
196
+ if (isAbortError(error)) {
197
+ throw error;
198
+ }
199
+ return DEFAULT_CODEX_CLIENT_VERSION;
200
+ }
201
+ }
202
+
203
+ function normalizeClientVersion(value: unknown): string | undefined {
204
+ if (typeof value !== "string") {
205
+ return undefined;
206
+ }
207
+ const trimmed = value.trim();
208
+ if (!/^\d+\.\d+\.\d+$/.test(trimmed)) {
209
+ return undefined;
210
+ }
211
+ return trimmed;
212
+ }
213
+
214
+ function isAbortError(error: unknown): error is Error {
215
+ return error instanceof Error && error.name === "AbortError";
216
+ }
217
+
218
+ function normalizeCodexModels(payload: unknown, baseUrl: string): Model<"openai-codex-responses">[] | null {
219
+ const parsedResponse = codexModelsResponseSchema.safeParse(payload);
220
+ if (!parsedResponse.success) {
221
+ return null;
222
+ }
223
+
224
+ const entries = parsedResponse.data.models ?? parsedResponse.data.data ?? [];
225
+ const normalized: NormalizedCodexModel[] = [];
226
+ for (const entry of entries) {
227
+ const model = normalizeCodexModelEntry(entry, baseUrl);
228
+ if (model) {
229
+ normalized.push(model);
230
+ }
231
+ }
232
+
233
+ normalized.sort((left, right) => {
234
+ if (left.priority !== right.priority) {
235
+ return left.priority - right.priority;
236
+ }
237
+ return left.model.id.localeCompare(right.model.id);
238
+ });
239
+
240
+ return normalized.map(item => item.model);
241
+ }
242
+
243
+ function normalizeCodexModelEntry(entry: unknown, baseUrl: string): NormalizedCodexModel | null {
244
+ const parsedEntry = codexModelEntrySchema.safeParse(entry);
245
+ if (!parsedEntry.success) {
246
+ return null;
247
+ }
248
+
249
+ const payload: CodexModelEntry = parsedEntry.data;
250
+ const slug = toNonEmptyString(payload.slug) ?? toNonEmptyString(payload.id);
251
+ if (!slug) {
252
+ return null;
253
+ }
254
+
255
+ const supportedInApi = toBoolean(payload.supported_in_api);
256
+ if (supportedInApi === false) {
257
+ return null;
258
+ }
259
+
260
+ const name = toNonEmptyString(payload.display_name) ?? slug;
261
+ const contextWindow = toPositiveInt(payload.context_window) ?? DEFAULT_CONTEXT_WINDOW;
262
+ const maxTokens = Math.min(DEFAULT_MAX_TOKENS, contextWindow);
263
+ const reasoning = supportsReasoning(payload.default_reasoning_level, payload.supported_reasoning_levels);
264
+ const input = normalizeInputModalities(payload.input_modalities);
265
+ const preferWebsockets = toBoolean(payload.prefer_websockets) === true;
266
+ const priority = toFiniteNumber(payload.priority) ?? Number.MAX_SAFE_INTEGER;
267
+
268
+ return {
269
+ priority,
270
+ model: {
271
+ id: slug,
272
+ name,
273
+ api: "openai-codex-responses",
274
+ provider: "openai-codex",
275
+ baseUrl,
276
+ reasoning,
277
+ input,
278
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
279
+ contextWindow,
280
+ maxTokens,
281
+ ...(preferWebsockets ? { preferWebsockets: true } : {}),
282
+ ...(priority !== Number.MAX_SAFE_INTEGER ? { priority } : {}),
283
+ },
284
+ };
285
+ }
286
+
287
+ function supportsReasoning(defaultReasoningLevel: unknown, supportedReasoningLevels: unknown): boolean {
288
+ const defaultLevel = toNonEmptyString(defaultReasoningLevel)?.toLowerCase();
289
+ if (defaultLevel && defaultLevel !== "none") {
290
+ return true;
291
+ }
292
+
293
+ if (!Array.isArray(supportedReasoningLevels)) {
294
+ return false;
295
+ }
296
+
297
+ for (const level of supportedReasoningLevels) {
298
+ const parsedLevel = codexReasoningPresetSchema.safeParse(level);
299
+ if (!parsedLevel.success) {
300
+ continue;
301
+ }
302
+ const effort = toNonEmptyString(parsedLevel.data.effort)?.toLowerCase();
303
+ if (effort && effort !== "none") {
304
+ return true;
305
+ }
306
+ }
307
+
308
+ return false;
309
+ }
310
+
311
+ function normalizeInputModalities(inputModalities: unknown): ("text" | "image")[] {
312
+ if (!Array.isArray(inputModalities)) {
313
+ return ["text", "image"];
314
+ }
315
+
316
+ const set = new Set<"text" | "image">();
317
+ for (const modality of inputModalities) {
318
+ const normalized = toNonEmptyString(modality)?.toLowerCase();
319
+ if (normalized === "text" || normalized === "image") {
320
+ set.add(normalized);
321
+ }
322
+ }
323
+
324
+ if (set.size === 0) {
325
+ return ["text", "image"];
326
+ }
327
+
328
+ const canonical: ("text" | "image")[] = ["text", "image"];
329
+ return canonical.filter(modality => set.has(modality));
330
+ }
331
+
332
+ function getResponseEtag(headers: Headers): string | undefined {
333
+ const etag = headers.get("etag");
334
+ if (!etag) {
335
+ return undefined;
336
+ }
337
+ const trimmed = etag.trim();
338
+ return trimmed.length > 0 ? trimmed : undefined;
339
+ }
340
+
341
+ function toNonEmptyString(value: unknown): string | null {
342
+ if (typeof value !== "string") {
343
+ return null;
344
+ }
345
+ const trimmed = value.trim();
346
+ return trimmed.length > 0 ? trimmed : null;
347
+ }
348
+
349
+ function toPositiveInt(value: unknown): number | null {
350
+ if (typeof value !== "number" || !Number.isFinite(value)) {
351
+ return null;
352
+ }
353
+ if (value <= 0) {
354
+ return null;
355
+ }
356
+ return Math.trunc(value);
357
+ }
358
+
359
+ function toFiniteNumber(value: unknown): number | null {
360
+ if (typeof value !== "number" || !Number.isFinite(value)) {
361
+ return null;
362
+ }
363
+ return value;
364
+ }
365
+
366
+ function toBoolean(value: unknown): boolean | null {
367
+ if (typeof value !== "boolean") {
368
+ return null;
369
+ }
370
+ return value;
371
+ }