@vib-rato/ai 0.16.0

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 (525) hide show
  1. package/CHANGELOG.md +3354 -0
  2. package/README.md +1194 -0
  3. package/dist/types/adapter-internals/provider-safety-stop.d.ts +45 -0
  4. package/dist/types/api-registry.d.ts +30 -0
  5. package/dist/types/auth-broker/client.d.ts +80 -0
  6. package/dist/types/auth-broker/index.d.ts +5 -0
  7. package/dist/types/auth-broker/redact.d.ts +7 -0
  8. package/dist/types/auth-broker/refresher.d.ts +25 -0
  9. package/dist/types/auth-broker/remote-store.d.ts +153 -0
  10. package/dist/types/auth-broker/server.d.ts +32 -0
  11. package/dist/types/auth-broker/types.d.ts +132 -0
  12. package/dist/types/auth-broker/wire-schemas.d.ts +555 -0
  13. package/dist/types/auth-gateway/http.d.ts +40 -0
  14. package/dist/types/auth-gateway/index.d.ts +3 -0
  15. package/dist/types/auth-gateway/server.d.ts +70 -0
  16. package/dist/types/auth-gateway/types.d.ts +129 -0
  17. package/dist/types/auth-storage.d.ts +1074 -0
  18. package/dist/types/cli.d.ts +2 -0
  19. package/dist/types/codex-tools.d.ts +4 -0
  20. package/dist/types/context-cap-policy.d.ts +68 -0
  21. package/dist/types/core.d.ts +35 -0
  22. package/dist/types/index.d.ts +55 -0
  23. package/dist/types/model-cache.d.ts +24 -0
  24. package/dist/types/model-manager.d.ts +77 -0
  25. package/dist/types/model-pricing.d.ts +3 -0
  26. package/dist/types/model-retirements.d.ts +6 -0
  27. package/dist/types/model-thinking.d.ts +100 -0
  28. package/dist/types/models.d.ts +21 -0
  29. package/dist/types/openai-completions-compat.d.ts +34 -0
  30. package/dist/types/provider-details.d.ts +24 -0
  31. package/dist/types/provider-models/bundled-references.d.ts +4 -0
  32. package/dist/types/provider-models/descriptors.d.ts +48 -0
  33. package/dist/types/provider-models/google.d.ts +20 -0
  34. package/dist/types/provider-models/index.d.ts +5 -0
  35. package/dist/types/provider-models/ollama.d.ts +7 -0
  36. package/dist/types/provider-models/openai-compat.d.ts +293 -0
  37. package/dist/types/provider-models/special.d.ts +29 -0
  38. package/dist/types/providers/amazon-bedrock.d.ts +60 -0
  39. package/dist/types/providers/anthropic-messages-server-schema.d.ts +450 -0
  40. package/dist/types/providers/anthropic-messages-server.d.ts +17 -0
  41. package/dist/types/providers/anthropic.d.ts +280 -0
  42. package/dist/types/providers/aws-credential-config.d.ts +19 -0
  43. package/dist/types/providers/aws-credentials.d.ts +43 -0
  44. package/dist/types/providers/aws-eventstream.d.ts +38 -0
  45. package/dist/types/providers/aws-sigv4.d.ts +55 -0
  46. package/dist/types/providers/azure-openai-responses.d.ts +22 -0
  47. package/dist/types/providers/composer-discipline.d.ts +32 -0
  48. package/dist/types/providers/cursor/client-version.d.ts +10 -0
  49. package/dist/types/providers/cursor/exec-modern.d.ts +98 -0
  50. package/dist/types/providers/cursor/gen/agent_pb.d.ts +16769 -0
  51. package/dist/types/providers/cursor-pi-args.d.ts +119 -0
  52. package/dist/types/providers/cursor.d.ts +72 -0
  53. package/dist/types/providers/dashscope-token-plan-headers.d.ts +57 -0
  54. package/dist/types/providers/error-message.d.ts +27 -0
  55. package/dist/types/providers/github-copilot-headers.d.ts +40 -0
  56. package/dist/types/providers/gitlab-duo.d.ts +27 -0
  57. package/dist/types/providers/google-auth.d.ts +26 -0
  58. package/dist/types/providers/google-gemini-cli.d.ts +75 -0
  59. package/dist/types/providers/google-gemini-headers.d.ts +43 -0
  60. package/dist/types/providers/google-shared.d.ts +183 -0
  61. package/dist/types/providers/google-types.d.ts +138 -0
  62. package/dist/types/providers/google-vertex.d.ts +11 -0
  63. package/dist/types/providers/google.d.ts +4 -0
  64. package/dist/types/providers/grammar.d.ts +1 -0
  65. package/dist/types/providers/kimi.d.ts +27 -0
  66. package/dist/types/providers/kiro-api-key.d.ts +50 -0
  67. package/dist/types/providers/kiro-codewhisperer.d.ts +11 -0
  68. package/dist/types/providers/mock.d.ts +189 -0
  69. package/dist/types/providers/ollama.d.ts +41 -0
  70. package/dist/types/providers/openai-anthropic-shim.d.ts +31 -0
  71. package/dist/types/providers/openai-bounded-rate-limits.d.ts +3 -0
  72. package/dist/types/providers/openai-chat-server-schema.d.ts +1733 -0
  73. package/dist/types/providers/openai-chat-server.d.ts +16 -0
  74. package/dist/types/providers/openai-codex/constants.d.ts +26 -0
  75. package/dist/types/providers/openai-codex/request-transformer.d.ts +50 -0
  76. package/dist/types/providers/openai-codex/response-handler.d.ts +18 -0
  77. package/dist/types/providers/openai-codex-responses.d.ts +71 -0
  78. package/dist/types/providers/openai-completions-compat.d.ts +6 -0
  79. package/dist/types/providers/openai-completions.d.ts +35 -0
  80. package/dist/types/providers/openai-opencodex-responses.d.ts +10 -0
  81. package/dist/types/providers/openai-request-transform.d.ts +4 -0
  82. package/dist/types/providers/openai-responses-server-schema.d.ts +392 -0
  83. package/dist/types/providers/openai-responses-server.d.ts +17 -0
  84. package/dist/types/providers/openai-responses-shared.d.ts +106 -0
  85. package/dist/types/providers/openai-responses.d.ts +37 -0
  86. package/dist/types/providers/pi-native-client.d.ts +29 -0
  87. package/dist/types/providers/pi-native-server.d.ts +60 -0
  88. package/dist/types/providers/register-builtins.d.ts +59 -0
  89. package/dist/types/providers/synthetic.d.ts +26 -0
  90. package/dist/types/providers/transform-messages.d.ts +33 -0
  91. package/dist/types/providers/vision-guard.d.ts +8 -0
  92. package/dist/types/rate-limit-utils.d.ts +19 -0
  93. package/dist/types/stream.d.ts +45 -0
  94. package/dist/types/types.d.ts +1073 -0
  95. package/dist/types/usage/claude.d.ts +3 -0
  96. package/dist/types/usage/gemini.d.ts +2 -0
  97. package/dist/types/usage/github-copilot.d.ts +7 -0
  98. package/dist/types/usage/google-antigravity.d.ts +2 -0
  99. package/dist/types/usage/grok-cli.d.ts +17 -0
  100. package/dist/types/usage/kimi.d.ts +4 -0
  101. package/dist/types/usage/minimax-code.d.ts +2 -0
  102. package/dist/types/usage/openai-codex.d.ts +3 -0
  103. package/dist/types/usage/shared.d.ts +1 -0
  104. package/dist/types/usage/zai.d.ts +2 -0
  105. package/dist/types/usage.d.ts +264 -0
  106. package/dist/types/utils/abort.d.ts +19 -0
  107. package/dist/types/utils/anthropic-auth.d.ts +39 -0
  108. package/dist/types/utils/block-symbols.d.ts +6 -0
  109. package/dist/types/utils/discovery/antigravity.d.ts +67 -0
  110. package/dist/types/utils/discovery/codex.d.ts +38 -0
  111. package/dist/types/utils/discovery/cursor.d.ts +49 -0
  112. package/dist/types/utils/discovery/gemini.d.ts +25 -0
  113. package/dist/types/utils/discovery/index.d.ts +4 -0
  114. package/dist/types/utils/discovery/openai-compatible.d.ts +81 -0
  115. package/dist/types/utils/event-stream.d.ts +41 -0
  116. package/dist/types/utils/fallback-transport.d.ts +110 -0
  117. package/dist/types/utils/fireworks-model-id.d.ts +10 -0
  118. package/dist/types/utils/foundry.d.ts +11 -0
  119. package/dist/types/utils/h2-fetch.d.ts +22 -0
  120. package/dist/types/utils/http-inspector.d.ts +59 -0
  121. package/dist/types/utils/idle-iterator.d.ts +122 -0
  122. package/dist/types/utils/json-parse.d.ts +98 -0
  123. package/dist/types/utils/oauth/alibaba-token-plan.d.ts +19 -0
  124. package/dist/types/utils/oauth/anthropic.d.ts +41 -0
  125. package/dist/types/utils/oauth/api-key-login.d.ts +38 -0
  126. package/dist/types/utils/oauth/api-key-validation.d.ts +39 -0
  127. package/dist/types/utils/oauth/bizrouter.d.ts +1 -0
  128. package/dist/types/utils/oauth/callback-server.d.ts +80 -0
  129. package/dist/types/utils/oauth/cerebras.d.ts +1 -0
  130. package/dist/types/utils/oauth/cloudflare-ai-gateway.d.ts +18 -0
  131. package/dist/types/utils/oauth/commandcode.d.ts +1 -0
  132. package/dist/types/utils/oauth/cursor.d.ts +15 -0
  133. package/dist/types/utils/oauth/deepinfra.d.ts +1 -0
  134. package/dist/types/utils/oauth/deepseek.d.ts +10 -0
  135. package/dist/types/utils/oauth/firepass.d.ts +1 -0
  136. package/dist/types/utils/oauth/fireworks.d.ts +1 -0
  137. package/dist/types/utils/oauth/fugu.d.ts +1 -0
  138. package/dist/types/utils/oauth/github-copilot.d.ts +38 -0
  139. package/dist/types/utils/oauth/gitlab-duo.d.ts +3 -0
  140. package/dist/types/utils/oauth/glm-zcode.d.ts +71 -0
  141. package/dist/types/utils/oauth/google-antigravity.d.ts +11 -0
  142. package/dist/types/utils/oauth/google-gemini-cli.d.ts +10 -0
  143. package/dist/types/utils/oauth/google-oauth-shared.d.ts +28 -0
  144. package/dist/types/utils/oauth/huggingface.d.ts +19 -0
  145. package/dist/types/utils/oauth/index.d.ts +39 -0
  146. package/dist/types/utils/oauth/kagi.d.ts +17 -0
  147. package/dist/types/utils/oauth/kilo.d.ts +5 -0
  148. package/dist/types/utils/oauth/kimi.d.ts +17 -0
  149. package/dist/types/utils/oauth/kiro.d.ts +71 -0
  150. package/dist/types/utils/oauth/litellm.d.ts +18 -0
  151. package/dist/types/utils/oauth/lm-studio.d.ts +17 -0
  152. package/dist/types/utils/oauth/mara.d.ts +1 -0
  153. package/dist/types/utils/oauth/minimax-code.d.ts +28 -0
  154. package/dist/types/utils/oauth/moonshot.d.ts +1 -0
  155. package/dist/types/utils/oauth/nanogpt.d.ts +1 -0
  156. package/dist/types/utils/oauth/nvidia.d.ts +18 -0
  157. package/dist/types/utils/oauth/ollama-cloud.d.ts +2 -0
  158. package/dist/types/utils/oauth/ollama.d.ts +18 -0
  159. package/dist/types/utils/oauth/openai-codex.d.ts +21 -0
  160. package/dist/types/utils/oauth/opencode.d.ts +18 -0
  161. package/dist/types/utils/oauth/opengateway.d.ts +1 -0
  162. package/dist/types/utils/oauth/openrouter.d.ts +1 -0
  163. package/dist/types/utils/oauth/parallel.d.ts +17 -0
  164. package/dist/types/utils/oauth/perplexity.d.ts +4 -0
  165. package/dist/types/utils/oauth/pkce.d.ts +8 -0
  166. package/dist/types/utils/oauth/qianfan.d.ts +17 -0
  167. package/dist/types/utils/oauth/qwen-portal.d.ts +19 -0
  168. package/dist/types/utils/oauth/sglang.d.ts +16 -0
  169. package/dist/types/utils/oauth/synthetic.d.ts +1 -0
  170. package/dist/types/utils/oauth/tavily.d.ts +17 -0
  171. package/dist/types/utils/oauth/together.d.ts +1 -0
  172. package/dist/types/utils/oauth/types.d.ts +56 -0
  173. package/dist/types/utils/oauth/venice.d.ts +18 -0
  174. package/dist/types/utils/oauth/vercel-ai-gateway.d.ts +18 -0
  175. package/dist/types/utils/oauth/vllm.d.ts +16 -0
  176. package/dist/types/utils/oauth/xai.d.ts +30 -0
  177. package/dist/types/utils/oauth/xiaomi.d.ts +25 -0
  178. package/dist/types/utils/oauth/zai.d.ts +18 -0
  179. package/dist/types/utils/oauth/zenmux.d.ts +1 -0
  180. package/dist/types/utils/overflow.d.ts +14 -0
  181. package/dist/types/utils/parse-bind.d.ts +26 -0
  182. package/dist/types/utils/provider-response.d.ts +6 -0
  183. package/dist/types/utils/provider-safety-stop.d.ts +8 -0
  184. package/dist/types/utils/proxy.d.ts +7 -0
  185. package/dist/types/utils/retry-after.d.ts +3 -0
  186. package/dist/types/utils/retry-budget.d.ts +1 -0
  187. package/dist/types/utils/retry.d.ts +29 -0
  188. package/dist/types/utils/schema/adapt.d.ts +24 -0
  189. package/dist/types/utils/schema/compatibility.d.ts +30 -0
  190. package/dist/types/utils/schema/dereference.d.ts +11 -0
  191. package/dist/types/utils/schema/draft.d.ts +10 -0
  192. package/dist/types/utils/schema/equality.d.ts +4 -0
  193. package/dist/types/utils/schema/fields.d.ts +49 -0
  194. package/dist/types/utils/schema/index.d.ts +14 -0
  195. package/dist/types/utils/schema/json-schema-validator.d.ts +12 -0
  196. package/dist/types/utils/schema/meta-validator.d.ts +2 -0
  197. package/dist/types/utils/schema/normalize.d.ts +93 -0
  198. package/dist/types/utils/schema/root-combinator.d.ts +12 -0
  199. package/dist/types/utils/schema/spill.d.ts +8 -0
  200. package/dist/types/utils/schema/stamps.d.ts +25 -0
  201. package/dist/types/utils/schema/types.d.ts +4 -0
  202. package/dist/types/utils/schema/wire.d.ts +54 -0
  203. package/dist/types/utils/schema/zod-decontaminate.d.ts +31 -0
  204. package/dist/types/utils/sse-debug.d.ts +10 -0
  205. package/dist/types/utils/tool-call-healing.d.ts +80 -0
  206. package/dist/types/utils/tool-choice-capability.d.ts +57 -0
  207. package/dist/types/utils/tool-choice.d.ts +50 -0
  208. package/dist/types/utils/validation.d.ts +17 -0
  209. package/dist/types/utils.d.ts +117 -0
  210. package/package.json +152 -0
  211. package/src/adapter-internals/provider-safety-stop.d.ts +45 -0
  212. package/src/adapter-internals/provider-safety-stop.ts +156 -0
  213. package/src/api-registry.d.ts +30 -0
  214. package/src/api-registry.ts +96 -0
  215. package/src/auth-broker/client.ts +444 -0
  216. package/src/auth-broker/index.ts +5 -0
  217. package/src/auth-broker/redact.ts +39 -0
  218. package/src/auth-broker/refresher.ts +130 -0
  219. package/src/auth-broker/remote-store.ts +1576 -0
  220. package/src/auth-broker/server.ts +764 -0
  221. package/src/auth-broker/types.ts +164 -0
  222. package/src/auth-broker/wire-schemas.ts +261 -0
  223. package/src/auth-gateway/http.ts +198 -0
  224. package/src/auth-gateway/index.ts +3 -0
  225. package/src/auth-gateway/server.ts +1315 -0
  226. package/src/auth-gateway/types.ts +160 -0
  227. package/src/auth-storage.ts +7312 -0
  228. package/src/cli.ts +269 -0
  229. package/src/codex-tools.d.ts +4 -0
  230. package/src/codex-tools.ts +24 -0
  231. package/src/context-cap-policy.d.ts +68 -0
  232. package/src/context-cap-policy.ts +123 -0
  233. package/src/core.ts +44 -0
  234. package/src/index.ts +61 -0
  235. package/src/model-cache.ts +236 -0
  236. package/src/model-manager.ts +744 -0
  237. package/src/model-pricing.d.ts +3 -0
  238. package/src/model-pricing.ts +68 -0
  239. package/src/model-retirements.d.ts +6 -0
  240. package/src/model-retirements.ts +19 -0
  241. package/src/model-thinking.d.ts +100 -0
  242. package/src/model-thinking.ts +1054 -0
  243. package/src/models.d.ts +21 -0
  244. package/src/models.json +94672 -0
  245. package/src/models.json.d.ts +9 -0
  246. package/src/models.ts +126 -0
  247. package/src/openai-completions-compat.d.ts +34 -0
  248. package/src/openai-completions-compat.ts +383 -0
  249. package/src/prompts/composer-bash-policy-recovery.md +1 -0
  250. package/src/prompts/cursor-composer-bash-policy-recovery.md +1 -0
  251. package/src/prompts/cursor-composer-edit-discipline.md +7 -0
  252. package/src/prompts/turn-aborted-guidance.md +4 -0
  253. package/src/provider-details.ts +90 -0
  254. package/src/provider-models/bundled-references.ts +38 -0
  255. package/src/provider-models/descriptors.ts +392 -0
  256. package/src/provider-models/google.ts +92 -0
  257. package/src/provider-models/index.ts +5 -0
  258. package/src/provider-models/ollama.ts +159 -0
  259. package/src/provider-models/openai-compat.ts +2920 -0
  260. package/src/provider-models/special.ts +185 -0
  261. package/src/providers/amazon-bedrock.d.ts +60 -0
  262. package/src/providers/amazon-bedrock.ts +939 -0
  263. package/src/providers/anthropic-messages-server-schema.ts +229 -0
  264. package/src/providers/anthropic-messages-server.ts +839 -0
  265. package/src/providers/anthropic.d.ts +280 -0
  266. package/src/providers/anthropic.ts +4421 -0
  267. package/src/providers/aws-credential-config.d.ts +19 -0
  268. package/src/providers/aws-credential-config.ts +179 -0
  269. package/src/providers/aws-credentials.d.ts +43 -0
  270. package/src/providers/aws-credentials.ts +457 -0
  271. package/src/providers/aws-eventstream.d.ts +38 -0
  272. package/src/providers/aws-eventstream.ts +185 -0
  273. package/src/providers/aws-sigv4.d.ts +55 -0
  274. package/src/providers/aws-sigv4.ts +218 -0
  275. package/src/providers/azure-openai-responses.d.ts +22 -0
  276. package/src/providers/azure-openai-responses.ts +447 -0
  277. package/src/providers/composer-discipline.d.ts +32 -0
  278. package/src/providers/composer-discipline.ts +95 -0
  279. package/src/providers/cursor/client-version.d.ts +10 -0
  280. package/src/providers/cursor/client-version.ts +10 -0
  281. package/src/providers/cursor/exec-modern.d.ts +98 -0
  282. package/src/providers/cursor/exec-modern.ts +497 -0
  283. package/src/providers/cursor/gen/agent_pb.d.ts +16769 -0
  284. package/src/providers/cursor/gen/agent_pb.ts +19780 -0
  285. package/src/providers/cursor/proto/agent.proto +4533 -0
  286. package/src/providers/cursor/proto/buf.gen.yaml +6 -0
  287. package/src/providers/cursor/proto/buf.yaml +17 -0
  288. package/src/providers/cursor-pi-args.d.ts +119 -0
  289. package/src/providers/cursor-pi-args.ts +187 -0
  290. package/src/providers/cursor.d.ts +72 -0
  291. package/src/providers/cursor.ts +3396 -0
  292. package/src/providers/dashscope-token-plan-headers.d.ts +57 -0
  293. package/src/providers/dashscope-token-plan-headers.ts +84 -0
  294. package/src/providers/error-message.d.ts +27 -0
  295. package/src/providers/error-message.ts +21 -0
  296. package/src/providers/github-copilot-headers.d.ts +40 -0
  297. package/src/providers/github-copilot-headers.ts +140 -0
  298. package/src/providers/gitlab-duo.d.ts +27 -0
  299. package/src/providers/gitlab-duo.ts +393 -0
  300. package/src/providers/google-auth.d.ts +26 -0
  301. package/src/providers/google-auth.ts +262 -0
  302. package/src/providers/google-gemini-cli.d.ts +75 -0
  303. package/src/providers/google-gemini-cli.ts +969 -0
  304. package/src/providers/google-gemini-headers.d.ts +43 -0
  305. package/src/providers/google-gemini-headers.ts +100 -0
  306. package/src/providers/google-shared.d.ts +183 -0
  307. package/src/providers/google-shared.ts +1105 -0
  308. package/src/providers/google-types.d.ts +138 -0
  309. package/src/providers/google-types.ts +167 -0
  310. package/src/providers/google-vertex.d.ts +11 -0
  311. package/src/providers/google-vertex.ts +124 -0
  312. package/src/providers/google.d.ts +4 -0
  313. package/src/providers/google.ts +41 -0
  314. package/src/providers/grammar.d.ts +1 -0
  315. package/src/providers/grammar.ts +70 -0
  316. package/src/providers/kimi.d.ts +27 -0
  317. package/src/providers/kimi.ts +52 -0
  318. package/src/providers/kiro-api-key.d.ts +50 -0
  319. package/src/providers/kiro-api-key.ts +786 -0
  320. package/src/providers/kiro-codewhisperer.d.ts +11 -0
  321. package/src/providers/kiro-codewhisperer.ts +600 -0
  322. package/src/providers/mock.ts +526 -0
  323. package/src/providers/ollama.d.ts +41 -0
  324. package/src/providers/ollama.ts +645 -0
  325. package/src/providers/openai-anthropic-shim.d.ts +31 -0
  326. package/src/providers/openai-anthropic-shim.ts +156 -0
  327. package/src/providers/openai-bounded-rate-limits.d.ts +3 -0
  328. package/src/providers/openai-bounded-rate-limits.ts +57 -0
  329. package/src/providers/openai-chat-server-schema.ts +254 -0
  330. package/src/providers/openai-chat-server.ts +724 -0
  331. package/src/providers/openai-codex/constants.d.ts +26 -0
  332. package/src/providers/openai-codex/constants.ts +43 -0
  333. package/src/providers/openai-codex/request-transformer.d.ts +50 -0
  334. package/src/providers/openai-codex/request-transformer.ts +219 -0
  335. package/src/providers/openai-codex/response-handler.d.ts +18 -0
  336. package/src/providers/openai-codex/response-handler.ts +111 -0
  337. package/src/providers/openai-codex-responses.d.ts +71 -0
  338. package/src/providers/openai-codex-responses.ts +3288 -0
  339. package/src/providers/openai-completions-compat.d.ts +6 -0
  340. package/src/providers/openai-completions-compat.ts +6 -0
  341. package/src/providers/openai-completions.d.ts +35 -0
  342. package/src/providers/openai-completions.ts +2294 -0
  343. package/src/providers/openai-opencodex-responses.ts +174 -0
  344. package/src/providers/openai-request-transform.d.ts +4 -0
  345. package/src/providers/openai-request-transform.ts +136 -0
  346. package/src/providers/openai-responses-server-schema.ts +290 -0
  347. package/src/providers/openai-responses-server.ts +1268 -0
  348. package/src/providers/openai-responses-shared.d.ts +106 -0
  349. package/src/providers/openai-responses-shared.ts +1253 -0
  350. package/src/providers/openai-responses.d.ts +37 -0
  351. package/src/providers/openai-responses.ts +989 -0
  352. package/src/providers/pi-native-client.d.ts +29 -0
  353. package/src/providers/pi-native-client.ts +243 -0
  354. package/src/providers/pi-native-server.ts +488 -0
  355. package/src/providers/register-builtins.d.ts +59 -0
  356. package/src/providers/register-builtins.ts +544 -0
  357. package/src/providers/synthetic.d.ts +26 -0
  358. package/src/providers/synthetic.ts +50 -0
  359. package/src/providers/transform-messages.d.ts +33 -0
  360. package/src/providers/transform-messages.ts +408 -0
  361. package/src/providers/vision-guard.d.ts +8 -0
  362. package/src/providers/vision-guard.ts +31 -0
  363. package/src/rate-limit-utils.d.ts +19 -0
  364. package/src/rate-limit-utils.ts +102 -0
  365. package/src/stream.d.ts +45 -0
  366. package/src/stream.ts +1306 -0
  367. package/src/types.d.ts +1073 -0
  368. package/src/types.ts +1305 -0
  369. package/src/usage/claude.ts +449 -0
  370. package/src/usage/gemini.ts +250 -0
  371. package/src/usage/github-copilot.ts +421 -0
  372. package/src/usage/google-antigravity.ts +201 -0
  373. package/src/usage/grok-cli.ts +259 -0
  374. package/src/usage/kimi.ts +285 -0
  375. package/src/usage/minimax-code.ts +31 -0
  376. package/src/usage/openai-codex.ts +503 -0
  377. package/src/usage/shared.ts +10 -0
  378. package/src/usage/zai.ts +247 -0
  379. package/src/usage.ts +190 -0
  380. package/src/utils/abort.d.ts +19 -0
  381. package/src/utils/abort.ts +51 -0
  382. package/src/utils/anthropic-auth.ts +95 -0
  383. package/src/utils/block-symbols.d.ts +6 -0
  384. package/src/utils/block-symbols.ts +11 -0
  385. package/src/utils/discovery/antigravity.ts +275 -0
  386. package/src/utils/discovery/codex.ts +362 -0
  387. package/src/utils/discovery/cursor.ts +388 -0
  388. package/src/utils/discovery/gemini.ts +248 -0
  389. package/src/utils/discovery/index.ts +4 -0
  390. package/src/utils/discovery/openai-compatible.ts +379 -0
  391. package/src/utils/event-stream.d.ts +41 -0
  392. package/src/utils/event-stream.ts +269 -0
  393. package/src/utils/fallback-transport.d.ts +110 -0
  394. package/src/utils/fallback-transport.ts +411 -0
  395. package/src/utils/fireworks-model-id.d.ts +10 -0
  396. package/src/utils/fireworks-model-id.ts +30 -0
  397. package/src/utils/foundry.d.ts +11 -0
  398. package/src/utils/foundry.ts +18 -0
  399. package/src/utils/h2-fetch.ts +60 -0
  400. package/src/utils/http-inspector.d.ts +59 -0
  401. package/src/utils/http-inspector.ts +380 -0
  402. package/src/utils/idle-iterator.d.ts +122 -0
  403. package/src/utils/idle-iterator.ts +410 -0
  404. package/src/utils/json-parse.d.ts +98 -0
  405. package/src/utils/json-parse.ts +607 -0
  406. package/src/utils/oauth/alibaba-token-plan.ts +60 -0
  407. package/src/utils/oauth/anthropic.ts +233 -0
  408. package/src/utils/oauth/api-key-login.ts +98 -0
  409. package/src/utils/oauth/api-key-validation.ts +344 -0
  410. package/src/utils/oauth/bizrouter.ts +15 -0
  411. package/src/utils/oauth/callback-server.d.ts +80 -0
  412. package/src/utils/oauth/callback-server.ts +359 -0
  413. package/src/utils/oauth/cerebras.ts +16 -0
  414. package/src/utils/oauth/cloudflare-ai-gateway.ts +48 -0
  415. package/src/utils/oauth/commandcode.ts +17 -0
  416. package/src/utils/oauth/cursor.ts +157 -0
  417. package/src/utils/oauth/deepinfra.ts +15 -0
  418. package/src/utils/oauth/deepseek.ts +53 -0
  419. package/src/utils/oauth/firepass.ts +24 -0
  420. package/src/utils/oauth/fireworks.ts +15 -0
  421. package/src/utils/oauth/fugu.ts +15 -0
  422. package/src/utils/oauth/github-copilot.d.ts +38 -0
  423. package/src/utils/oauth/github-copilot.ts +362 -0
  424. package/src/utils/oauth/gitlab-duo.ts +123 -0
  425. package/src/utils/oauth/glm-zcode.d.ts +71 -0
  426. package/src/utils/oauth/glm-zcode.ts +433 -0
  427. package/src/utils/oauth/google-antigravity.ts +200 -0
  428. package/src/utils/oauth/google-gemini-cli.ts +256 -0
  429. package/src/utils/oauth/google-oauth-shared.ts +110 -0
  430. package/src/utils/oauth/huggingface.ts +62 -0
  431. package/src/utils/oauth/index.ts +558 -0
  432. package/src/utils/oauth/kagi.ts +47 -0
  433. package/src/utils/oauth/kilo.ts +87 -0
  434. package/src/utils/oauth/kimi.d.ts +17 -0
  435. package/src/utils/oauth/kimi.ts +275 -0
  436. package/src/utils/oauth/kiro.ts +448 -0
  437. package/src/utils/oauth/litellm.ts +47 -0
  438. package/src/utils/oauth/lm-studio.ts +38 -0
  439. package/src/utils/oauth/mara.ts +16 -0
  440. package/src/utils/oauth/minimax-code.ts +78 -0
  441. package/src/utils/oauth/moonshot.ts +16 -0
  442. package/src/utils/oauth/nanogpt.ts +15 -0
  443. package/src/utils/oauth/nvidia.ts +70 -0
  444. package/src/utils/oauth/oauth.html +199 -0
  445. package/src/utils/oauth/ollama-cloud.ts +28 -0
  446. package/src/utils/oauth/ollama.ts +47 -0
  447. package/src/utils/oauth/openai-codex.ts +299 -0
  448. package/src/utils/oauth/opencode.ts +49 -0
  449. package/src/utils/oauth/opengateway.ts +15 -0
  450. package/src/utils/oauth/openrouter.ts +16 -0
  451. package/src/utils/oauth/parallel.ts +46 -0
  452. package/src/utils/oauth/perplexity.ts +225 -0
  453. package/src/utils/oauth/pkce.ts +18 -0
  454. package/src/utils/oauth/qianfan.ts +58 -0
  455. package/src/utils/oauth/qwen-portal.ts +60 -0
  456. package/src/utils/oauth/sglang.ts +42 -0
  457. package/src/utils/oauth/synthetic.ts +15 -0
  458. package/src/utils/oauth/tavily.ts +46 -0
  459. package/src/utils/oauth/together.ts +16 -0
  460. package/src/utils/oauth/types.d.ts +56 -0
  461. package/src/utils/oauth/types.ts +122 -0
  462. package/src/utils/oauth/venice.ts +59 -0
  463. package/src/utils/oauth/vercel-ai-gateway.ts +47 -0
  464. package/src/utils/oauth/vllm.ts +42 -0
  465. package/src/utils/oauth/xai.ts +246 -0
  466. package/src/utils/oauth/xiaomi.ts +199 -0
  467. package/src/utils/oauth/zai.ts +60 -0
  468. package/src/utils/oauth/zenmux.ts +15 -0
  469. package/src/utils/overflow.ts +275 -0
  470. package/src/utils/parse-bind.ts +81 -0
  471. package/src/utils/provider-response.d.ts +6 -0
  472. package/src/utils/provider-response.ts +30 -0
  473. package/src/utils/provider-safety-stop.ts +8 -0
  474. package/src/utils/proxy.d.ts +7 -0
  475. package/src/utils/proxy.ts +652 -0
  476. package/src/utils/retry-after.d.ts +3 -0
  477. package/src/utils/retry-after.ts +110 -0
  478. package/src/utils/retry-budget.d.ts +1 -0
  479. package/src/utils/retry-budget.ts +4 -0
  480. package/src/utils/retry.d.ts +29 -0
  481. package/src/utils/retry.ts +67 -0
  482. package/src/utils/schema/CONSTRAINTS.md +164 -0
  483. package/src/utils/schema/adapt.d.ts +24 -0
  484. package/src/utils/schema/adapt.ts +36 -0
  485. package/src/utils/schema/compatibility.d.ts +30 -0
  486. package/src/utils/schema/compatibility.ts +435 -0
  487. package/src/utils/schema/dereference.d.ts +11 -0
  488. package/src/utils/schema/dereference.ts +98 -0
  489. package/src/utils/schema/draft.d.ts +10 -0
  490. package/src/utils/schema/draft.ts +341 -0
  491. package/src/utils/schema/equality.d.ts +4 -0
  492. package/src/utils/schema/equality.ts +97 -0
  493. package/src/utils/schema/fields.d.ts +49 -0
  494. package/src/utils/schema/fields.ts +190 -0
  495. package/src/utils/schema/index.d.ts +14 -0
  496. package/src/utils/schema/index.ts +14 -0
  497. package/src/utils/schema/json-schema-validator.d.ts +12 -0
  498. package/src/utils/schema/json-schema-validator.ts +577 -0
  499. package/src/utils/schema/meta-validator.d.ts +2 -0
  500. package/src/utils/schema/meta-validator.ts +167 -0
  501. package/src/utils/schema/normalize.d.ts +93 -0
  502. package/src/utils/schema/normalize.ts +1588 -0
  503. package/src/utils/schema/root-combinator.d.ts +12 -0
  504. package/src/utils/schema/root-combinator.ts +143 -0
  505. package/src/utils/schema/spill.d.ts +8 -0
  506. package/src/utils/schema/spill.ts +43 -0
  507. package/src/utils/schema/stamps.d.ts +25 -0
  508. package/src/utils/schema/stamps.ts +97 -0
  509. package/src/utils/schema/types.d.ts +4 -0
  510. package/src/utils/schema/types.ts +11 -0
  511. package/src/utils/schema/wire.d.ts +54 -0
  512. package/src/utils/schema/wire.ts +213 -0
  513. package/src/utils/schema/zod-decontaminate.d.ts +31 -0
  514. package/src/utils/schema/zod-decontaminate.ts +331 -0
  515. package/src/utils/sse-debug.d.ts +10 -0
  516. package/src/utils/sse-debug.ts +289 -0
  517. package/src/utils/tool-call-healing.d.ts +80 -0
  518. package/src/utils/tool-call-healing.ts +298 -0
  519. package/src/utils/tool-choice-capability.d.ts +57 -0
  520. package/src/utils/tool-choice-capability.ts +633 -0
  521. package/src/utils/tool-choice.d.ts +50 -0
  522. package/src/utils/tool-choice.ts +99 -0
  523. package/src/utils/validation.ts +1080 -0
  524. package/src/utils.d.ts +117 -0
  525. package/src/utils.ts +523 -0
@@ -0,0 +1,969 @@
1
+ /**
2
+ * Google Gemini CLI / Antigravity provider.
3
+ * Shared implementation for both google-gemini-cli and google-antigravity providers.
4
+ * Uses the Cloud Code Assist API endpoint to access Gemini and Anthropic model models.
5
+ */
6
+ import { createHash, randomBytes, randomUUID } from "node:crypto";
7
+ import { scheduler } from "node:timers/promises";
8
+ import { extractHttpStatusFromError, fetchWithRetry, readSseJson } from "@vib-rato/utils";
9
+ import {
10
+ isProviderSafetyStopAdapterInvocation,
11
+ mintProviderSafetyStop,
12
+ PROVIDER_SAFETY_STOP_ADAPTER_CAPABILITY,
13
+ } from "../adapter-internals/provider-safety-stop";
14
+ import { calculateCost } from "../models";
15
+ import type {
16
+ Api,
17
+ AssistantMessage,
18
+ Context,
19
+ Model,
20
+ StreamFunction,
21
+ StreamOptions,
22
+ TextContent,
23
+ ThinkingContent,
24
+ ToolCall,
25
+ } from "../types";
26
+ import { normalizeSystemPrompts } from "../utils";
27
+ import { AssistantMessageEventStream } from "../utils/event-stream";
28
+ import { transportFailureFacts } from "../utils/fallback-transport";
29
+ import { appendRawHttpRequestDumpFor400, type RawHttpRequestDump, withHttpStatus } from "../utils/http-inspector";
30
+ import { resolveRetryBudget } from "../utils/retry-budget";
31
+ // Refresh is the sole responsibility of AuthStorage (broker-aware, single-flighted);
32
+ // the stream provider trusts the access token threaded through `options.apiKey`.
33
+ import { normalizeSchemaForCCA } from "../utils/schema";
34
+ import {
35
+ isForcedToolChoiceUnsupportedError,
36
+ markToolChoiceIncapability,
37
+ resolveToolChoice,
38
+ } from "../utils/tool-choice-capability";
39
+ import {
40
+ ANTIGRAVITY_SYSTEM_INSTRUCTION,
41
+ getAntigravityRequestHeaders,
42
+ getGeminiCliHeaders,
43
+ } from "./google-gemini-headers";
44
+ import type { Content, FunctionCallingConfigMode, ThinkingConfig } from "./google-shared";
45
+ import {
46
+ convertMessages,
47
+ convertTools,
48
+ type GoogleThinkingLevel,
49
+ getGooglePromptBlockReason,
50
+ isGoogleCandidateSafetyStopReason,
51
+ isGooglePromptSafetyStopReason,
52
+ isThinkingPart,
53
+ mapStopReasonString,
54
+ mapToolChoice,
55
+ nextToolCallId,
56
+ pushBlockEndEvent,
57
+ pushToolCallEvents,
58
+ retainThoughtSignature,
59
+ startTextOrThinkingBlock,
60
+ } from "./google-shared";
61
+
62
+ /**
63
+ * Thinking level for Gemini 3 models. Re-exported from `google-shared` so existing
64
+ * `import { GoogleThinkingLevel } from "./google-gemini-cli"` callers keep working.
65
+ */
66
+ export type { GoogleThinkingLevel };
67
+
68
+ export interface GoogleGeminiCliOptions extends StreamOptions {
69
+ toolChoice?: "auto" | "none" | "any" | "required";
70
+ /**
71
+ * Thinking/reasoning configuration.
72
+ * - Gemini 2.x models: use `budgetTokens` to set the thinking budget
73
+ * - Gemini 3 models (gemini-3-pro-*, gemini-3-flash-*): use `level` instead
74
+ *
75
+ * When using `streamSimple`, this is handled automatically based on the model.
76
+ */
77
+ thinking?: {
78
+ enabled: boolean;
79
+ /** Thinking budget in tokens. Use for Gemini 2.x models. */
80
+ budgetTokens?: number;
81
+ /** Thinking level. Use for Gemini 3 models (LOW/HIGH for Pro, MINIMAL/LOW/MEDIUM/HIGH for Flash). */
82
+ level?: GoogleThinkingLevel;
83
+ };
84
+ projectId?: string;
85
+ }
86
+
87
+ const DEFAULT_ENDPOINT = "https://cloudcode-pa.googleapis.com";
88
+ const ANTIGRAVITY_DAILY_ENDPOINT = "https://daily-cloudcode-pa.googleapis.com";
89
+ const ANTIGRAVITY_SANDBOX_ENDPOINT = "https://daily-cloudcode-pa.sandbox.googleapis.com";
90
+ const ANTIGRAVITY_ENDPOINT_FALLBACKS = [ANTIGRAVITY_DAILY_ENDPOINT, ANTIGRAVITY_SANDBOX_ENDPOINT] as const;
91
+
92
+ export {
93
+ ANTIGRAVITY_SYSTEM_INSTRUCTION,
94
+ getAntigravityRequestHeaders,
95
+ getGeminiCliHeaders,
96
+ getGeminiCliUserAgent,
97
+ } from "./google-gemini-headers";
98
+
99
+ // Retry configuration
100
+ const MAX_RETRIES = 3;
101
+ const BASE_DELAY_MS = 1000;
102
+ const MAX_EMPTY_STREAM_RETRIES = 2;
103
+ const EMPTY_STREAM_BASE_DELAY_MS = 500;
104
+ const RATE_LIMIT_BUDGET_MS = 5 * 60 * 1000;
105
+ const CLAUDE_THINKING_BETA_HEADER = "interleaved-thinking-2025-05-14";
106
+ const GOOGLE_GEMINI_REFRESH_SKEW_MS = 60_000;
107
+ const ANTIGRAVITY_REFRESH_SKEW_MS = 60_000;
108
+
109
+ function isClaudeModel(modelId: string): boolean {
110
+ return modelId.toLowerCase().includes("claude");
111
+ }
112
+
113
+ function needsClaudeThinkingBetaHeader(model: Model<"google-gemini-cli">): boolean {
114
+ return model.provider === "google-antigravity" && model.id.startsWith("claude-") && model.reasoning;
115
+ }
116
+
117
+ function shouldInjectAntigravitySystemInstruction(modelId: string): boolean {
118
+ const normalized = modelId.toLowerCase();
119
+ return normalized.includes("claude") || normalized.includes("gemini-3");
120
+ }
121
+
122
+ /**
123
+ * Extract a clean, user-friendly error message from Google API error response.
124
+ * Parses JSON error responses and returns just the message field.
125
+ */
126
+ function extractErrorMessage(errorText: string): string {
127
+ try {
128
+ const parsed = JSON.parse(errorText) as { error?: { message?: string } };
129
+ if (parsed.error?.message) {
130
+ return parsed.error.message;
131
+ }
132
+ } catch {
133
+ // Not JSON, return as-is
134
+ }
135
+ return errorText;
136
+ }
137
+
138
+ function createGeminiCliHttpError(response: Response, errorText: string, formatErrorMessage = true): Error {
139
+ const message = formatErrorMessage ? extractErrorMessage(errorText) : errorText;
140
+ const error = withHttpStatus(
141
+ new Error(`Cloud Code Assist API error (${response.status}): ${message}`),
142
+ response.status,
143
+ ) as Error & { code?: string; headers?: Headers };
144
+ error.headers = response.headers;
145
+ try {
146
+ const code = (JSON.parse(errorText) as { error?: { code?: unknown } }).error?.code;
147
+ if (typeof code === "string") error.code = code;
148
+ } catch {
149
+ // The response body is not JSON.
150
+ }
151
+ return error;
152
+ }
153
+
154
+ interface GeminiCliApiKeyPayload {
155
+ token?: unknown;
156
+ projectId?: unknown;
157
+ project_id?: unknown;
158
+ refreshToken?: unknown;
159
+ expiresAt?: unknown;
160
+ refresh?: unknown;
161
+ expires?: unknown;
162
+ }
163
+ interface ParsedGeminiCliCredentials {
164
+ accessToken: string;
165
+ projectId: string;
166
+ refreshToken?: string;
167
+ expiresAt?: number;
168
+ }
169
+
170
+ function normalizeExpiryMs(value: unknown): number | undefined {
171
+ if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
172
+ return undefined;
173
+ }
174
+ return value < 10_000_000_000 ? value * 1000 : value;
175
+ }
176
+
177
+ export function parseGeminiCliCredentials(apiKeyRaw: string): ParsedGeminiCliCredentials {
178
+ const invalidCredentialsMessage = "Invalid Google Cloud Code Assist credentials. Use /login to re-authenticate.";
179
+ const missingCredentialsMessage =
180
+ "Missing token or projectId in Google Cloud credentials. Use /login to re-authenticate.";
181
+
182
+ let parsed: GeminiCliApiKeyPayload;
183
+ try {
184
+ parsed = JSON.parse(apiKeyRaw) as GeminiCliApiKeyPayload;
185
+ } catch {
186
+ throw new Error(invalidCredentialsMessage);
187
+ }
188
+
189
+ const projectId =
190
+ typeof parsed.projectId === "string"
191
+ ? parsed.projectId
192
+ : typeof parsed.project_id === "string"
193
+ ? parsed.project_id
194
+ : undefined;
195
+
196
+ if (typeof parsed.token !== "string" || typeof projectId !== "string") {
197
+ throw new Error(missingCredentialsMessage);
198
+ }
199
+
200
+ const refreshToken =
201
+ typeof parsed.refreshToken === "string"
202
+ ? parsed.refreshToken
203
+ : typeof parsed.refresh === "string"
204
+ ? parsed.refresh
205
+ : undefined;
206
+ const expiresAt = normalizeExpiryMs(parsed.expiresAt ?? parsed.expires);
207
+
208
+ return {
209
+ accessToken: parsed.token,
210
+ projectId,
211
+ refreshToken,
212
+ expiresAt,
213
+ };
214
+ }
215
+
216
+ export function shouldRefreshGeminiCliCredentials(
217
+ expiresAt: number | undefined,
218
+ isAntigravity: boolean,
219
+ nowMs = Date.now(),
220
+ ): boolean {
221
+ if (expiresAt === undefined) {
222
+ return false;
223
+ }
224
+
225
+ const skewMs = isAntigravity ? ANTIGRAVITY_REFRESH_SKEW_MS : GOOGLE_GEMINI_REFRESH_SKEW_MS;
226
+ return nowMs + skewMs >= expiresAt;
227
+ }
228
+
229
+ interface CloudCodeAssistRequest {
230
+ project: string;
231
+ model: string;
232
+ request: {
233
+ contents: Content[];
234
+ sessionId?: string;
235
+ systemInstruction?: { role?: string; parts: { text: string }[] };
236
+ generationConfig?: {
237
+ maxOutputTokens?: number;
238
+ temperature?: number;
239
+ topP?: number;
240
+ topK?: number;
241
+ minP?: number;
242
+ presencePenalty?: number;
243
+ repetitionPenalty?: number;
244
+ thinkingConfig?: ThinkingConfig;
245
+ };
246
+ tools?: { functionDeclarations: Record<string, unknown>[] }[] | undefined;
247
+ toolConfig?: {
248
+ functionCallingConfig: {
249
+ mode: FunctionCallingConfigMode;
250
+ };
251
+ };
252
+ // Evidence: Real Antigravity IDE sends preambleConfig with
253
+ // SYSTEM_INSTRUCTION_MODE_REPLACE to control how the server
254
+ // interprets the system instruction (replace vs append).
255
+ // Confirmed via network interception of official IDE traffic.
256
+ preambleConfig?: {
257
+ mode: "SYSTEM_INSTRUCTION_MODE_REPLACE";
258
+ };
259
+ };
260
+ requestType?: string;
261
+ userAgent?: string;
262
+ requestId?: string;
263
+ }
264
+
265
+ interface CloudCodeAssistResponseChunk {
266
+ response?: {
267
+ candidates?: Array<{
268
+ content?: {
269
+ role: string;
270
+ parts?: Array<{
271
+ text?: string;
272
+ thought?: boolean;
273
+ thoughtSignature?: string;
274
+ functionCall?: {
275
+ name: string;
276
+ args: Record<string, unknown>;
277
+ id?: string;
278
+ };
279
+ }>;
280
+ };
281
+ finishReason?: string;
282
+ }>;
283
+ promptFeedback?: {
284
+ blockReason?: string;
285
+ };
286
+ usageMetadata?: {
287
+ promptTokenCount?: number;
288
+ candidatesTokenCount?: number;
289
+ thoughtsTokenCount?: number;
290
+ totalTokenCount?: number;
291
+ cachedContentTokenCount?: number;
292
+ };
293
+ modelVersion?: string;
294
+ responseId?: string;
295
+ };
296
+ traceId?: string;
297
+ }
298
+
299
+ export const streamGoogleGeminiCli: StreamFunction<"google-gemini-cli"> = (
300
+ model: Model<"google-gemini-cli">,
301
+ context: Context,
302
+ options?: GoogleGeminiCliOptions,
303
+ ): AssistantMessageEventStream => {
304
+ const stream = new AssistantMessageEventStream();
305
+
306
+ (async () => {
307
+ const startTime = Date.now();
308
+ let firstTokenTime: number | undefined;
309
+
310
+ const output: AssistantMessage = {
311
+ role: "assistant",
312
+ content: [],
313
+ api: "google-gemini-cli" as Api,
314
+ provider: model.provider,
315
+ model: model.id,
316
+ usage: {
317
+ input: 0,
318
+ output: 0,
319
+ cacheRead: 0,
320
+ cacheWrite: 0,
321
+ totalTokens: 0,
322
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
323
+ },
324
+ stopReason: "stop",
325
+ timestamp: Date.now(),
326
+ };
327
+ let rawRequestDump: RawHttpRequestDump | undefined;
328
+
329
+ try {
330
+ const apiKeyRaw = options?.apiKey;
331
+ if (!apiKeyRaw) {
332
+ throw new Error("Google Cloud Code Assist requires OAuth authentication. Use /login to authenticate.");
333
+ }
334
+
335
+ const isAntigravity = model.provider === "google-antigravity";
336
+ const parsedCredentials = parseGeminiCliCredentials(apiKeyRaw);
337
+ // AuthStorage already refreshed credentials before threading them
338
+ // here (see {@link OAUTH_REFRESH_SKEW_MS}). If the credential lands
339
+ // expired we bail rather than POSTing a stale token; the next call
340
+ // — driven by AuthStorage's invalidate+retry path — will carry a
341
+ // fresh credential.
342
+ if (
343
+ shouldRefreshGeminiCliCredentials(parsedCredentials.expiresAt, isAntigravity) &&
344
+ parsedCredentials.expiresAt !== undefined &&
345
+ Date.now() >= parsedCredentials.expiresAt
346
+ ) {
347
+ throw new Error(
348
+ "OAuth token expired before request — please retry; AuthStorage will refresh on the next attempt.",
349
+ );
350
+ }
351
+ const { accessToken, projectId } = parsedCredentials;
352
+
353
+ const baseUrl = model.baseUrl?.trim();
354
+ const endpoints = baseUrl ? [baseUrl] : isAntigravity ? ANTIGRAVITY_ENDPOINT_FALLBACKS : [DEFAULT_ENDPOINT];
355
+
356
+ let requestBody = buildRequest(model, context, projectId, options, isAntigravity);
357
+ const replacementPayload = await options?.onPayload?.(requestBody, model, options?.attemptScope);
358
+ if (replacementPayload !== undefined) {
359
+ requestBody = replacementPayload as typeof requestBody;
360
+ }
361
+ const headers = isAntigravity
362
+ ? getAntigravityRequestHeaders() // Evidence: UA = "antigravity-ide" (disassembly 0x5ecb1dd)
363
+ : getGeminiCliHeaders(model.id);
364
+
365
+ const requestHeaders = {
366
+ Authorization: `Bearer ${accessToken}`,
367
+ "Content-Type": "application/json",
368
+ Accept: "text/event-stream",
369
+ ...headers,
370
+ ...(needsClaudeThinkingBetaHeader(model) ? { "anthropic-beta": CLAUDE_THINKING_BETA_HEADER } : {}),
371
+ ...(options?.headers ?? {}),
372
+ };
373
+ let requestBodyJson = JSON.stringify(requestBody);
374
+ rawRequestDump = {
375
+ provider: model.provider,
376
+ api: output.api,
377
+ model: model.id,
378
+ method: "POST",
379
+ body: requestBody,
380
+ headers: requestHeaders,
381
+ };
382
+
383
+ const sentForcedToolChoice =
384
+ (requestBody.request.toolConfig?.functionCallingConfig?.mode === "ANY" ||
385
+ requestBody.request.toolConfig?.functionCallingConfig?.mode === "VALIDATED") &&
386
+ options?.toolChoice !== undefined &&
387
+ options.toolChoice !== "auto" &&
388
+ options.toolChoice !== "none";
389
+ options.onStreamCreated?.();
390
+ let response = await fetchWithRetry(
391
+ attempt => `${endpoints[Math.min(attempt, endpoints.length - 1)]}/v1internal:streamGenerateContent?alt=sse`,
392
+ {
393
+ method: "POST",
394
+ headers: requestHeaders,
395
+ body: requestBodyJson,
396
+ signal: options?.signal,
397
+ maxAttempts: resolveRetryBudget(options?.requestMaxRetries, MAX_RETRIES) + 1,
398
+ defaultDelayMs: attempt => BASE_DELAY_MS * 2 ** attempt,
399
+ maxDelayMs: options?.maxRetryDelayMs ?? RATE_LIMIT_BUDGET_MS,
400
+ fetch: options?.fetch,
401
+ },
402
+ );
403
+ if (!response.ok && sentForcedToolChoice) {
404
+ const errorText = await response.text();
405
+ const error = createGeminiCliHttpError(response, errorText);
406
+ if (
407
+ !options?.fallbackManaged &&
408
+ !options?.disableProviderRetries &&
409
+ firstTokenTime === undefined &&
410
+ isForcedToolChoiceUnsupportedError(error, true)
411
+ ) {
412
+ const beforeMark = resolveToolChoice(model, options?.toolChoice);
413
+ markToolChoiceIncapability(model, "auto", error.message);
414
+ stream.push({
415
+ type: "toolChoiceIncapability",
416
+ api: model.api,
417
+ provider: model.provider,
418
+ model: model.id,
419
+ requestedLevel: beforeMark.requestedLevel,
420
+ resolvedLevel: "auto",
421
+ reason: error.message,
422
+ registryKey: beforeMark.registryKey,
423
+ });
424
+ requestBody = {
425
+ ...requestBody,
426
+ request: { ...requestBody.request, toolConfig: undefined },
427
+ };
428
+ requestBodyJson = JSON.stringify(requestBody);
429
+ rawRequestDump = { ...rawRequestDump, body: requestBody };
430
+ options.onStreamCreated?.();
431
+ response = await fetchWithRetry(
432
+ attempt =>
433
+ `${endpoints[Math.min(attempt, endpoints.length - 1)]}/v1internal:streamGenerateContent?alt=sse`,
434
+ {
435
+ method: "POST",
436
+ headers: requestHeaders,
437
+ body: requestBodyJson,
438
+ signal: options?.signal,
439
+ maxAttempts: 1,
440
+ defaultDelayMs: attempt => BASE_DELAY_MS * 2 ** attempt,
441
+ maxDelayMs: options?.maxRetryDelayMs ?? RATE_LIMIT_BUDGET_MS,
442
+ fetch: options?.fetch,
443
+ },
444
+ );
445
+ } else {
446
+ throw error;
447
+ }
448
+ }
449
+ if (!response.ok) {
450
+ const errorText = await response.text();
451
+ throw createGeminiCliHttpError(response, errorText);
452
+ }
453
+ const requestUrl = response.url;
454
+
455
+ let started = false;
456
+ const ensureStarted = () => {
457
+ if (!started) {
458
+ if (!firstTokenTime) firstTokenTime = Date.now();
459
+ stream.push({ type: "start", partial: output });
460
+ started = true;
461
+ }
462
+ };
463
+
464
+ const resetOutput = () => {
465
+ output.content = [];
466
+ output.usage = {
467
+ input: 0,
468
+ output: 0,
469
+ cacheRead: 0,
470
+ cacheWrite: 0,
471
+ totalTokens: 0,
472
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
473
+ };
474
+ output.stopReason = "stop";
475
+ output.errorMessage = undefined;
476
+ output.timestamp = Date.now();
477
+ started = false;
478
+ };
479
+
480
+ const streamResponse = async (activeResponse: Response): Promise<boolean> => {
481
+ if (!activeResponse.body) {
482
+ throw new Error("No response body");
483
+ }
484
+
485
+ let hasContent = false;
486
+ let providerSafetyStop = false;
487
+ let currentBlock: TextContent | ThinkingContent | null = null;
488
+ const blocks = output.content;
489
+ const blockIndex = () => blocks.length - 1;
490
+
491
+ for await (const chunk of readSseJson<CloudCodeAssistResponseChunk>(
492
+ activeResponse.body!,
493
+ options?.signal,
494
+ event =>
495
+ options?.onSseEvent?.(
496
+ { event: event.event, data: event.data, raw: [...event.raw] },
497
+ model,
498
+ options?.attemptScope,
499
+ ),
500
+ )) {
501
+ const responseData = chunk.response;
502
+ if (!responseData) continue;
503
+
504
+ const candidate = responseData.candidates?.[0];
505
+ if (candidate?.content?.parts) {
506
+ for (const part of candidate.content.parts) {
507
+ if (part.text !== undefined) {
508
+ hasContent = true;
509
+ const isThinking = isThinkingPart(part);
510
+ if (
511
+ !currentBlock ||
512
+ (isThinking && currentBlock.type !== "thinking") ||
513
+ (!isThinking && currentBlock.type !== "text")
514
+ ) {
515
+ if (currentBlock) {
516
+ pushBlockEndEvent(currentBlock, blockIndex(), output, stream);
517
+ }
518
+ currentBlock = startTextOrThinkingBlock(isThinking, output, stream, ensureStarted);
519
+ }
520
+ if (currentBlock.type === "thinking") {
521
+ currentBlock.thinking += part.text;
522
+ currentBlock.thinkingSignature = retainThoughtSignature(
523
+ currentBlock.thinkingSignature,
524
+ part.thoughtSignature,
525
+ );
526
+ stream.push({
527
+ type: "thinking_delta",
528
+ contentIndex: blockIndex(),
529
+ delta: part.text,
530
+ partial: output,
531
+ });
532
+ } else {
533
+ currentBlock.text += part.text;
534
+ currentBlock.textSignature = retainThoughtSignature(
535
+ currentBlock.textSignature,
536
+ part.thoughtSignature,
537
+ );
538
+ stream.push({
539
+ type: "text_delta",
540
+ contentIndex: blockIndex(),
541
+ delta: part.text,
542
+ partial: output,
543
+ });
544
+ }
545
+ }
546
+
547
+ if (part.functionCall) {
548
+ hasContent = true;
549
+ if (currentBlock) {
550
+ pushBlockEndEvent(currentBlock, blockIndex(), output, stream);
551
+ currentBlock = null;
552
+ }
553
+
554
+ const providedId = part.functionCall.id;
555
+ const needsNewId =
556
+ !providedId || output.content.some(b => b.type === "toolCall" && b.id === providedId);
557
+ const toolCallId = needsNewId ? nextToolCallId(part.functionCall.name || "tool") : providedId;
558
+
559
+ const toolCall: ToolCall = {
560
+ type: "toolCall",
561
+ id: toolCallId,
562
+ name: part.functionCall.name || "",
563
+ arguments: part.functionCall.args as Record<string, unknown>,
564
+ ...(part.thoughtSignature && { thoughtSignature: part.thoughtSignature }),
565
+ };
566
+
567
+ output.content.push(toolCall);
568
+ ensureStarted();
569
+ pushToolCallEvents(toolCall, blockIndex(), output, stream);
570
+ }
571
+ }
572
+ }
573
+
574
+ if (candidate?.finishReason) {
575
+ if (isGoogleCandidateSafetyStopReason(candidate.finishReason)) {
576
+ providerSafetyStop = true;
577
+ hasContent = true;
578
+ // Adapter-minted terminal authority from the parsed
579
+ // structured finish reason (#4777).
580
+ mintProviderSafetyStop(
581
+ output,
582
+ candidate.finishReason,
583
+ PROVIDER_SAFETY_STOP_ADAPTER_CAPABILITY,
584
+ options?.fetch,
585
+ isProviderSafetyStopAdapterInvocation(options),
586
+ );
587
+ output.stopReason = "error";
588
+ } else if (!providerSafetyStop) {
589
+ output.stopReason = mapStopReasonString(candidate.finishReason);
590
+ if (output.stopReason === "stop" && output.content.some(b => b.type === "toolCall")) {
591
+ output.stopReason = "toolUse";
592
+ }
593
+ }
594
+ }
595
+
596
+ const blockReason = getGooglePromptBlockReason(responseData.promptFeedback);
597
+ if (blockReason) {
598
+ hasContent = true;
599
+ if (isGooglePromptSafetyStopReason(blockReason)) {
600
+ providerSafetyStop = true;
601
+ // Prompt-level block reason: adapter-minted authority (#4777).
602
+ mintProviderSafetyStop(
603
+ output,
604
+ blockReason,
605
+ PROVIDER_SAFETY_STOP_ADAPTER_CAPABILITY,
606
+ options?.fetch,
607
+ isProviderSafetyStopAdapterInvocation(options),
608
+ );
609
+ output.stopReason = "error";
610
+ } else if (!providerSafetyStop) {
611
+ output.stopReason = "error";
612
+ }
613
+ }
614
+
615
+ if (responseData.usageMetadata) {
616
+ // promptTokenCount includes cachedContentTokenCount, so subtract to get fresh input
617
+ const promptTokens = responseData.usageMetadata.promptTokenCount || 0;
618
+ const cacheReadTokens = responseData.usageMetadata.cachedContentTokenCount || 0;
619
+ const thinkingTokens = responseData.usageMetadata.thoughtsTokenCount || 0;
620
+ output.usage = {
621
+ input: promptTokens - cacheReadTokens,
622
+ output: (responseData.usageMetadata.candidatesTokenCount || 0) + thinkingTokens,
623
+ cacheRead: cacheReadTokens,
624
+ cacheWrite: 0,
625
+ totalTokens: responseData.usageMetadata.totalTokenCount || 0,
626
+ ...(thinkingTokens > 0 ? { reasoningTokens: thinkingTokens } : {}),
627
+ cost: {
628
+ input: 0,
629
+ output: 0,
630
+ cacheRead: 0,
631
+ cacheWrite: 0,
632
+ total: 0,
633
+ },
634
+ };
635
+ calculateCost(model, output.usage);
636
+ }
637
+ }
638
+
639
+ if (currentBlock) {
640
+ pushBlockEndEvent(currentBlock, blockIndex(), output, stream);
641
+ }
642
+
643
+ return hasContent;
644
+ };
645
+
646
+ let receivedContent = false;
647
+ let currentResponse = response;
648
+
649
+ const emptyStreamRetryBudget = resolveRetryBudget(options?.streamMaxRetries, MAX_EMPTY_STREAM_RETRIES);
650
+ for (let emptyAttempt = 0; emptyAttempt <= emptyStreamRetryBudget; emptyAttempt++) {
651
+ if (options?.signal?.aborted) {
652
+ throw new Error("Request was aborted");
653
+ }
654
+
655
+ if (emptyAttempt > 0) {
656
+ const backoffMs = EMPTY_STREAM_BASE_DELAY_MS * 2 ** (emptyAttempt - 1);
657
+ try {
658
+ await scheduler.wait(backoffMs, { signal: options?.signal });
659
+ } catch {
660
+ // Normalize AbortError to expected message for consistent error handling
661
+ throw new Error("Request was aborted");
662
+ }
663
+
664
+ if (!requestUrl) {
665
+ throw new Error("Missing request URL");
666
+ }
667
+
668
+ currentResponse = await (options?.fetch ?? fetch)(requestUrl, {
669
+ method: "POST",
670
+ headers: requestHeaders,
671
+ body: requestBodyJson,
672
+ signal: options?.signal,
673
+ });
674
+
675
+ if (!currentResponse.ok) {
676
+ const retryErrorText = await currentResponse.text();
677
+ throw createGeminiCliHttpError(currentResponse, retryErrorText, false);
678
+ }
679
+ }
680
+
681
+ const streamed = await streamResponse(currentResponse);
682
+ if (streamed) {
683
+ receivedContent = true;
684
+ break;
685
+ }
686
+
687
+ if (emptyAttempt < emptyStreamRetryBudget) {
688
+ resetOutput();
689
+ }
690
+ }
691
+
692
+ if (!receivedContent) {
693
+ throw new Error("Cloud Code Assist API returned an empty response");
694
+ }
695
+
696
+ if (options?.signal?.aborted) {
697
+ throw new Error("Request was aborted");
698
+ }
699
+
700
+ if (output.stopReason === "aborted" || output.stopReason === "error") {
701
+ throw new Error(output.errorMessage ?? "An unknown error occurred");
702
+ }
703
+
704
+ output.duration = Date.now() - startTime;
705
+ if (firstTokenTime) output.ttft = firstTokenTime - startTime;
706
+ stream.push({ type: "done", reason: output.stopReason, message: output });
707
+ stream.end();
708
+ } catch (error) {
709
+ for (const block of output.content) {
710
+ if ("index" in block) {
711
+ delete (block as { index?: number }).index;
712
+ }
713
+ }
714
+ output.stopReason = options?.signal?.aborted ? "aborted" : "error";
715
+ output.errorStatus = extractHttpStatusFromError(error);
716
+ output.transportFailure = transportFailureFacts(error);
717
+ output.errorMessage = await appendRawHttpRequestDumpFor400(
718
+ error instanceof Error ? error.message : JSON.stringify(error),
719
+ error,
720
+ rawRequestDump,
721
+ );
722
+ output.duration = Date.now() - startTime;
723
+ if (firstTokenTime) output.ttft = firstTokenTime - startTime;
724
+ stream.push({ type: "error", reason: output.stopReason, error: output });
725
+ stream.end();
726
+ }
727
+ })();
728
+
729
+ return stream;
730
+ };
731
+
732
+ const INT63_MASK = (1n << 63n) - 1n;
733
+ const ANTIGRAVITY_RANDOM_BOUND = 9_000_000_000_000_000_000n;
734
+
735
+ function formatSignedDecimalSessionId(value: bigint): string {
736
+ return `-${value.toString()}`;
737
+ }
738
+
739
+ function deriveSignedDecimalFromHash(text: string): string {
740
+ const digest = createHash("sha256").update(text).digest();
741
+ let value = 0n;
742
+ for (let index = 0; index < 8; index += 1) {
743
+ value = (value << 8n) | BigInt(digest[index] ?? 0);
744
+ }
745
+ return formatSignedDecimalSessionId(value & INT63_MASK);
746
+ }
747
+
748
+ function randomBoundedInt63(maxExclusive: bigint): bigint {
749
+ while (true) {
750
+ const bytes = randomBytes(8);
751
+ let value = 0n;
752
+ for (const byte of bytes) {
753
+ value = (value << 8n) | BigInt(byte);
754
+ }
755
+ value &= INT63_MASK;
756
+ if (value < maxExclusive) {
757
+ return value;
758
+ }
759
+ }
760
+ }
761
+
762
+ function randomSignedDecimalSessionId(): string {
763
+ return formatSignedDecimalSessionId(randomBoundedInt63(ANTIGRAVITY_RANDOM_BOUND));
764
+ }
765
+
766
+ function getFirstUserTextForAntigravitySession(context: Context): string | undefined {
767
+ for (const message of context.messages) {
768
+ if (message.role !== "user") {
769
+ continue;
770
+ }
771
+
772
+ if (typeof message.content === "string") {
773
+ return message.content;
774
+ }
775
+
776
+ if (Array.isArray(message.content)) {
777
+ const firstTextPart = message.content.find((item): item is TextContent => item.type === "text");
778
+ return firstTextPart?.text;
779
+ }
780
+
781
+ return undefined;
782
+ }
783
+
784
+ return undefined;
785
+ }
786
+
787
+ function deriveAntigravitySessionId(context: Context): string {
788
+ const text = getFirstUserTextForAntigravitySession(context);
789
+ if (text && text.trim().length > 0) {
790
+ return deriveSignedDecimalFromHash(text);
791
+ }
792
+
793
+ return randomSignedDecimalSessionId();
794
+ }
795
+
796
+ function normalizeAntigravityTools(
797
+ tools: CloudCodeAssistRequest["request"]["tools"],
798
+ ): CloudCodeAssistRequest["request"]["tools"] {
799
+ return tools?.map(tool => ({
800
+ ...tool,
801
+ functionDeclarations: tool.functionDeclarations.map(declaration => {
802
+ if ("parameters" in declaration) {
803
+ return declaration;
804
+ }
805
+
806
+ const { parametersJsonSchema, ...rest } = declaration;
807
+ return {
808
+ ...rest,
809
+ parameters: normalizeSchemaForCCA(parametersJsonSchema),
810
+ };
811
+ }),
812
+ }));
813
+ }
814
+
815
+ export function buildRequest(
816
+ model: Model<"google-gemini-cli">,
817
+ context: Context,
818
+ projectId: string,
819
+ options: GoogleGeminiCliOptions = {},
820
+ isAntigravity = false,
821
+ ): CloudCodeAssistRequest {
822
+ const systemPrompts = normalizeSystemPrompts(context.systemPrompt);
823
+ const contents = convertMessages(model, context);
824
+ const generationConfig: CloudCodeAssistRequest["request"]["generationConfig"] = {};
825
+ if (options.temperature !== undefined) {
826
+ generationConfig.temperature = options.temperature;
827
+ }
828
+ if (options.maxTokens !== undefined) {
829
+ generationConfig.maxOutputTokens = options.maxTokens;
830
+ }
831
+ if (options.topP !== undefined) {
832
+ generationConfig.topP = options.topP;
833
+ }
834
+ if (options.topK !== undefined) {
835
+ generationConfig.topK = options.topK;
836
+ }
837
+ if (options.minP !== undefined) {
838
+ generationConfig.minP = options.minP;
839
+ }
840
+ if (options.presencePenalty !== undefined) {
841
+ generationConfig.presencePenalty = options.presencePenalty;
842
+ }
843
+ if (options.repetitionPenalty !== undefined) {
844
+ generationConfig.repetitionPenalty = options.repetitionPenalty;
845
+ }
846
+
847
+ // Thinking config
848
+ if (options.thinking?.enabled && model.reasoning) {
849
+ generationConfig.thinkingConfig = {
850
+ includeThoughts: true,
851
+ };
852
+ // Gemini 3 models use thinkingLevel, older models use thinkingBudget
853
+ if (options.thinking.level !== undefined) {
854
+ // Cast to any since our GoogleThinkingLevel mirrors Google's ThinkingLevel enum values
855
+ generationConfig.thinkingConfig.thinkingLevel = options.thinking.level as any;
856
+ } else if (options.thinking.budgetTokens !== undefined) {
857
+ generationConfig.thinkingConfig.thinkingBudget = options.thinking.budgetTokens;
858
+ }
859
+ }
860
+
861
+ const request: CloudCodeAssistRequest["request"] = {
862
+ contents,
863
+ };
864
+
865
+ if (isAntigravity) {
866
+ request.sessionId = deriveAntigravitySessionId(context);
867
+ }
868
+
869
+ // System instruction must be object with parts, not plain string.
870
+ // Evidence: Real Antigravity IDE sets role: "user" on systemInstruction
871
+ // (confirmed in request body dumps from network interception).
872
+ // Only applied for Antigravity path — standard gemini-cli omits role.
873
+ if (systemPrompts.length > 0) {
874
+ request.systemInstruction = {
875
+ ...(isAntigravity && { role: "user" }),
876
+ parts: systemPrompts.map(text => ({ text })),
877
+ };
878
+ }
879
+
880
+ if (Object.keys(generationConfig).length > 0) {
881
+ request.generationConfig = generationConfig;
882
+ }
883
+
884
+ const resolvedToolChoice = resolveToolChoice(model, options.toolChoice);
885
+ if (context.tools && context.tools.length > 0) {
886
+ const convertedTools = convertTools(context.tools, model);
887
+ request.tools = isAntigravity ? normalizeAntigravityTools(convertedTools) : convertedTools;
888
+ const resolved = resolvedToolChoice;
889
+ if (resolved.resolvedChoice) {
890
+ request.toolConfig = {
891
+ functionCallingConfig: {
892
+ mode: mapToolChoice(resolved.resolvedChoice as string),
893
+ },
894
+ };
895
+ }
896
+ }
897
+
898
+ if (isAntigravity && !isClaudeModel(model.id) && request.generationConfig?.maxOutputTokens !== undefined) {
899
+ delete request.generationConfig.maxOutputTokens;
900
+ if (Object.keys(request.generationConfig).length === 0) {
901
+ delete request.generationConfig;
902
+ }
903
+ }
904
+
905
+ // Claude Antigravity: use VALIDATED mode only when tools are present
906
+ // and the caller hasn't explicitly requested "none" tool choice.
907
+ //
908
+ // Evidence:
909
+ // - Real Antigravity IDE sends VALIDATED for Claude requests with tools
910
+ // (confirmed via network interception of official IDE traffic)
911
+ // - The original Vibrato code used resolvedToolChoice.resolvedLevel to gate
912
+ // VALIDATED, but the real IDE doesn't check tool choice resolution —
913
+ // it sends VALIDATED whenever tools exist and toolChoice != "none"
914
+ // - omp reference: packages/ai/src/providers/google-gemini-cli.ts
915
+ // `antigravityClaudeToolConfig` guard pattern
916
+ if (
917
+ isAntigravity &&
918
+ isClaudeModel(model.id) &&
919
+ context.tools &&
920
+ context.tools.length > 0 &&
921
+ options?.toolChoice !== "none"
922
+ ) {
923
+ request.toolConfig = {
924
+ functionCallingConfig: {
925
+ mode: "VALIDATED" as FunctionCallingConfigMode,
926
+ },
927
+ };
928
+ }
929
+
930
+ // Stateless system instruction injection: send on EVERY Antigravity request.
931
+ // This is safer than client-side session dedup because:
932
+ // - preambleConfig server-side persistence is unproven
933
+ // - A failed first request would poison the session if we skipped injection
934
+ // - Token cost is acceptable for Antigravity's long-context models
935
+ //
936
+ // Evidence:
937
+ // - Real Antigravity IDE sends the full system prompt on every request
938
+ // (confirmed via repeated request dumps — no client-side dedup observed)
939
+ // - The [ignore] wrapper was a Vibrato-original addition not present in the
940
+ // real IDE wire format. Removed for byte-faithful emulation.
941
+ // - preambleConfig: { mode: "SYSTEM_INSTRUCTION_MODE_REPLACE" } is the
942
+ // mechanism the real IDE uses to deliver system instructions. Without it,
943
+ // the server may append (not replace) the system prompt.
944
+ // - omp reference: `sessionSystemInstructionSent` Map was omp's approach;
945
+ // we chose stateless injection for simplicity and safety.
946
+ if (isAntigravity && shouldInjectAntigravitySystemInstruction(model.id)) {
947
+ const existingParts = request.systemInstruction?.parts ?? [];
948
+ request.systemInstruction = {
949
+ role: "user",
950
+ parts: [{ text: ANTIGRAVITY_SYSTEM_INSTRUCTION }, ...existingParts],
951
+ };
952
+ request.preambleConfig = {
953
+ mode: "SYSTEM_INSTRUCTION_MODE_REPLACE",
954
+ };
955
+ }
956
+
957
+ return {
958
+ project: projectId,
959
+ model: model.id,
960
+ request,
961
+ ...(isAntigravity
962
+ ? {
963
+ requestType: "agent",
964
+ userAgent: "antigravity",
965
+ requestId: `agent-${randomUUID()}`,
966
+ }
967
+ : {}),
968
+ };
969
+ }