@cortexkit/opencode-antigravity-auth 1.1.0 → 2.0.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 (371) hide show
  1. package/README.md +225 -569
  2. package/dist/cli.js +3790 -0
  3. package/dist/cli.js.map +7 -0
  4. package/dist/index.d.ts +1 -3
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +18767 -13829
  7. package/dist/index.js.map +4 -4
  8. package/dist/src/antigravity/oauth.d.ts +1 -1
  9. package/dist/src/antigravity/oauth.js +1 -1
  10. package/dist/src/cli.d.ts +21 -0
  11. package/dist/src/cli.d.ts.map +1 -0
  12. package/dist/src/cli.js +237 -0
  13. package/dist/src/cli.js.map +1 -0
  14. package/dist/src/constants.d.ts +1 -1
  15. package/dist/src/constants.js +1 -1
  16. package/dist/src/hooks/auto-update-checker/cache.d.ts.map +1 -1
  17. package/dist/src/hooks/auto-update-checker/cache.js +13 -13
  18. package/dist/src/hooks/auto-update-checker/cache.js.map +1 -1
  19. package/dist/src/hooks/auto-update-checker/checker.d.ts +1 -1
  20. package/dist/src/hooks/auto-update-checker/checker.d.ts.map +1 -1
  21. package/dist/src/hooks/auto-update-checker/checker.js +75 -51
  22. package/dist/src/hooks/auto-update-checker/checker.js.map +1 -1
  23. package/dist/src/hooks/auto-update-checker/constants.d.ts.map +1 -1
  24. package/dist/src/hooks/auto-update-checker/constants.js +12 -12
  25. package/dist/src/hooks/auto-update-checker/constants.js.map +1 -1
  26. package/dist/src/hooks/auto-update-checker/index.d.ts +6 -6
  27. package/dist/src/hooks/auto-update-checker/index.d.ts.map +1 -1
  28. package/dist/src/hooks/auto-update-checker/index.js +17 -17
  29. package/dist/src/hooks/auto-update-checker/index.js.map +1 -1
  30. package/dist/src/hooks/auto-update-checker/logging.js +2 -2
  31. package/dist/src/hooks/auto-update-checker/logging.js.map +1 -1
  32. package/dist/src/hooks/auto-update-checker/types.d.ts.map +1 -1
  33. package/dist/src/plugin/account-access.d.ts +99 -0
  34. package/dist/src/plugin/account-access.d.ts.map +1 -0
  35. package/dist/src/plugin/account-access.js +480 -0
  36. package/dist/src/plugin/account-access.js.map +1 -0
  37. package/dist/src/plugin/accounts.d.ts +7 -256
  38. package/dist/src/plugin/accounts.d.ts.map +1 -1
  39. package/dist/src/plugin/accounts.js +31 -1367
  40. package/dist/src/plugin/accounts.js.map +1 -1
  41. package/dist/src/plugin/agy-request-metadata.d.ts +1 -1
  42. package/dist/src/plugin/agy-request-metadata.js +1 -1
  43. package/dist/src/plugin/agy-transport.d.ts +1 -1
  44. package/dist/src/plugin/agy-transport.js +1 -1
  45. package/dist/src/plugin/auth-doctor.d.ts +6 -6
  46. package/dist/src/plugin/auth-doctor.d.ts.map +1 -1
  47. package/dist/src/plugin/auth-doctor.js +74 -66
  48. package/dist/src/plugin/auth-doctor.js.map +1 -1
  49. package/dist/src/plugin/auth-drift.d.ts +4 -4
  50. package/dist/src/plugin/auth-drift.d.ts.map +1 -1
  51. package/dist/src/plugin/auth-drift.js +15 -15
  52. package/dist/src/plugin/auth-drift.js.map +1 -1
  53. package/dist/src/plugin/auth-loader.d.ts +35 -0
  54. package/dist/src/plugin/auth-loader.d.ts.map +1 -0
  55. package/dist/src/plugin/auth-loader.js +144 -0
  56. package/dist/src/plugin/auth-loader.js.map +1 -0
  57. package/dist/src/plugin/auth.d.ts +1 -1
  58. package/dist/src/plugin/auth.js +1 -1
  59. package/dist/src/plugin/cache/index.d.ts +1 -1
  60. package/dist/src/plugin/cache/index.d.ts.map +1 -1
  61. package/dist/src/plugin/cache/index.js +1 -1
  62. package/dist/src/plugin/cache/index.js.map +1 -1
  63. package/dist/src/plugin/cache/signature-cache.d.ts +1 -1
  64. package/dist/src/plugin/cache/signature-cache.d.ts.map +1 -1
  65. package/dist/src/plugin/cache/signature-cache.js +23 -24
  66. package/dist/src/plugin/cache/signature-cache.js.map +1 -1
  67. package/dist/src/plugin/cache.d.ts +6 -5
  68. package/dist/src/plugin/cache.d.ts.map +1 -1
  69. package/dist/src/plugin/cache.js +21 -7
  70. package/dist/src/plugin/cache.js.map +1 -1
  71. package/dist/src/plugin/catalog.d.ts +23 -0
  72. package/dist/src/plugin/catalog.d.ts.map +1 -0
  73. package/dist/src/plugin/catalog.js +60 -0
  74. package/dist/src/plugin/catalog.js.map +1 -0
  75. package/dist/src/plugin/cli.d.ts +7 -7
  76. package/dist/src/plugin/cli.d.ts.map +1 -1
  77. package/dist/src/plugin/cli.js +62 -55
  78. package/dist/src/plugin/cli.js.map +1 -1
  79. package/dist/src/plugin/command-data.d.ts +276 -0
  80. package/dist/src/plugin/command-data.d.ts.map +1 -0
  81. package/dist/src/plugin/command-data.js +325 -0
  82. package/dist/src/plugin/command-data.js.map +1 -0
  83. package/dist/src/plugin/commands.d.ts +151 -0
  84. package/dist/src/plugin/commands.d.ts.map +1 -0
  85. package/dist/src/plugin/commands.js +639 -0
  86. package/dist/src/plugin/commands.js.map +1 -0
  87. package/dist/src/plugin/config/index.d.ts +2 -2
  88. package/dist/src/plugin/config/index.d.ts.map +1 -1
  89. package/dist/src/plugin/config/index.js +2 -2
  90. package/dist/src/plugin/config/index.js.map +1 -1
  91. package/dist/src/plugin/config/loader.d.ts +1 -1
  92. package/dist/src/plugin/config/loader.d.ts.map +1 -1
  93. package/dist/src/plugin/config/loader.js +18 -16
  94. package/dist/src/plugin/config/loader.js.map +1 -1
  95. package/dist/src/plugin/config/models.d.ts +2 -2
  96. package/dist/src/plugin/config/models.d.ts.map +1 -1
  97. package/dist/src/plugin/config/models.js +1 -1
  98. package/dist/src/plugin/config/models.js.map +1 -1
  99. package/dist/src/plugin/config/operator-settings-schema.d.ts +29 -0
  100. package/dist/src/plugin/config/operator-settings-schema.d.ts.map +1 -0
  101. package/dist/src/plugin/config/operator-settings-schema.js +28 -0
  102. package/dist/src/plugin/config/operator-settings-schema.js.map +1 -0
  103. package/dist/src/plugin/config/schema.d.ts +21 -2
  104. package/dist/src/plugin/config/schema.d.ts.map +1 -1
  105. package/dist/src/plugin/config/schema.js +85 -25
  106. package/dist/src/plugin/config/schema.js.map +1 -1
  107. package/dist/src/plugin/config/updater.d.ts.map +1 -1
  108. package/dist/src/plugin/config/updater.js +15 -15
  109. package/dist/src/plugin/config/updater.js.map +1 -1
  110. package/dist/src/plugin/config/writer.d.ts +34 -0
  111. package/dist/src/plugin/config/writer.d.ts.map +1 -0
  112. package/dist/src/plugin/config/writer.js +81 -0
  113. package/dist/src/plugin/config/writer.js.map +1 -0
  114. package/dist/src/plugin/core/streaming/index.d.ts +1 -1
  115. package/dist/src/plugin/core/streaming/index.d.ts.map +1 -1
  116. package/dist/src/plugin/core/streaming/index.js +1 -1
  117. package/dist/src/plugin/core/streaming/index.js.map +1 -1
  118. package/dist/src/plugin/core/streaming/transformer.d.ts.map +1 -1
  119. package/dist/src/plugin/core/streaming/transformer.js +85 -44
  120. package/dist/src/plugin/core/streaming/transformer.js.map +1 -1
  121. package/dist/src/plugin/core/streaming/types.d.ts.map +1 -1
  122. package/dist/src/plugin/debug.d.ts +3 -3
  123. package/dist/src/plugin/debug.d.ts.map +1 -1
  124. package/dist/src/plugin/debug.js +85 -47
  125. package/dist/src/plugin/debug.js.map +1 -1
  126. package/dist/src/plugin/dependencies.d.ts +129 -0
  127. package/dist/src/plugin/dependencies.d.ts.map +1 -0
  128. package/dist/src/plugin/dependencies.js +107 -0
  129. package/dist/src/plugin/dependencies.js.map +1 -0
  130. package/dist/src/plugin/errors.d.ts +27 -0
  131. package/dist/src/plugin/errors.d.ts.map +1 -1
  132. package/dist/src/plugin/errors.js +29 -3
  133. package/dist/src/plugin/errors.js.map +1 -1
  134. package/dist/src/plugin/event-handler.d.ts +53 -0
  135. package/dist/src/plugin/event-handler.d.ts.map +1 -0
  136. package/dist/src/plugin/event-handler.js +101 -0
  137. package/dist/src/plugin/event-handler.js.map +1 -0
  138. package/dist/src/plugin/fetch/retry-state.d.ts +61 -0
  139. package/dist/src/plugin/fetch/retry-state.d.ts.map +1 -0
  140. package/dist/src/plugin/fetch/retry-state.js +248 -0
  141. package/dist/src/plugin/fetch/retry-state.js.map +1 -0
  142. package/dist/src/plugin/fetch/warmup.d.ts +30 -0
  143. package/dist/src/plugin/fetch/warmup.d.ts.map +1 -0
  144. package/dist/src/plugin/fetch/warmup.js +76 -0
  145. package/dist/src/plugin/fetch/warmup.js.map +1 -0
  146. package/dist/src/plugin/fetch-interceptor.d.ts +59 -0
  147. package/dist/src/plugin/fetch-interceptor.d.ts.map +1 -0
  148. package/dist/src/plugin/fetch-interceptor.js +1387 -0
  149. package/dist/src/plugin/fetch-interceptor.js.map +1 -0
  150. package/dist/src/plugin/fetch-routing.d.ts +26 -0
  151. package/dist/src/plugin/fetch-routing.d.ts.map +1 -0
  152. package/dist/src/plugin/fetch-routing.js +99 -0
  153. package/dist/src/plugin/fetch-routing.js.map +1 -0
  154. package/dist/src/plugin/fingerprint.d.ts +1 -1
  155. package/dist/src/plugin/fingerprint.js +1 -1
  156. package/dist/src/plugin/gemini-dump.d.ts +5 -5
  157. package/dist/src/plugin/gemini-dump.d.ts.map +1 -1
  158. package/dist/src/plugin/gemini-dump.js +109 -55
  159. package/dist/src/plugin/gemini-dump.js.map +1 -1
  160. package/dist/src/plugin/google-search-tool.d.ts +9 -0
  161. package/dist/src/plugin/google-search-tool.d.ts.map +1 -0
  162. package/dist/src/plugin/google-search-tool.js +56 -0
  163. package/dist/src/plugin/google-search-tool.js.map +1 -0
  164. package/dist/src/plugin/image-saver.d.ts.map +1 -1
  165. package/dist/src/plugin/image-saver.js +16 -16
  166. package/dist/src/plugin/image-saver.js.map +1 -1
  167. package/dist/src/plugin/index.d.ts +23 -0
  168. package/dist/src/plugin/index.d.ts.map +1 -0
  169. package/dist/src/plugin/index.js +308 -0
  170. package/dist/src/plugin/index.js.map +1 -0
  171. package/dist/src/plugin/killswitch.d.ts +94 -0
  172. package/dist/src/plugin/killswitch.d.ts.map +1 -0
  173. package/dist/src/plugin/killswitch.js +194 -0
  174. package/dist/src/plugin/killswitch.js.map +1 -0
  175. package/dist/src/plugin/lifecycle.d.ts +40 -0
  176. package/dist/src/plugin/lifecycle.d.ts.map +1 -0
  177. package/dist/src/plugin/lifecycle.js +73 -0
  178. package/dist/src/plugin/lifecycle.js.map +1 -0
  179. package/dist/src/plugin/logger.d.ts +10 -1
  180. package/dist/src/plugin/logger.d.ts.map +1 -1
  181. package/dist/src/plugin/logger.js +38 -12
  182. package/dist/src/plugin/logger.js.map +1 -1
  183. package/dist/src/plugin/logging-utils.d.ts +35 -1
  184. package/dist/src/plugin/logging-utils.d.ts.map +1 -1
  185. package/dist/src/plugin/logging-utils.js +98 -15
  186. package/dist/src/plugin/logging-utils.js.map +1 -1
  187. package/dist/src/plugin/model-registry.d.ts +1 -1
  188. package/dist/src/plugin/model-registry.js +1 -1
  189. package/dist/src/plugin/oauth-login.d.ts +22 -0
  190. package/dist/src/plugin/oauth-login.d.ts.map +1 -0
  191. package/dist/src/plugin/oauth-login.js +37 -0
  192. package/dist/src/plugin/oauth-login.js.map +1 -0
  193. package/dist/src/plugin/oauth-methods.d.ts +42 -0
  194. package/dist/src/plugin/oauth-methods.d.ts.map +1 -0
  195. package/dist/src/plugin/oauth-methods.js +1284 -0
  196. package/dist/src/plugin/oauth-methods.js.map +1 -0
  197. package/dist/src/plugin/operator-settings.d.ts +40 -0
  198. package/dist/src/plugin/operator-settings.d.ts.map +1 -0
  199. package/dist/src/plugin/operator-settings.js +148 -0
  200. package/dist/src/plugin/operator-settings.js.map +1 -0
  201. package/dist/src/plugin/persist-account-pool.d.ts +37 -0
  202. package/dist/src/plugin/persist-account-pool.d.ts.map +1 -0
  203. package/dist/src/plugin/persist-account-pool.js +142 -0
  204. package/dist/src/plugin/persist-account-pool.js.map +1 -0
  205. package/dist/src/plugin/project.d.ts +1 -1
  206. package/dist/src/plugin/project.js +1 -1
  207. package/dist/src/plugin/prompt-context.d.ts.map +1 -1
  208. package/dist/src/plugin/prompt-context.js +11 -11
  209. package/dist/src/plugin/prompt-context.js.map +1 -1
  210. package/dist/src/plugin/quota.d.ts +97 -41
  211. package/dist/src/plugin/quota.d.ts.map +1 -1
  212. package/dist/src/plugin/quota.js +273 -285
  213. package/dist/src/plugin/quota.js.map +1 -1
  214. package/dist/src/plugin/recovery/constants.d.ts.map +1 -1
  215. package/dist/src/plugin/recovery/constants.js +24 -15
  216. package/dist/src/plugin/recovery/constants.js.map +1 -1
  217. package/dist/src/plugin/recovery/index.d.ts +3 -3
  218. package/dist/src/plugin/recovery/index.d.ts.map +1 -1
  219. package/dist/src/plugin/recovery/index.js +3 -3
  220. package/dist/src/plugin/recovery/index.js.map +1 -1
  221. package/dist/src/plugin/recovery/storage.d.ts +1 -1
  222. package/dist/src/plugin/recovery/storage.d.ts.map +1 -1
  223. package/dist/src/plugin/recovery/storage.js +31 -39
  224. package/dist/src/plugin/recovery/storage.js.map +1 -1
  225. package/dist/src/plugin/recovery/types.d.ts +12 -12
  226. package/dist/src/plugin/recovery/types.d.ts.map +1 -1
  227. package/dist/src/plugin/recovery.d.ts +3 -3
  228. package/dist/src/plugin/recovery.d.ts.map +1 -1
  229. package/dist/src/plugin/recovery.js +62 -58
  230. package/dist/src/plugin/recovery.js.map +1 -1
  231. package/dist/src/plugin/refresh-queue.d.ts +5 -2
  232. package/dist/src/plugin/refresh-queue.d.ts.map +1 -1
  233. package/dist/src/plugin/refresh-queue.js +37 -15
  234. package/dist/src/plugin/refresh-queue.js.map +1 -1
  235. package/dist/src/plugin/request-helpers.d.ts +1 -1
  236. package/dist/src/plugin/request-helpers.d.ts.map +1 -1
  237. package/dist/src/plugin/request-helpers.js +451 -352
  238. package/dist/src/plugin/request-helpers.js.map +1 -1
  239. package/dist/src/plugin/request.d.ts +7 -7
  240. package/dist/src/plugin/request.d.ts.map +1 -1
  241. package/dist/src/plugin/request.js +622 -384
  242. package/dist/src/plugin/request.js.map +1 -1
  243. package/dist/src/plugin/rotation.d.ts +1 -168
  244. package/dist/src/plugin/rotation.d.ts.map +1 -1
  245. package/dist/src/plugin/rotation.js +1 -327
  246. package/dist/src/plugin/rotation.js.map +1 -1
  247. package/dist/src/plugin/search.d.ts.map +1 -1
  248. package/dist/src/plugin/search.js +39 -35
  249. package/dist/src/plugin/search.js.map +1 -1
  250. package/dist/src/plugin/server.d.ts +1 -1
  251. package/dist/src/plugin/server.d.ts.map +1 -1
  252. package/dist/src/plugin/server.js +42 -37
  253. package/dist/src/plugin/server.js.map +1 -1
  254. package/dist/src/plugin/session-context.d.ts +2 -1
  255. package/dist/src/plugin/session-context.d.ts.map +1 -1
  256. package/dist/src/plugin/session-context.js +11 -7
  257. package/dist/src/plugin/session-context.js.map +1 -1
  258. package/dist/src/plugin/storage.d.ts +59 -120
  259. package/dist/src/plugin/storage.d.ts.map +1 -1
  260. package/dist/src/plugin/storage.js +140 -485
  261. package/dist/src/plugin/storage.js.map +1 -1
  262. package/dist/src/plugin/stores/signature-store.d.ts.map +1 -1
  263. package/dist/src/plugin/stores/signature-store.js.map +1 -1
  264. package/dist/src/plugin/thinking-recovery.d.ts.map +1 -1
  265. package/dist/src/plugin/thinking-recovery.js +35 -33
  266. package/dist/src/plugin/thinking-recovery.js.map +1 -1
  267. package/dist/src/plugin/token.d.ts +2 -2
  268. package/dist/src/plugin/token.d.ts.map +1 -1
  269. package/dist/src/plugin/token.js +30 -21
  270. package/dist/src/plugin/token.js.map +1 -1
  271. package/dist/src/plugin/transform/cross-model-sanitizer.d.ts +1 -1
  272. package/dist/src/plugin/transform/cross-model-sanitizer.js +1 -1
  273. package/dist/src/plugin/transform/index.d.ts +1 -1
  274. package/dist/src/plugin/transform/index.js +1 -1
  275. package/dist/src/plugin/transform/model-resolver.d.ts +1 -1
  276. package/dist/src/plugin/transform/model-resolver.js +1 -1
  277. package/dist/src/plugin/transform/types.d.ts +1 -1
  278. package/dist/src/plugin/transform/types.js +1 -1
  279. package/dist/src/plugin/types.d.ts +25 -69
  280. package/dist/src/plugin/types.d.ts.map +1 -1
  281. package/dist/src/plugin/ui/ansi.d.ts.map +1 -1
  282. package/dist/src/plugin/ui/ansi.js.map +1 -1
  283. package/dist/src/plugin/ui/auth-menu.d.ts +1 -1
  284. package/dist/src/plugin/ui/auth-menu.d.ts.map +1 -1
  285. package/dist/src/plugin/ui/auth-menu.js +82 -31
  286. package/dist/src/plugin/ui/auth-menu.js.map +1 -1
  287. package/dist/src/plugin/ui/confirm.d.ts.map +1 -1
  288. package/dist/src/plugin/ui/confirm.js.map +1 -1
  289. package/dist/src/plugin/ui/model-status.d.ts +3 -3
  290. package/dist/src/plugin/ui/model-status.d.ts.map +1 -1
  291. package/dist/src/plugin/ui/model-status.js +3 -3
  292. package/dist/src/plugin/ui/model-status.js.map +1 -1
  293. package/dist/src/plugin/ui/quota-status.d.ts +4 -4
  294. package/dist/src/plugin/ui/quota-status.d.ts.map +1 -1
  295. package/dist/src/plugin/ui/quota-status.js +51 -49
  296. package/dist/src/plugin/ui/quota-status.js.map +1 -1
  297. package/dist/src/plugin/ui/select.d.ts.map +1 -1
  298. package/dist/src/plugin/ui/select.js +22 -12
  299. package/dist/src/plugin/ui/select.js.map +1 -1
  300. package/dist/src/plugin/version.d.ts +1 -1
  301. package/dist/src/plugin/version.js +1 -1
  302. package/dist/src/rpc/notifications.d.ts +6 -0
  303. package/dist/src/rpc/notifications.d.ts.map +1 -0
  304. package/dist/src/rpc/notifications.js +46 -0
  305. package/dist/src/rpc/notifications.js.map +1 -0
  306. package/dist/src/rpc/port-file.d.ts +13 -0
  307. package/dist/src/rpc/port-file.d.ts.map +1 -0
  308. package/dist/src/rpc/port-file.js +109 -0
  309. package/dist/src/rpc/port-file.js.map +1 -0
  310. package/dist/src/rpc/protocol.d.ts +22 -0
  311. package/dist/src/rpc/protocol.d.ts.map +1 -0
  312. package/dist/src/rpc/protocol.js +1 -0
  313. package/dist/src/rpc/protocol.js.map +1 -0
  314. package/dist/src/rpc/rpc-client.d.ts +10 -0
  315. package/dist/src/rpc/rpc-client.d.ts.map +1 -0
  316. package/dist/src/rpc/rpc-client.js +58 -0
  317. package/dist/src/rpc/rpc-client.js.map +1 -0
  318. package/dist/src/rpc/rpc-dir.d.ts +4 -0
  319. package/dist/src/rpc/rpc-dir.d.ts.map +1 -0
  320. package/dist/src/rpc/rpc-dir.js +19 -0
  321. package/dist/src/rpc/rpc-dir.js.map +1 -0
  322. package/dist/src/rpc/rpc-server.d.ts +13 -0
  323. package/dist/src/rpc/rpc-server.d.ts.map +1 -0
  324. package/dist/src/rpc/rpc-server.js +231 -0
  325. package/dist/src/rpc/rpc-server.js.map +1 -0
  326. package/dist/src/sidebar-state.d.ts +240 -0
  327. package/dist/src/sidebar-state.d.ts.map +1 -0
  328. package/dist/src/sidebar-state.js +520 -0
  329. package/dist/src/sidebar-state.js.map +1 -0
  330. package/dist/src/tui/command-dialogs.d.ts +61 -0
  331. package/dist/src/tui/command-dialogs.d.ts.map +1 -0
  332. package/dist/src/tui/command-dialogs.js +497 -0
  333. package/dist/src/tui/command-dialogs.js.map +1 -0
  334. package/dist/src/tui/file-logger.d.ts +41 -0
  335. package/dist/src/tui/file-logger.d.ts.map +1 -0
  336. package/dist/src/tui/file-logger.js +114 -0
  337. package/dist/src/tui/file-logger.js.map +1 -0
  338. package/dist/src/tui-preferences.d.ts +40 -0
  339. package/dist/src/tui-preferences.d.ts.map +1 -0
  340. package/dist/src/tui-preferences.js +328 -0
  341. package/dist/src/tui-preferences.js.map +1 -0
  342. package/dist/src/tui.d.ts +68 -0
  343. package/dist/src/tui.d.ts.map +1 -0
  344. package/dist/src/tui.js +662 -0
  345. package/dist/src/tui.js.map +1 -0
  346. package/package.json +46 -22
  347. package/src/plugin/command-data.ts +651 -0
  348. package/src/rpc/port-file.ts +143 -0
  349. package/src/rpc/protocol.ts +31 -0
  350. package/src/rpc/rpc-client.ts +102 -0
  351. package/src/rpc/rpc-dir.ts +24 -0
  352. package/src/sidebar-state.ts +717 -0
  353. package/src/tui/command-dialogs.tsx +699 -0
  354. package/src/tui/entry.mjs +74 -0
  355. package/src/tui/file-logger.ts +145 -0
  356. package/src/tui-compiled/plugin/command-data.ts +651 -0
  357. package/src/tui-compiled/rpc/port-file.ts +143 -0
  358. package/src/tui-compiled/rpc/protocol.ts +31 -0
  359. package/src/tui-compiled/rpc/rpc-client.ts +102 -0
  360. package/src/tui-compiled/rpc/rpc-dir.ts +24 -0
  361. package/src/tui-compiled/sidebar-state.ts +717 -0
  362. package/src/tui-compiled/tui/command-dialogs.tsx +659 -0
  363. package/src/tui-compiled/tui/file-logger.ts +145 -0
  364. package/src/tui-compiled/tui-preferences.ts +416 -0
  365. package/src/tui-compiled/tui.tsx +1150 -0
  366. package/src/tui-preferences.ts +416 -0
  367. package/src/tui.tsx +1117 -0
  368. package/dist/src/plugin.d.ts +0 -48
  369. package/dist/src/plugin.d.ts.map +0 -1
  370. package/dist/src/plugin.js +0 -3311
  371. package/dist/src/plugin.js.map +0 -1
@@ -1,10 +1,9 @@
1
- import { getKeepThinking } from "./config";
2
- import { createLogger } from "./logger";
3
- import { cacheSignature } from "./cache";
4
- import { EMPTY_SCHEMA_PLACEHOLDER_NAME, EMPTY_SCHEMA_PLACEHOLDER_DESCRIPTION, SKIP_THOUGHT_SIGNATURE, } from "../constants";
5
- import { processImageData } from "./image-saver";
6
- const log = createLogger("request-helpers");
7
- const ANTIGRAVITY_PREVIEW_LINK = "https://goo.gle/enable-preview-features"; // TODO: Update to Antigravity link if available
1
+ import { EMPTY_SCHEMA_PLACEHOLDER_DESCRIPTION, EMPTY_SCHEMA_PLACEHOLDER_NAME, } from '../constants';
2
+ import { getKeepThinking } from './config';
3
+ import { processImageData } from './image-saver';
4
+ import { createLogger } from './logger';
5
+ const log = createLogger('request-helpers');
6
+ const ANTIGRAVITY_PREVIEW_LINK = 'https://goo.gle/enable-preview-features'; // TODO: Update to Antigravity link if available
8
7
  // ============================================================================
9
8
  // JSON SCHEMA CLEANING FOR ANTIGRAVITY API
10
9
  // Ported from CLIProxyAPI's CleanJSONSchemaForAntigravity (gemini_schema.go)
@@ -14,26 +13,41 @@ const ANTIGRAVITY_PREVIEW_LINK = "https://goo.gle/enable-preview-features"; // T
14
13
  * Claude/Gemini reject these in VALIDATED mode.
15
14
  */
16
15
  const UNSUPPORTED_CONSTRAINTS = [
17
- "minLength", "maxLength", "exclusiveMinimum", "exclusiveMaximum",
18
- "pattern", "minItems", "maxItems", "format",
19
- "default", "examples",
16
+ 'minLength',
17
+ 'maxLength',
18
+ 'exclusiveMinimum',
19
+ 'exclusiveMaximum',
20
+ 'pattern',
21
+ 'minItems',
22
+ 'maxItems',
23
+ 'format',
24
+ 'default',
25
+ 'examples',
20
26
  ];
21
27
  /**
22
28
  * Keywords that should be removed after hint extraction.
23
29
  */
24
30
  const UNSUPPORTED_KEYWORDS = [
25
31
  ...UNSUPPORTED_CONSTRAINTS,
26
- "$schema", "$defs", "definitions", "const", "$ref", "additionalProperties",
27
- "propertyNames", "title", "$id", "$comment",
32
+ '$schema',
33
+ '$defs',
34
+ 'definitions',
35
+ 'const',
36
+ '$ref',
37
+ 'additionalProperties',
38
+ 'propertyNames',
39
+ 'title',
40
+ '$id',
41
+ '$comment',
28
42
  ];
29
43
  /**
30
44
  * Appends a hint to a schema's description field.
31
45
  */
32
46
  function appendDescriptionHint(schema, hint) {
33
- if (!schema || typeof schema !== "object") {
47
+ if (!schema || typeof schema !== 'object') {
34
48
  return schema;
35
49
  }
36
- const existing = typeof schema.description === "string" ? schema.description : "";
50
+ const existing = typeof schema.description === 'string' ? schema.description : '';
37
51
  const newDescription = existing ? `${existing} (${hint})` : hint;
38
52
  return { ...schema, description: newDescription };
39
53
  }
@@ -42,20 +56,20 @@ function appendDescriptionHint(schema, hint) {
42
56
  * $ref: "#/$defs/Foo" → { type: "object", description: "See: Foo" }
43
57
  */
44
58
  function convertRefsToHints(schema) {
45
- if (!schema || typeof schema !== "object") {
59
+ if (!schema || typeof schema !== 'object') {
46
60
  return schema;
47
61
  }
48
62
  if (Array.isArray(schema)) {
49
- return schema.map(item => convertRefsToHints(item));
63
+ return schema.map((item) => convertRefsToHints(item));
50
64
  }
51
65
  // If this object has $ref, replace it with a hint
52
- if (typeof schema.$ref === "string") {
66
+ if (typeof schema.$ref === 'string') {
53
67
  const refVal = schema.$ref;
54
- const defName = refVal.includes("/") ? refVal.split("/").pop() : refVal;
68
+ const defName = refVal.includes('/') ? refVal.split('/').pop() : refVal;
55
69
  const hint = `See: ${defName}`;
56
- const existingDesc = typeof schema.description === "string" ? schema.description : "";
70
+ const existingDesc = typeof schema.description === 'string' ? schema.description : '';
57
71
  const newDescription = existingDesc ? `${existingDesc} (${hint})` : hint;
58
- return { type: "object", description: newDescription };
72
+ return { type: 'object', description: newDescription };
59
73
  }
60
74
  // Recursively process all properties
61
75
  const result = {};
@@ -69,15 +83,15 @@ function convertRefsToHints(schema) {
69
83
  * { const: "foo" } → { enum: ["foo"] }
70
84
  */
71
85
  function convertConstToEnum(schema) {
72
- if (!schema || typeof schema !== "object") {
86
+ if (!schema || typeof schema !== 'object') {
73
87
  return schema;
74
88
  }
75
89
  if (Array.isArray(schema)) {
76
- return schema.map(item => convertConstToEnum(item));
90
+ return schema.map((item) => convertConstToEnum(item));
77
91
  }
78
92
  const result = {};
79
93
  for (const [key, value] of Object.entries(schema)) {
80
- if (key === "const" && !schema.enum) {
94
+ if (key === 'const' && !schema.enum) {
81
95
  result.enum = [value];
82
96
  }
83
97
  else {
@@ -91,21 +105,23 @@ function convertConstToEnum(schema) {
91
105
  * { enum: ["a", "b", "c"] } → adds "(Allowed: a, b, c)" to description
92
106
  */
93
107
  function addEnumHints(schema) {
94
- if (!schema || typeof schema !== "object") {
108
+ if (!schema || typeof schema !== 'object') {
95
109
  return schema;
96
110
  }
97
111
  if (Array.isArray(schema)) {
98
- return schema.map(item => addEnumHints(item));
112
+ return schema.map((item) => addEnumHints(item));
99
113
  }
100
114
  let result = { ...schema };
101
115
  // Add enum hint if enum has 2-10 items
102
- if (Array.isArray(result.enum) && result.enum.length > 1 && result.enum.length <= 10) {
103
- const vals = result.enum.map((v) => String(v)).join(", ");
116
+ if (Array.isArray(result.enum) &&
117
+ result.enum.length > 1 &&
118
+ result.enum.length <= 10) {
119
+ const vals = result.enum.map((v) => String(v)).join(', ');
104
120
  result = appendDescriptionHint(result, `Allowed: ${vals}`);
105
121
  }
106
122
  // Recursively process nested objects
107
123
  for (const [key, value] of Object.entries(result)) {
108
- if (key !== "enum" && typeof value === "object" && value !== null) {
124
+ if (key !== 'enum' && typeof value === 'object' && value !== null) {
109
125
  result[key] = addEnumHints(value);
110
126
  }
111
127
  }
@@ -116,19 +132,21 @@ function addEnumHints(schema) {
116
132
  * { additionalProperties: false } → adds "(No extra properties allowed)" to description
117
133
  */
118
134
  function addAdditionalPropertiesHints(schema) {
119
- if (!schema || typeof schema !== "object") {
135
+ if (!schema || typeof schema !== 'object') {
120
136
  return schema;
121
137
  }
122
138
  if (Array.isArray(schema)) {
123
- return schema.map(item => addAdditionalPropertiesHints(item));
139
+ return schema.map((item) => addAdditionalPropertiesHints(item));
124
140
  }
125
141
  let result = { ...schema };
126
142
  if (result.additionalProperties === false) {
127
- result = appendDescriptionHint(result, "No extra properties allowed");
143
+ result = appendDescriptionHint(result, 'No extra properties allowed');
128
144
  }
129
145
  // Recursively process nested objects
130
146
  for (const [key, value] of Object.entries(result)) {
131
- if (key !== "additionalProperties" && typeof value === "object" && value !== null) {
147
+ if (key !== 'additionalProperties' &&
148
+ typeof value === 'object' &&
149
+ value !== null) {
132
150
  result[key] = addAdditionalPropertiesHints(value);
133
151
  }
134
152
  }
@@ -139,22 +157,23 @@ function addAdditionalPropertiesHints(schema) {
139
157
  * { minLength: 1, maxLength: 100 } → adds "(minLength: 1) (maxLength: 100)" to description
140
158
  */
141
159
  function moveConstraintsToDescription(schema) {
142
- if (!schema || typeof schema !== "object") {
160
+ if (!schema || typeof schema !== 'object') {
143
161
  return schema;
144
162
  }
145
163
  if (Array.isArray(schema)) {
146
- return schema.map(item => moveConstraintsToDescription(item));
164
+ return schema.map((item) => moveConstraintsToDescription(item));
147
165
  }
148
166
  let result = { ...schema };
149
167
  // Move constraint values to description
150
168
  for (const constraint of UNSUPPORTED_CONSTRAINTS) {
151
- if (result[constraint] !== undefined && typeof result[constraint] !== "object") {
169
+ if (result[constraint] !== undefined &&
170
+ typeof result[constraint] !== 'object') {
152
171
  result = appendDescriptionHint(result, `${constraint}: ${result[constraint]}`);
153
172
  }
154
173
  }
155
174
  // Recursively process nested objects
156
175
  for (const [key, value] of Object.entries(result)) {
157
- if (typeof value === "object" && value !== null) {
176
+ if (typeof value === 'object' && value !== null) {
158
177
  result[key] = moveConstraintsToDescription(value);
159
178
  }
160
179
  }
@@ -166,22 +185,22 @@ function moveConstraintsToDescription(schema) {
166
185
  * → { properties: { a: ..., b: ... } }
167
186
  */
168
187
  function mergeAllOf(schema) {
169
- if (!schema || typeof schema !== "object") {
188
+ if (!schema || typeof schema !== 'object') {
170
189
  return schema;
171
190
  }
172
191
  if (Array.isArray(schema)) {
173
- return schema.map(item => mergeAllOf(item));
192
+ return schema.map((item) => mergeAllOf(item));
174
193
  }
175
- let result = { ...schema };
194
+ const result = { ...schema };
176
195
  // If this object has allOf, merge its contents
177
196
  if (Array.isArray(result.allOf)) {
178
197
  const merged = {};
179
198
  const mergedRequired = [];
180
199
  for (const item of result.allOf) {
181
- if (!item || typeof item !== "object")
200
+ if (!item || typeof item !== 'object')
182
201
  continue;
183
202
  // Merge properties
184
- if (item.properties && typeof item.properties === "object") {
203
+ if (item.properties && typeof item.properties === 'object') {
185
204
  merged.properties = { ...merged.properties, ...item.properties };
186
205
  }
187
206
  // Merge required arrays
@@ -194,7 +213,9 @@ function mergeAllOf(schema) {
194
213
  }
195
214
  // Copy other fields from allOf items
196
215
  for (const [key, value] of Object.entries(item)) {
197
- if (key !== "properties" && key !== "required" && merged[key] === undefined) {
216
+ if (key !== 'properties' &&
217
+ key !== 'required' &&
218
+ merged[key] === undefined) {
198
219
  merged[key] = value;
199
220
  }
200
221
  }
@@ -204,12 +225,16 @@ function mergeAllOf(schema) {
204
225
  result.properties = { ...result.properties, ...merged.properties };
205
226
  }
206
227
  if (mergedRequired.length > 0) {
207
- const existingRequired = Array.isArray(result.required) ? result.required : [];
228
+ const existingRequired = Array.isArray(result.required)
229
+ ? result.required
230
+ : [];
208
231
  result.required = Array.from(new Set([...existingRequired, ...mergedRequired]));
209
232
  }
210
233
  // Copy other merged fields
211
234
  for (const [key, value] of Object.entries(merged)) {
212
- if (key !== "properties" && key !== "required" && result[key] === undefined) {
235
+ if (key !== 'properties' &&
236
+ key !== 'required' &&
237
+ result[key] === undefined) {
213
238
  result[key] = value;
214
239
  }
215
240
  }
@@ -217,7 +242,7 @@ function mergeAllOf(schema) {
217
242
  }
218
243
  // Recursively process nested objects
219
244
  for (const [key, value] of Object.entries(result)) {
220
- if (typeof value === "object" && value !== null) {
245
+ if (typeof value === 'object' && value !== null) {
221
246
  result[key] = mergeAllOf(value);
222
247
  }
223
248
  }
@@ -228,24 +253,24 @@ function mergeAllOf(schema) {
228
253
  * Higher score = more preferred.
229
254
  */
230
255
  function scoreSchemaOption(schema) {
231
- if (!schema || typeof schema !== "object") {
232
- return { score: 0, typeName: "unknown" };
256
+ if (!schema || typeof schema !== 'object') {
257
+ return { score: 0, typeName: 'unknown' };
233
258
  }
234
259
  const type = schema.type;
235
260
  // Object or has properties = highest priority
236
- if (type === "object" || schema.properties) {
237
- return { score: 3, typeName: "object" };
261
+ if (type === 'object' || schema.properties) {
262
+ return { score: 3, typeName: 'object' };
238
263
  }
239
264
  // Array or has items = second priority
240
- if (type === "array" || schema.items) {
241
- return { score: 2, typeName: "array" };
265
+ if (type === 'array' || schema.items) {
266
+ return { score: 2, typeName: 'array' };
242
267
  }
243
268
  // Any other non-null type
244
- if (type && type !== "null") {
269
+ if (type && type !== 'null') {
245
270
  return { score: 1, typeName: type };
246
271
  }
247
272
  // Null or no type
248
- return { score: 0, typeName: type || "null" };
273
+ return { score: 0, typeName: type || 'null' };
249
274
  }
250
275
  /**
251
276
  * Checks if an anyOf/oneOf array represents enum choices.
@@ -262,7 +287,7 @@ function tryMergeEnumFromUnion(options) {
262
287
  }
263
288
  const enumValues = [];
264
289
  for (const option of options) {
265
- if (!option || typeof option !== "object") {
290
+ if (!option || typeof option !== 'object') {
266
291
  return null;
267
292
  }
268
293
  // Check for const value
@@ -283,7 +308,11 @@ function tryMergeEnumFromUnion(options) {
283
308
  continue;
284
309
  }
285
310
  // If option has complex structure (properties, items, etc.), it's not a simple enum
286
- if (option.properties || option.items || option.anyOf || option.oneOf || option.allOf) {
311
+ if (option.properties ||
312
+ option.items ||
313
+ option.anyOf ||
314
+ option.oneOf ||
315
+ option.allOf) {
287
316
  return null;
288
317
  }
289
318
  // If option has only type (no const/enum), it's not an enum pattern
@@ -304,18 +333,18 @@ function tryMergeEnumFromUnion(options) {
304
333
  * → { type: "string", enum: ["a", "b"] }
305
334
  */
306
335
  function flattenAnyOfOneOf(schema) {
307
- if (!schema || typeof schema !== "object") {
336
+ if (!schema || typeof schema !== 'object') {
308
337
  return schema;
309
338
  }
310
339
  if (Array.isArray(schema)) {
311
- return schema.map(item => flattenAnyOfOneOf(item));
340
+ return schema.map((item) => flattenAnyOfOneOf(item));
312
341
  }
313
342
  let result = { ...schema };
314
343
  // Process anyOf or oneOf
315
- for (const unionKey of ["anyOf", "oneOf"]) {
344
+ for (const unionKey of ['anyOf', 'oneOf']) {
316
345
  if (Array.isArray(result[unionKey]) && result[unionKey].length > 0) {
317
346
  const options = result[unionKey];
318
- const parentDesc = typeof result.description === "string" ? result.description : "";
347
+ const parentDesc = typeof result.description === 'string' ? result.description : '';
319
348
  // First, check if this is an enum pattern (anyOf with const/enum values)
320
349
  // This is crucial for tools like WebFetch where format: anyOf[{const:"text"},{const:"markdown"},{const:"html"}]
321
350
  const mergedEnum = tryMergeEnumFromUnion(options);
@@ -324,7 +353,7 @@ function flattenAnyOfOneOf(schema) {
324
353
  const { [unionKey]: _, ...rest } = result;
325
354
  result = {
326
355
  ...rest,
327
- type: "string",
356
+ type: 'string',
328
357
  enum: mergedEnum,
329
358
  };
330
359
  // Preserve parent description
@@ -349,12 +378,15 @@ function flattenAnyOfOneOf(schema) {
349
378
  }
350
379
  }
351
380
  // Select the best option and flatten it recursively
352
- let selected = flattenAnyOfOneOf(options[bestIdx]) || { type: "string" };
381
+ let selected = flattenAnyOfOneOf(options[bestIdx]) || { type: 'string' };
353
382
  // Preserve parent description
354
383
  if (parentDesc) {
355
- const childDesc = typeof selected.description === "string" ? selected.description : "";
384
+ const childDesc = typeof selected.description === 'string' ? selected.description : '';
356
385
  if (childDesc && childDesc !== parentDesc) {
357
- selected = { ...selected, description: `${parentDesc} (${childDesc})` };
386
+ selected = {
387
+ ...selected,
388
+ description: `${parentDesc} (${childDesc})`,
389
+ };
358
390
  }
359
391
  else if (!childDesc) {
360
392
  selected = { ...selected, description: parentDesc };
@@ -362,7 +394,7 @@ function flattenAnyOfOneOf(schema) {
362
394
  }
363
395
  if (allTypes.length > 1) {
364
396
  const uniqueTypes = Array.from(new Set(allTypes));
365
- const hint = `Accepts: ${uniqueTypes.join(" | ")}`;
397
+ const hint = `Accepts: ${uniqueTypes.join(' | ')}`;
366
398
  selected = appendDescriptionHint(selected, hint);
367
399
  }
368
400
  // Replace result with selected schema, preserving other fields
@@ -372,7 +404,7 @@ function flattenAnyOfOneOf(schema) {
372
404
  }
373
405
  // Recursively process nested objects
374
406
  for (const [key, value] of Object.entries(result)) {
375
- if (typeof value === "object" && value !== null) {
407
+ if (typeof value === 'object' && value !== null) {
376
408
  result[key] = flattenAnyOfOneOf(value);
377
409
  }
378
410
  }
@@ -383,43 +415,46 @@ function flattenAnyOfOneOf(schema) {
383
415
  * { type: ["string", "null"] } → { type: "string", description: "(nullable)" }
384
416
  */
385
417
  function flattenTypeArrays(schema, nullableFields, currentPath) {
386
- if (!schema || typeof schema !== "object") {
418
+ if (!schema || typeof schema !== 'object') {
387
419
  return schema;
388
420
  }
389
421
  if (Array.isArray(schema)) {
390
- return schema.map((item, idx) => flattenTypeArrays(item, nullableFields, `${currentPath || ""}[${idx}]`));
422
+ return schema.map((item, idx) => flattenTypeArrays(item, nullableFields, `${currentPath || ''}[${idx}]`));
391
423
  }
392
424
  let result = { ...schema };
393
425
  const localNullableFields = nullableFields || new Map();
394
426
  // Handle type array
395
427
  if (Array.isArray(result.type)) {
396
428
  const types = result.type;
397
- const hasNull = types.includes("null");
398
- const nonNullTypes = types.filter(t => t !== "null" && t);
429
+ const hasNull = types.includes('null');
430
+ const nonNullTypes = types.filter((t) => t !== 'null' && t);
399
431
  // Select first non-null type, or "string" as fallback
400
- const firstType = nonNullTypes.length > 0 ? nonNullTypes[0] : "string";
432
+ const firstType = nonNullTypes.length > 0 ? nonNullTypes[0] : 'string';
401
433
  result.type = firstType;
402
434
  // Add hint for multiple types
403
435
  if (nonNullTypes.length > 1) {
404
- result = appendDescriptionHint(result, `Accepts: ${nonNullTypes.join(" | ")}`);
436
+ result = appendDescriptionHint(result, `Accepts: ${nonNullTypes.join(' | ')}`);
405
437
  }
406
438
  // Add nullable hint
407
439
  if (hasNull) {
408
- result = appendDescriptionHint(result, "nullable");
440
+ result = appendDescriptionHint(result, 'nullable');
409
441
  }
410
442
  }
411
443
  // Recursively process properties
412
- if (result.properties && typeof result.properties === "object") {
444
+ if (result.properties && typeof result.properties === 'object') {
413
445
  const newProps = {};
414
446
  for (const [propKey, propValue] of Object.entries(result.properties)) {
415
- const propPath = currentPath ? `${currentPath}.properties.${propKey}` : `properties.${propKey}`;
447
+ const propPath = currentPath
448
+ ? `${currentPath}.properties.${propKey}`
449
+ : `properties.${propKey}`;
416
450
  const processed = flattenTypeArrays(propValue, localNullableFields, propPath);
417
451
  newProps[propKey] = processed;
418
452
  // Track nullable fields for required array cleanup
419
- if (processed && typeof processed === "object" &&
420
- typeof processed.description === "string" &&
421
- processed.description.includes("nullable")) {
422
- const objectPath = currentPath || "";
453
+ if (processed &&
454
+ typeof processed === 'object' &&
455
+ typeof processed.description === 'string' &&
456
+ processed.description.includes('nullable')) {
457
+ const objectPath = currentPath || '';
423
458
  const existing = localNullableFields.get(objectPath) || [];
424
459
  existing.push(propKey);
425
460
  localNullableFields.set(objectPath, existing);
@@ -430,7 +465,7 @@ function flattenTypeArrays(schema, nullableFields, currentPath) {
430
465
  // Remove nullable fields from required array
431
466
  if (Array.isArray(result.required) && !nullableFields) {
432
467
  // Only at root level, filter out nullable fields
433
- const nullableAtRoot = localNullableFields.get("") || [];
468
+ const nullableAtRoot = localNullableFields.get('') || [];
434
469
  if (nullableAtRoot.length > 0) {
435
470
  result.required = result.required.filter((r) => !nullableAtRoot.includes(r));
436
471
  if (result.required.length === 0) {
@@ -440,8 +475,8 @@ function flattenTypeArrays(schema, nullableFields, currentPath) {
440
475
  }
441
476
  // Recursively process other nested objects
442
477
  for (const [key, value] of Object.entries(result)) {
443
- if (key !== "properties" && typeof value === "object" && value !== null) {
444
- result[key] = flattenTypeArrays(value, localNullableFields, `${currentPath || ""}.${key}`);
478
+ if (key !== 'properties' && typeof value === 'object' && value !== null) {
479
+ result[key] = flattenTypeArrays(value, localNullableFields, `${currentPath || ''}.${key}`);
445
480
  }
446
481
  }
447
482
  return result;
@@ -451,19 +486,20 @@ function flattenTypeArrays(schema, nullableFields, currentPath) {
451
486
  * @param insideProperties - When true, keys are property NAMES (preserve); when false, keys are JSON Schema keywords (filter).
452
487
  */
453
488
  function removeUnsupportedKeywords(schema, insideProperties = false) {
454
- if (!schema || typeof schema !== "object") {
489
+ if (!schema || typeof schema !== 'object') {
455
490
  return schema;
456
491
  }
457
492
  if (Array.isArray(schema)) {
458
- return schema.map(item => removeUnsupportedKeywords(item, false));
493
+ return schema.map((item) => removeUnsupportedKeywords(item, false));
459
494
  }
460
495
  const result = {};
461
496
  for (const [key, value] of Object.entries(schema)) {
462
- if (!insideProperties && UNSUPPORTED_KEYWORDS.includes(key)) {
497
+ if (!insideProperties &&
498
+ UNSUPPORTED_KEYWORDS.includes(key)) {
463
499
  continue;
464
500
  }
465
- if (typeof value === "object" && value !== null) {
466
- if (key === "properties") {
501
+ if (typeof value === 'object' && value !== null) {
502
+ if (key === 'properties') {
467
503
  const propertiesResult = {};
468
504
  for (const [propName, propSchema] of Object.entries(value)) {
469
505
  propertiesResult[propName] = removeUnsupportedKeywords(propSchema, false);
@@ -484,16 +520,18 @@ function removeUnsupportedKeywords(schema, insideProperties = false) {
484
520
  * Phase 3b: Cleans up required fields - removes entries that don't exist in properties.
485
521
  */
486
522
  function cleanupRequiredFields(schema) {
487
- if (!schema || typeof schema !== "object") {
523
+ if (!schema || typeof schema !== 'object') {
488
524
  return schema;
489
525
  }
490
526
  if (Array.isArray(schema)) {
491
- return schema.map(item => cleanupRequiredFields(item));
527
+ return schema.map((item) => cleanupRequiredFields(item));
492
528
  }
493
- let result = { ...schema };
529
+ const result = { ...schema };
494
530
  // Clean up required array if properties exist
495
- if (Array.isArray(result.required) && result.properties && typeof result.properties === "object") {
496
- const validRequired = result.required.filter((req) => Object.prototype.hasOwnProperty.call(result.properties, req));
531
+ if (Array.isArray(result.required) &&
532
+ result.properties &&
533
+ typeof result.properties === 'object') {
534
+ const validRequired = result.required.filter((req) => Object.hasOwn(result.properties, req));
497
535
  if (validRequired.length === 0) {
498
536
  delete result.required;
499
537
  }
@@ -503,7 +541,7 @@ function cleanupRequiredFields(schema) {
503
541
  }
504
542
  // Recursively process nested objects
505
543
  for (const [key, value] of Object.entries(result)) {
506
- if (typeof value === "object" && value !== null) {
544
+ if (typeof value === 'object' && value !== null) {
507
545
  result[key] = cleanupRequiredFields(value);
508
546
  }
509
547
  }
@@ -514,23 +552,23 @@ function cleanupRequiredFields(schema) {
514
552
  * Claude VALIDATED mode requires at least one property.
515
553
  */
516
554
  function addEmptySchemaPlaceholder(schema) {
517
- if (!schema || typeof schema !== "object") {
555
+ if (!schema || typeof schema !== 'object') {
518
556
  return schema;
519
557
  }
520
558
  if (Array.isArray(schema)) {
521
- return schema.map(item => addEmptySchemaPlaceholder(item));
559
+ return schema.map((item) => addEmptySchemaPlaceholder(item));
522
560
  }
523
- let result = { ...schema };
561
+ const result = { ...schema };
524
562
  // Check if this is an empty object schema
525
- const isObjectType = result.type === "object";
563
+ const isObjectType = result.type === 'object';
526
564
  if (isObjectType) {
527
565
  const hasProperties = result.properties &&
528
- typeof result.properties === "object" &&
566
+ typeof result.properties === 'object' &&
529
567
  Object.keys(result.properties).length > 0;
530
568
  if (!hasProperties) {
531
569
  result.properties = {
532
570
  [EMPTY_SCHEMA_PLACEHOLDER_NAME]: {
533
- type: "boolean",
571
+ type: 'boolean',
534
572
  description: EMPTY_SCHEMA_PLACEHOLDER_DESCRIPTION,
535
573
  },
536
574
  };
@@ -539,7 +577,7 @@ function addEmptySchemaPlaceholder(schema) {
539
577
  }
540
578
  // Recursively process nested objects
541
579
  for (const [key, value] of Object.entries(result)) {
542
- if (typeof value === "object" && value !== null) {
580
+ if (typeof value === 'object' && value !== null) {
543
581
  result[key] = addEmptySchemaPlaceholder(value);
544
582
  }
545
583
  }
@@ -552,7 +590,7 @@ function addEmptySchemaPlaceholder(schema) {
552
590
  * Ported from CLIProxyAPI's CleanJSONSchemaForAntigravity (gemini_schema.go)
553
591
  */
554
592
  export function cleanJSONSchemaForAntigravity(schema) {
555
- if (!schema || typeof schema !== "object") {
593
+ if (!schema || typeof schema !== 'object') {
556
594
  return schema;
557
595
  }
558
596
  let result = schema;
@@ -584,33 +622,37 @@ export const DEFAULT_THINKING_BUDGET = 16000;
584
622
  */
585
623
  export function isThinkingCapableModel(modelName) {
586
624
  const lowerModel = modelName.toLowerCase();
587
- return lowerModel.includes("thinking")
588
- || lowerModel.includes("gemini-3")
589
- || lowerModel.includes("opus");
625
+ return (lowerModel.includes('thinking') ||
626
+ lowerModel.includes('gemini-3') ||
627
+ lowerModel.includes('opus'));
590
628
  }
591
629
  /**
592
630
  * Extracts thinking configuration from various possible request locations.
593
631
  * Supports both Gemini-style thinkingConfig and Anthropic-style thinking options.
594
632
  */
595
633
  export function extractThinkingConfig(requestPayload, rawGenerationConfig, extraBody) {
596
- const thinkingConfig = rawGenerationConfig?.thinkingConfig
597
- ?? extraBody?.thinkingConfig
598
- ?? requestPayload.thinkingConfig;
599
- if (thinkingConfig && typeof thinkingConfig === "object") {
634
+ const thinkingConfig = rawGenerationConfig?.thinkingConfig ??
635
+ extraBody?.thinkingConfig ??
636
+ requestPayload.thinkingConfig;
637
+ if (thinkingConfig && typeof thinkingConfig === 'object') {
600
638
  const config = thinkingConfig;
601
639
  return {
602
640
  includeThoughts: Boolean(config.includeThoughts),
603
- thinkingBudget: typeof config.thinkingBudget === "number" ? config.thinkingBudget : DEFAULT_THINKING_BUDGET,
641
+ thinkingBudget: typeof config.thinkingBudget === 'number'
642
+ ? config.thinkingBudget
643
+ : DEFAULT_THINKING_BUDGET,
604
644
  };
605
645
  }
606
646
  // Convert Anthropic-style "thinking" option: { type: "enabled", budgetTokens: N }
607
647
  const anthropicThinking = extraBody?.thinking ?? requestPayload.thinking;
608
- if (anthropicThinking && typeof anthropicThinking === "object") {
648
+ if (anthropicThinking && typeof anthropicThinking === 'object') {
609
649
  const thinking = anthropicThinking;
610
- if (thinking.type === "enabled" || thinking.budgetTokens) {
650
+ if (thinking.type === 'enabled' || thinking.budgetTokens) {
611
651
  return {
612
652
  includeThoughts: true,
613
- thinkingBudget: typeof thinking.budgetTokens === "number" ? thinking.budgetTokens : DEFAULT_THINKING_BUDGET,
653
+ thinkingBudget: typeof thinking.budgetTokens === 'number'
654
+ ? thinking.budgetTokens
655
+ : DEFAULT_THINKING_BUDGET,
614
656
  };
615
657
  }
616
658
  }
@@ -632,42 +674,54 @@ export function extractThinkingConfig(requestPayload, rawGenerationConfig, extra
632
674
  export function extractVariantThinkingConfig(providerOptions, generationConfig) {
633
675
  const result = {};
634
676
  // Primary path: extract from providerOptions.google
635
- const google = (providerOptions?.google);
677
+ const google = providerOptions?.google;
636
678
  if (google) {
637
679
  // Gemini 3 native format: { google: { thinkingLevel: "high", includeThoughts: true } }
638
680
  // thinkingLevel takes priority over thinkingBudget - they are mutually exclusive
639
- if (typeof google.thinkingLevel === "string") {
681
+ if (typeof google.thinkingLevel === 'string') {
640
682
  result.thinkingLevel = google.thinkingLevel;
641
- result.includeThoughts = typeof google.includeThoughts === "boolean" ? google.includeThoughts : undefined;
683
+ result.includeThoughts =
684
+ typeof google.includeThoughts === 'boolean'
685
+ ? google.includeThoughts
686
+ : undefined;
642
687
  }
643
- else if (google.thinkingConfig && typeof google.thinkingConfig === "object") {
688
+ else if (google.thinkingConfig &&
689
+ typeof google.thinkingConfig === 'object') {
644
690
  // Budget-based format (Claude/Gemini 2.5): { google: { thinkingConfig: { thinkingBudget } } }
645
691
  // Only used when thinkingLevel is not present
646
692
  const tc = google.thinkingConfig;
647
- if (typeof tc.thinkingBudget === "number") {
693
+ if (typeof tc.thinkingBudget === 'number') {
648
694
  result.thinkingBudget = tc.thinkingBudget;
649
695
  }
650
696
  }
651
697
  // Extract Google Search config
652
- if (google.googleSearch && typeof google.googleSearch === "object") {
698
+ if (google.googleSearch && typeof google.googleSearch === 'object') {
653
699
  const search = google.googleSearch;
654
700
  result.googleSearch = {
655
- mode: search.mode === 'auto' || search.mode === 'off' ? search.mode : undefined,
701
+ mode: search.mode === 'auto' || search.mode === 'off'
702
+ ? search.mode
703
+ : undefined,
656
704
  threshold: typeof search.threshold === 'number' ? search.threshold : undefined,
657
705
  };
658
706
  }
659
707
  }
660
708
  // Fallback: OpenCode may pass thinking config in generationConfig
661
709
  // instead of providerOptions (common when using model variants)
662
- if (result.thinkingBudget === undefined && !result.thinkingLevel && generationConfig) {
663
- if (generationConfig.thinkingConfig && typeof generationConfig.thinkingConfig === "object") {
710
+ if (result.thinkingBudget === undefined &&
711
+ !result.thinkingLevel &&
712
+ generationConfig) {
713
+ if (generationConfig.thinkingConfig &&
714
+ typeof generationConfig.thinkingConfig === 'object') {
664
715
  const tc = generationConfig.thinkingConfig;
665
- if (typeof tc.thinkingLevel === "string") {
716
+ if (typeof tc.thinkingLevel === 'string') {
666
717
  // Gemini 3 native format sent via generationConfig
667
718
  result.thinkingLevel = tc.thinkingLevel;
668
- result.includeThoughts = typeof tc.includeThoughts === "boolean" ? tc.includeThoughts : undefined;
719
+ result.includeThoughts =
720
+ typeof tc.includeThoughts === 'boolean'
721
+ ? tc.includeThoughts
722
+ : undefined;
669
723
  }
670
- else if (typeof tc.thinkingBudget === "number") {
724
+ else if (typeof tc.thinkingBudget === 'number') {
671
725
  result.thinkingBudget = tc.thinkingBudget;
672
726
  }
673
727
  }
@@ -691,11 +745,11 @@ export function resolveThinkingConfig(userConfig, isThinkingModel, _isClaudeMode
691
745
  * Checks if a part is a thinking/reasoning block (Anthropic or Gemini style).
692
746
  */
693
747
  function isThinkingPart(part) {
694
- return part.type === "thinking"
695
- || part.type === "redacted_thinking"
696
- || part.type === "reasoning"
697
- || part.thinking !== undefined
698
- || part.thought === true;
748
+ return (part.type === 'thinking' ||
749
+ part.type === 'redacted_thinking' ||
750
+ part.type === 'reasoning' ||
751
+ part.thinking !== undefined ||
752
+ part.thought === true);
699
753
  }
700
754
  /**
701
755
  * Checks if a part has a signature field (thinking block signature).
@@ -713,15 +767,15 @@ function hasSignatureField(part) {
713
767
  * - Gemini: { functionCall }, { functionResponse }
714
768
  */
715
769
  function isToolBlock(part) {
716
- return part.type === "tool_use"
717
- || part.type === "tool_result"
718
- || part.tool_use_id !== undefined
719
- || part.tool_call_id !== undefined
720
- || part.tool_result !== undefined
721
- || part.tool_use !== undefined
722
- || part.toolUse !== undefined
723
- || part.functionCall !== undefined
724
- || part.functionResponse !== undefined;
770
+ return (part.type === 'tool_use' ||
771
+ part.type === 'tool_result' ||
772
+ part.tool_use_id !== undefined ||
773
+ part.tool_call_id !== undefined ||
774
+ part.tool_result !== undefined ||
775
+ part.tool_use !== undefined ||
776
+ part.toolUse !== undefined ||
777
+ part.functionCall !== undefined ||
778
+ part.functionResponse !== undefined);
725
779
  }
726
780
  /**
727
781
  * Unconditionally strips ALL thinking/reasoning blocks from a content array.
@@ -729,8 +783,8 @@ function isToolBlock(part) {
729
783
  * Claude will generate fresh thinking for each turn.
730
784
  */
731
785
  function stripAllThinkingBlocks(contentArray) {
732
- return contentArray.map(item => {
733
- if (!item || typeof item !== "object")
786
+ return contentArray.map((item) => {
787
+ if (!item || typeof item !== 'object')
734
788
  return item;
735
789
  if (isToolBlock(item))
736
790
  return item;
@@ -739,7 +793,7 @@ function stripAllThinkingBlocks(contentArray) {
739
793
  const cc = item.cache_control;
740
794
  // Use plain empty text part — thinking-format sentinels get converted by the proxy
741
795
  // into Claude thinking blocks missing the required `thinking` field.
742
- const sentinel = { text: "." };
796
+ const sentinel = { text: '.' };
743
797
  if (cc)
744
798
  sentinel.cache_control = cc;
745
799
  return sentinel;
@@ -763,7 +817,7 @@ function removeTrailingThinkingBlocks(contentArray, sessionId, getCachedSignatur
763
817
  break;
764
818
  // Replace with sentinel instead of popping — preserves array length
765
819
  const cc = part?.cache_control;
766
- const sentinel = { text: "." };
820
+ const sentinel = { text: '.' };
767
821
  if (cc)
768
822
  sentinel.cache_control = cc;
769
823
  result[i] = sentinel;
@@ -776,14 +830,14 @@ function removeTrailingThinkingBlocks(contentArray, sessionId, getCachedSignatur
776
830
  */
777
831
  function hasValidSignature(part) {
778
832
  const signature = part.thought === true ? part.thoughtSignature : part.signature;
779
- return typeof signature === "string" && signature.length >= 50;
833
+ return typeof signature === 'string' && signature.length >= 50;
780
834
  }
781
835
  /**
782
836
  * Gets the signature from a thinking part, if present.
783
837
  */
784
838
  function getSignature(part) {
785
839
  const signature = part.thought === true ? part.thoughtSignature : part.signature;
786
- return typeof signature === "string" ? signature : undefined;
840
+ return typeof signature === 'string' ? signature : undefined;
787
841
  }
788
842
  /**
789
843
  * Checks if a thinking part's signature was generated by our plugin (exists in our cache).
@@ -809,21 +863,21 @@ function isOurCachedSignature(part, sessionId, getCachedSignatureFn) {
809
863
  * Gets the text content from a thinking part.
810
864
  */
811
865
  function getThinkingText(part) {
812
- if (typeof part.text === "string")
866
+ if (typeof part.text === 'string')
813
867
  return part.text;
814
- if (typeof part.thinking === "string")
868
+ if (typeof part.thinking === 'string')
815
869
  return part.thinking;
816
- if (part.text && typeof part.text === "object") {
870
+ if (part.text && typeof part.text === 'object') {
817
871
  const maybeText = part.text.text;
818
- if (typeof maybeText === "string")
872
+ if (typeof maybeText === 'string')
819
873
  return maybeText;
820
874
  }
821
- if (part.thinking && typeof part.thinking === "object") {
875
+ if (part.thinking && typeof part.thinking === 'object') {
822
876
  const maybeText = part.thinking.text ?? part.thinking.thinking;
823
- if (typeof maybeText === "string")
877
+ if (typeof maybeText === 'string')
824
878
  return maybeText;
825
879
  }
826
- return "";
880
+ return '';
827
881
  }
828
882
  /**
829
883
  * Recursively strips cache_control and providerOptions from any object.
@@ -832,13 +886,13 @@ function getThinkingText(part) {
832
886
  function stripCacheControlRecursively(obj) {
833
887
  if (obj === null || obj === undefined)
834
888
  return obj;
835
- if (typeof obj !== "object")
889
+ if (typeof obj !== 'object')
836
890
  return obj;
837
891
  if (Array.isArray(obj))
838
- return obj.map(item => stripCacheControlRecursively(item));
892
+ return obj.map((item) => stripCacheControlRecursively(item));
839
893
  const result = {};
840
894
  for (const [key, value] of Object.entries(obj)) {
841
- if (key === "cache_control" || key === "providerOptions")
895
+ if (key === 'cache_control' || key === 'providerOptions')
842
896
  continue;
843
897
  result[key] = stripCacheControlRecursively(value);
844
898
  }
@@ -853,16 +907,16 @@ function sanitizeThinkingPart(part) {
853
907
  // Gemini-style thought blocks: { thought: true, text, thoughtSignature }
854
908
  if (part.thought === true) {
855
909
  let textContent = part.text;
856
- if (typeof textContent === "object" && textContent !== null) {
910
+ if (typeof textContent === 'object' && textContent !== null) {
857
911
  const maybeText = textContent.text;
858
- textContent = typeof maybeText === "string" ? maybeText : undefined;
912
+ textContent = typeof maybeText === 'string' ? maybeText : undefined;
859
913
  }
860
- const hasContent = typeof textContent === "string" && textContent.trim().length > 0;
914
+ const hasContent = typeof textContent === 'string' && textContent.trim().length > 0;
861
915
  if (!hasContent && !part.thoughtSignature) {
862
916
  return null;
863
917
  }
864
918
  const sanitized = { thought: true };
865
- sanitized.text = typeof textContent === "string" ? textContent : "";
919
+ sanitized.text = typeof textContent === 'string' ? textContent : '';
866
920
  if (part.thoughtSignature !== undefined)
867
921
  sanitized.thoughtSignature = part.thoughtSignature;
868
922
  if (part.cache_control !== undefined)
@@ -870,18 +924,25 @@ function sanitizeThinkingPart(part) {
870
924
  return sanitized;
871
925
  }
872
926
  // Anthropic-style thinking/redacted_thinking blocks: { type: "thinking"|"redacted_thinking", thinking, signature }
873
- if (part.type === "thinking" || part.type === "redacted_thinking" || part.thinking !== undefined) {
927
+ if (part.type === 'thinking' ||
928
+ part.type === 'redacted_thinking' ||
929
+ part.thinking !== undefined) {
874
930
  let thinkingContent = part.thinking ?? part.text;
875
- if (thinkingContent !== undefined && typeof thinkingContent === "object" && thinkingContent !== null) {
931
+ if (thinkingContent !== undefined &&
932
+ typeof thinkingContent === 'object' &&
933
+ thinkingContent !== null) {
876
934
  const maybeText = thinkingContent.text ?? thinkingContent.thinking;
877
- thinkingContent = typeof maybeText === "string" ? maybeText : undefined;
935
+ thinkingContent = typeof maybeText === 'string' ? maybeText : undefined;
878
936
  }
879
- const hasContent = typeof thinkingContent === "string" && thinkingContent.trim().length > 0;
937
+ const hasContent = typeof thinkingContent === 'string' && thinkingContent.trim().length > 0;
880
938
  if (!hasContent && !part.signature) {
881
939
  return null;
882
940
  }
883
- const sanitized = { type: part.type === "redacted_thinking" ? "redacted_thinking" : "thinking" };
884
- sanitized.thinking = typeof thinkingContent === "string" ? thinkingContent : "";
941
+ const sanitized = {
942
+ type: part.type === 'redacted_thinking' ? 'redacted_thinking' : 'thinking',
943
+ };
944
+ sanitized.thinking =
945
+ typeof thinkingContent === 'string' ? thinkingContent : '';
885
946
  if (part.signature !== undefined)
886
947
  sanitized.signature = part.signature;
887
948
  if (part.cache_control !== undefined)
@@ -889,18 +950,18 @@ function sanitizeThinkingPart(part) {
889
950
  return sanitized;
890
951
  }
891
952
  // Reasoning blocks (OpenCode format): { type: "reasoning", text, signature }
892
- if (part.type === "reasoning") {
953
+ if (part.type === 'reasoning') {
893
954
  let textContent = part.text;
894
- if (typeof textContent === "object" && textContent !== null) {
955
+ if (typeof textContent === 'object' && textContent !== null) {
895
956
  const maybeText = textContent.text;
896
- textContent = typeof maybeText === "string" ? maybeText : undefined;
957
+ textContent = typeof maybeText === 'string' ? maybeText : undefined;
897
958
  }
898
- const hasContent = typeof textContent === "string" && textContent.trim().length > 0;
959
+ const hasContent = typeof textContent === 'string' && textContent.trim().length > 0;
899
960
  if (!hasContent && !part.signature) {
900
961
  return null;
901
962
  }
902
- const sanitized = { type: "reasoning" };
903
- sanitized.text = typeof textContent === "string" ? textContent : "";
963
+ const sanitized = { type: 'reasoning' };
964
+ sanitized.text = typeof textContent === 'string' ? textContent : '';
904
965
  if (part.signature !== undefined)
905
966
  sanitized.signature = part.signature;
906
967
  if (part.cache_control !== undefined)
@@ -914,7 +975,7 @@ function sanitizeThinkingPart(part) {
914
975
  function findLastAssistantIndex(contents, roleValue) {
915
976
  for (let i = contents.length - 1; i >= 0; i--) {
916
977
  const content = contents[i];
917
- if (content && typeof content === "object" && content.role === roleValue) {
978
+ if (content && typeof content === 'object' && content.role === roleValue) {
918
979
  return i;
919
980
  }
920
981
  }
@@ -928,7 +989,7 @@ function filterContentArray(contentArray, sessionId, getCachedSignatureFn, isCla
928
989
  }
929
990
  const filtered = [];
930
991
  for (const item of contentArray) {
931
- if (!item || typeof item !== "object") {
992
+ if (!item || typeof item !== 'object') {
932
993
  filtered.push(item);
933
994
  continue;
934
995
  }
@@ -954,7 +1015,7 @@ function filterContentArray(contentArray, sessionId, getCachedSignatureFn, isCla
954
1015
  if (isClaudeModel && (isThinking || hasSignature)) {
955
1016
  // Use plain empty text part — thinking-format sentinels get converted by the proxy
956
1017
  // into Claude thinking blocks with missing required fields
957
- const sentinel = { text: "." };
1018
+ const sentinel = { text: '.' };
958
1019
  if (item.cache_control)
959
1020
  sentinel.cache_control = item.cache_control;
960
1021
  filtered.push(sentinel);
@@ -974,7 +1035,7 @@ function filterContentArray(contentArray, sessionId, getCachedSignatureFn, isCla
974
1035
  }
975
1036
  else {
976
1037
  // sanitizeThinkingPart returned null — use sentinel to preserve array length
977
- const sentinel = { text: "." };
1038
+ const sentinel = { text: '.' };
978
1039
  if (item.cache_control)
979
1040
  sentinel.cache_control = item.cache_control;
980
1041
  filtered.push(sentinel);
@@ -983,9 +1044,11 @@ function filterContentArray(contentArray, sessionId, getCachedSignatureFn, isCla
983
1044
  }
984
1045
  // Not our signature (or no signature) - use plain empty text sentinel // Thinking-format sentinels get converted by the proxy into Claude thinking blocks with missing required fields
985
1046
  const existingSignature = item.signature || item.thoughtSignature;
986
- const signatureInfo = existingSignature ? `foreign signature (${String(existingSignature).length} chars)` : "no signature";
1047
+ const signatureInfo = existingSignature
1048
+ ? `foreign signature (${String(existingSignature).length} chars)`
1049
+ : 'no signature';
987
1050
  log.debug(`Injecting plain text sentinel for last-message thinking block with ${signatureInfo}`);
988
- const sentinel = { text: "." };
1051
+ const sentinel = { text: '.' };
989
1052
  if (item.cache_control)
990
1053
  sentinel.cache_control = item.cache_control;
991
1054
  filtered.push(sentinel);
@@ -998,7 +1061,7 @@ function filterContentArray(contentArray, sessionId, getCachedSignatureFn, isCla
998
1061
  }
999
1062
  else {
1000
1063
  // sanitizeThinkingPart returned null — use sentinel to preserve array length
1001
- const sentinel = { text: "." };
1064
+ const sentinel = { text: '.' };
1002
1065
  if (item.cache_control)
1003
1066
  sentinel.cache_control = item.cache_control;
1004
1067
  filtered.push(sentinel);
@@ -1012,9 +1075,11 @@ function filterContentArray(contentArray, sessionId, getCachedSignatureFn, isCla
1012
1075
  if (cachedSignature && cachedSignature.length >= 50) {
1013
1076
  const restoredPart = { ...item };
1014
1077
  if (item.thought === true) {
1078
+ ;
1015
1079
  restoredPart.thoughtSignature = cachedSignature;
1016
1080
  }
1017
1081
  else {
1082
+ ;
1018
1083
  restoredPart.signature = cachedSignature;
1019
1084
  }
1020
1085
  const sanitized = sanitizeThinkingPart(restoredPart);
@@ -1023,7 +1088,7 @@ function filterContentArray(contentArray, sessionId, getCachedSignatureFn, isCla
1023
1088
  }
1024
1089
  else {
1025
1090
  // sanitizeThinkingPart returned null — use sentinel to preserve array length
1026
- const sentinel = { text: "." };
1091
+ const sentinel = { text: '.' };
1027
1092
  if (item.cache_control)
1028
1093
  sentinel.cache_control = item.cache_control;
1029
1094
  filtered.push(sentinel);
@@ -1034,7 +1099,7 @@ function filterContentArray(contentArray, sessionId, getCachedSignatureFn, isCla
1034
1099
  }
1035
1100
  // Catch-all: thinking/signature part that didn't match any branch above
1036
1101
  // Use sentinel instead of silently dropping to preserve array length
1037
- const sentinel = { text: "." };
1102
+ const sentinel = { text: '.' };
1038
1103
  if (item.cache_control)
1039
1104
  sentinel.cache_control = item.cache_control;
1040
1105
  filtered.push(sentinel);
@@ -1050,23 +1115,24 @@ function filterContentArray(contentArray, sessionId, getCachedSignatureFn, isCla
1050
1115
  * @param getCachedSignatureFn - Optional function to retrieve cached signatures
1051
1116
  */
1052
1117
  export function filterUnsignedThinkingBlocks(contents, sessionId, getCachedSignatureFn, isClaudeModel) {
1053
- const lastAssistantIdx = findLastAssistantIndex(contents, "model");
1118
+ const lastAssistantIdx = findLastAssistantIndex(contents, 'model');
1054
1119
  return contents.map((content, idx) => {
1055
- if (!content || typeof content !== "object") {
1120
+ if (!content || typeof content !== 'object') {
1056
1121
  return content;
1057
1122
  }
1058
1123
  const isLastAssistant = idx === lastAssistantIdx;
1059
1124
  if (Array.isArray(content.parts)) {
1060
1125
  const filteredParts = filterContentArray(content.parts, sessionId, getCachedSignatureFn, isClaudeModel, isLastAssistant);
1061
- const trimmedParts = content.role === "model" && !isClaudeModel
1126
+ const trimmedParts = content.role === 'model' && !isClaudeModel
1062
1127
  ? removeTrailingThinkingBlocks(filteredParts, sessionId, getCachedSignatureFn)
1063
1128
  : filteredParts;
1064
1129
  return { ...content, parts: trimmedParts };
1065
1130
  }
1066
1131
  if (Array.isArray(content.content)) {
1067
- const isAssistantRole = content.role === "assistant";
1132
+ const isAssistantRole = content.role === 'assistant';
1068
1133
  const isLastAssistantContent = idx === lastAssistantIdx ||
1069
- (isAssistantRole && idx === findLastAssistantIndex(contents, "assistant"));
1134
+ (isAssistantRole &&
1135
+ idx === findLastAssistantIndex(contents, 'assistant'));
1070
1136
  const filteredContent = filterContentArray(content.content, sessionId, getCachedSignatureFn, isClaudeModel, isLastAssistantContent);
1071
1137
  const trimmedContent = isAssistantRole && !isClaudeModel
1072
1138
  ? removeTrailingThinkingBlocks(filteredContent, sessionId, getCachedSignatureFn)
@@ -1080,13 +1146,13 @@ export function filterUnsignedThinkingBlocks(contents, sessionId, getCachedSigna
1080
1146
  * Filters thinking blocks from Anthropic-style messages[] payloads using cached signatures.
1081
1147
  */
1082
1148
  export function filterMessagesThinkingBlocks(messages, sessionId, getCachedSignatureFn, isClaudeModel) {
1083
- const lastAssistantIdx = findLastAssistantIndex(messages, "assistant");
1149
+ const lastAssistantIdx = findLastAssistantIndex(messages, 'assistant');
1084
1150
  return messages.map((message, idx) => {
1085
- if (!message || typeof message !== "object") {
1151
+ if (!message || typeof message !== 'object') {
1086
1152
  return message;
1087
1153
  }
1088
1154
  if (Array.isArray(message.content)) {
1089
- const isAssistantRole = message.role === "assistant";
1155
+ const isAssistantRole = message.role === 'assistant';
1090
1156
  const isLastAssistant = isAssistantRole && idx === lastAssistantIdx;
1091
1157
  const filteredContent = filterContentArray(message.content, sessionId, getCachedSignatureFn, isClaudeModel, isLastAssistant);
1092
1158
  const trimmedContent = isAssistantRole && !isClaudeModel
@@ -1100,7 +1166,7 @@ export function filterMessagesThinkingBlocks(messages, sessionId, getCachedSigna
1100
1166
  export function deepFilterThinkingBlocks(payload, sessionId, getCachedSignatureFn, isClaudeModel) {
1101
1167
  const visited = new WeakSet();
1102
1168
  const walk = (value) => {
1103
- if (!value || typeof value !== "object") {
1169
+ if (!value || typeof value !== 'object') {
1104
1170
  return;
1105
1171
  }
1106
1172
  if (visited.has(value)) {
@@ -1108,7 +1174,9 @@ export function deepFilterThinkingBlocks(payload, sessionId, getCachedSignatureF
1108
1174
  }
1109
1175
  visited.add(value);
1110
1176
  if (Array.isArray(value)) {
1111
- value.forEach((item) => walk(item));
1177
+ value.forEach((item) => {
1178
+ walk(item);
1179
+ });
1112
1180
  return;
1113
1181
  }
1114
1182
  const obj = value;
@@ -1118,7 +1186,9 @@ export function deepFilterThinkingBlocks(payload, sessionId, getCachedSignatureF
1118
1186
  if (Array.isArray(obj.messages)) {
1119
1187
  obj.messages = filterMessagesThinkingBlocks(obj.messages, sessionId, getCachedSignatureFn, isClaudeModel);
1120
1188
  }
1121
- Object.keys(obj).forEach((key) => walk(obj[key]));
1189
+ Object.keys(obj).forEach((key) => {
1190
+ walk(obj[key]);
1191
+ });
1122
1192
  };
1123
1193
  walk(payload);
1124
1194
  return payload;
@@ -1129,47 +1199,53 @@ export function deepFilterThinkingBlocks(payload, sessionId, getCachedSignatureF
1129
1199
  * Claude responses through Antigravity may use candidates structure with Anthropic-style parts.
1130
1200
  */
1131
1201
  function transformGeminiCandidate(candidate) {
1132
- if (!candidate || typeof candidate !== "object") {
1202
+ if (!candidate || typeof candidate !== 'object') {
1133
1203
  return candidate;
1134
1204
  }
1135
1205
  const content = candidate.content;
1136
- if (!content || typeof content !== "object" || !Array.isArray(content.parts)) {
1206
+ if (!content ||
1207
+ typeof content !== 'object' ||
1208
+ !Array.isArray(content.parts)) {
1137
1209
  return candidate;
1138
1210
  }
1139
1211
  const thinkingTexts = [];
1140
1212
  const transformedParts = content.parts.map((part) => {
1141
- if (!part || typeof part !== "object") {
1213
+ if (!part || typeof part !== 'object') {
1142
1214
  return part;
1143
1215
  }
1144
1216
  // Handle Gemini-style: thought: true
1145
1217
  if (part.thought === true) {
1146
- const thinkingText = typeof part.text === "string" ? part.text : "";
1218
+ const thinkingText = typeof part.text === 'string' ? part.text : '';
1147
1219
  thinkingTexts.push(thinkingText);
1148
1220
  // Clean object — NO spread to prevent thinking: <object> leaking into output
1149
1221
  const transformed = {
1150
- type: "reasoning",
1222
+ type: 'reasoning',
1151
1223
  text: thinkingText,
1152
1224
  thought: true,
1153
1225
  };
1154
1226
  const sig = part.thoughtSignature || part.signature;
1155
- if (typeof sig === "string" && sig)
1227
+ if (typeof sig === 'string' && sig)
1156
1228
  transformed.thoughtSignature = sig;
1157
1229
  if (part.cache_control)
1158
1230
  transformed.cache_control = part.cache_control;
1159
1231
  return transformed;
1160
1232
  }
1161
1233
  // Handle Anthropic-style in candidates: type: "thinking"
1162
- if (part.type === "thinking") {
1163
- const thinkingText = typeof part.thinking === "string" ? part.thinking : typeof part.text === "string" ? part.text : "";
1234
+ if (part.type === 'thinking') {
1235
+ const thinkingText = typeof part.thinking === 'string'
1236
+ ? part.thinking
1237
+ : typeof part.text === 'string'
1238
+ ? part.text
1239
+ : '';
1164
1240
  thinkingTexts.push(thinkingText);
1165
1241
  // Clean object — NO spread to prevent thinking: <object> leaking into output
1166
1242
  const transformed = {
1167
- type: "reasoning",
1243
+ type: 'reasoning',
1168
1244
  text: thinkingText,
1169
1245
  thought: true,
1170
1246
  };
1171
1247
  const sig = part.thoughtSignature || part.signature;
1172
- if (typeof sig === "string" && sig)
1248
+ if (typeof sig === 'string' && sig)
1173
1249
  transformed.thoughtSignature = sig;
1174
1250
  if (part.cache_control)
1175
1251
  transformed.cache_control = part.cache_control;
@@ -1206,7 +1282,9 @@ function transformGeminiCandidate(candidate) {
1206
1282
  return {
1207
1283
  ...candidate,
1208
1284
  content: { ...content, parts: transformedParts },
1209
- ...(thinkingTexts.length > 0 ? { reasoning_content: thinkingTexts.join("\n\n") } : {}),
1285
+ ...(thinkingTexts.length > 0
1286
+ ? { reasoning_content: thinkingTexts.join('\n\n') }
1287
+ : {}),
1210
1288
  };
1211
1289
  }
1212
1290
  /**
@@ -1215,7 +1293,7 @@ function transformGeminiCandidate(candidate) {
1215
1293
  * Also extracts reasoning_content for Anthropic-style responses.
1216
1294
  */
1217
1295
  export function transformThinkingParts(response) {
1218
- if (!response || typeof response !== "object") {
1296
+ if (!response || typeof response !== 'object') {
1219
1297
  return response;
1220
1298
  }
1221
1299
  const resp = response;
@@ -1225,17 +1303,23 @@ export function transformThinkingParts(response) {
1225
1303
  if (Array.isArray(resp.content)) {
1226
1304
  const transformedContent = [];
1227
1305
  for (const block of resp.content) {
1228
- if (block && typeof block === "object" && block.type === "thinking") {
1229
- const thinkingText = typeof block.thinking === "string" ? block.thinking : typeof block.text === "string" ? block.text : "";
1306
+ if (block &&
1307
+ typeof block === 'object' &&
1308
+ block.type === 'thinking') {
1309
+ const thinkingText = typeof block.thinking === 'string'
1310
+ ? block.thinking
1311
+ : typeof block.text === 'string'
1312
+ ? block.text
1313
+ : '';
1230
1314
  reasoningTexts.push(thinkingText);
1231
1315
  // Clean object — NO spread to prevent thinking: <object> leaking into output
1232
1316
  const transformed = {
1233
- type: "reasoning",
1317
+ type: 'reasoning',
1234
1318
  text: thinkingText,
1235
1319
  thought: true,
1236
1320
  };
1237
1321
  const sig = block.thoughtSignature || block.signature;
1238
- if (typeof sig === "string" && sig)
1322
+ if (typeof sig === 'string' && sig)
1239
1323
  transformed.thoughtSignature = sig;
1240
1324
  if (block.cache_control)
1241
1325
  transformed.cache_control = block.cache_control;
@@ -1253,7 +1337,7 @@ export function transformThinkingParts(response) {
1253
1337
  }
1254
1338
  // Add reasoning_content if we found any thinking blocks (for Anthropic-style)
1255
1339
  if (reasoningTexts.length > 0 && !result.reasoning_content) {
1256
- result.reasoning_content = reasoningTexts.join("\n\n");
1340
+ result.reasoning_content = reasoningTexts.join('\n\n');
1257
1341
  }
1258
1342
  return result;
1259
1343
  }
@@ -1261,17 +1345,22 @@ export function transformThinkingParts(response) {
1261
1345
  * Ensures thinkingConfig is valid: includeThoughts only allowed when budget > 0.
1262
1346
  */
1263
1347
  export function normalizeThinkingConfig(config) {
1264
- if (!config || typeof config !== "object") {
1348
+ if (!config || typeof config !== 'object') {
1265
1349
  return undefined;
1266
1350
  }
1267
1351
  const record = config;
1268
1352
  const budgetRaw = record.thinkingBudget ?? record.thinking_budget;
1269
1353
  const includeRaw = record.includeThoughts ?? record.include_thoughts;
1270
- const thinkingBudget = typeof budgetRaw === "number" && Number.isFinite(budgetRaw) ? budgetRaw : undefined;
1271
- const includeThoughts = typeof includeRaw === "boolean" ? includeRaw : undefined;
1354
+ const thinkingBudget = typeof budgetRaw === 'number' && Number.isFinite(budgetRaw)
1355
+ ? budgetRaw
1356
+ : undefined;
1357
+ const includeThoughts = typeof includeRaw === 'boolean' ? includeRaw : undefined;
1272
1358
  const enableThinking = thinkingBudget !== undefined && thinkingBudget > 0;
1273
- const finalInclude = enableThinking ? includeThoughts ?? false : false;
1274
- if (!enableThinking && finalInclude === false && thinkingBudget === undefined && includeThoughts === undefined) {
1359
+ const finalInclude = enableThinking ? (includeThoughts ?? false) : false;
1360
+ if (!enableThinking &&
1361
+ finalInclude === false &&
1362
+ thinkingBudget === undefined &&
1363
+ includeThoughts === undefined) {
1275
1364
  return undefined;
1276
1365
  }
1277
1366
  const normalized = {};
@@ -1290,13 +1379,13 @@ export function parseAntigravityApiBody(rawText) {
1290
1379
  try {
1291
1380
  const parsed = JSON.parse(rawText);
1292
1381
  if (Array.isArray(parsed)) {
1293
- const firstObject = parsed.find((item) => typeof item === "object" && item !== null);
1294
- if (firstObject && typeof firstObject === "object") {
1382
+ const firstObject = parsed.find((item) => typeof item === 'object' && item !== null);
1383
+ if (firstObject && typeof firstObject === 'object') {
1295
1384
  return firstObject;
1296
1385
  }
1297
1386
  return null;
1298
1387
  }
1299
- if (parsed && typeof parsed === "object") {
1388
+ if (parsed && typeof parsed === 'object') {
1300
1389
  return parsed;
1301
1390
  }
1302
1391
  return null;
@@ -1309,14 +1398,14 @@ export function parseAntigravityApiBody(rawText) {
1309
1398
  * Extracts usageMetadata from a response object, guarding types.
1310
1399
  */
1311
1400
  export function extractUsageMetadata(body) {
1312
- const usage = (body.response && typeof body.response === "object"
1401
+ const usage = (body.response && typeof body.response === 'object'
1313
1402
  ? body.response.usageMetadata
1314
1403
  : undefined);
1315
- if (!usage || typeof usage !== "object") {
1404
+ if (!usage || typeof usage !== 'object') {
1316
1405
  return null;
1317
1406
  }
1318
1407
  const asRecord = usage;
1319
- const toNumber = (value) => typeof value === "number" && Number.isFinite(value) ? value : undefined;
1408
+ const toNumber = (value) => typeof value === 'number' && Number.isFinite(value) ? value : undefined;
1320
1409
  return {
1321
1410
  totalTokenCount: toNumber(asRecord.totalTokenCount),
1322
1411
  promptTokenCount: toNumber(asRecord.promptTokenCount),
@@ -1329,9 +1418,9 @@ export function extractUsageMetadata(body) {
1329
1418
  * Walks SSE lines to find a usage-bearing response chunk.
1330
1419
  */
1331
1420
  export function extractUsageFromSsePayload(payload) {
1332
- const lines = payload.split("\n");
1421
+ const lines = payload.split('\n');
1333
1422
  for (const line of lines) {
1334
- if (!line.startsWith("data:")) {
1423
+ if (!line.startsWith('data:')) {
1335
1424
  continue;
1336
1425
  }
1337
1426
  const jsonText = line.slice(5).trim();
@@ -1340,16 +1429,16 @@ export function extractUsageFromSsePayload(payload) {
1340
1429
  }
1341
1430
  try {
1342
1431
  const parsed = JSON.parse(jsonText);
1343
- if (parsed && typeof parsed === "object") {
1344
- const usage = extractUsageMetadata({ response: parsed.response });
1432
+ if (parsed && typeof parsed === 'object') {
1433
+ const usage = extractUsageMetadata({
1434
+ response: parsed.response,
1435
+ });
1345
1436
  if (usage) {
1346
1437
  return usage;
1347
1438
  }
1348
1439
  }
1349
1440
  }
1350
- catch {
1351
- continue;
1352
- }
1441
+ catch { }
1353
1442
  }
1354
1443
  return null;
1355
1444
  }
@@ -1361,10 +1450,10 @@ export function rewriteAntigravityPreviewAccessError(body, status, requestedMode
1361
1450
  return null;
1362
1451
  }
1363
1452
  const error = body.error ?? {};
1364
- const trimmedMessage = typeof error.message === "string" ? error.message.trim() : "";
1453
+ const trimmedMessage = typeof error.message === 'string' ? error.message.trim() : '';
1365
1454
  const messagePrefix = trimmedMessage.length > 0
1366
1455
  ? trimmedMessage
1367
- : "Antigravity preview features are not enabled for this account.";
1456
+ : 'Antigravity preview features are not enabled for this account.';
1368
1457
  const enhancedMessage = `${messagePrefix} Request preview access at ${ANTIGRAVITY_PREVIEW_LINK} before using this model.`;
1369
1458
  return {
1370
1459
  ...body,
@@ -1381,7 +1470,7 @@ function needsPreviewAccessOverride(status, body, requestedModel) {
1381
1470
  if (isAntigravityModel(requestedModel)) {
1382
1471
  return true;
1383
1472
  }
1384
- const errorMessage = typeof body.error?.message === "string" ? body.error.message : "";
1473
+ const errorMessage = typeof body.error?.message === 'string' ? body.error.message : '';
1385
1474
  return isAntigravityModel(errorMessage);
1386
1475
  }
1387
1476
  function isAntigravityModel(target) {
@@ -1389,7 +1478,9 @@ function isAntigravityModel(target) {
1389
1478
  return false;
1390
1479
  }
1391
1480
  // Check for Antigravity models instead of Gemini 3
1392
- return /antigravity/i.test(target) || /opus/i.test(target) || /claude/i.test(target);
1481
+ return (/antigravity/i.test(target) ||
1482
+ /opus/i.test(target) ||
1483
+ /claude/i.test(target));
1393
1484
  }
1394
1485
  // ============================================================================
1395
1486
  // EMPTY RESPONSE DETECTION (Ported from LLM-API-Key-Proxy)
@@ -1406,7 +1497,7 @@ function isAntigravityModel(target) {
1406
1497
  * @returns true if the response is empty
1407
1498
  */
1408
1499
  export function isEmptyResponseBody(text) {
1409
- if (!text || !text.trim()) {
1500
+ if (!text?.trim()) {
1410
1501
  return true;
1411
1502
  }
1412
1503
  try {
@@ -1423,7 +1514,7 @@ export function isEmptyResponseBody(text) {
1423
1514
  }
1424
1515
  // Check for empty parts in content
1425
1516
  const content = firstCandidate.content;
1426
- if (!content || typeof content !== "object") {
1517
+ if (!content || typeof content !== 'object') {
1427
1518
  return true;
1428
1519
  }
1429
1520
  const parts = content.parts;
@@ -1432,13 +1523,13 @@ export function isEmptyResponseBody(text) {
1432
1523
  }
1433
1524
  // Check if all parts are empty (no text, no functionCall)
1434
1525
  const hasContent = parts.some((part) => {
1435
- if (!part || typeof part !== "object")
1526
+ if (!part || typeof part !== 'object')
1436
1527
  return false;
1437
- if (typeof part.text === "string" && part.text.length > 0)
1528
+ if (typeof part.text === 'string' && part.text.length > 0)
1438
1529
  return true;
1439
1530
  if (part.functionCall)
1440
1531
  return true;
1441
- if (part.thought === true && typeof part.text === "string")
1532
+ if (part.thought === true && typeof part.text === 'string')
1442
1533
  return true;
1443
1534
  return false;
1444
1535
  });
@@ -1461,14 +1552,16 @@ export function isEmptyResponseBody(text) {
1461
1552
  return true;
1462
1553
  }
1463
1554
  // Check if message has content or tool_calls
1464
- if (!message.content && !message.tool_calls && !message.reasoning_content) {
1555
+ if (!message.content &&
1556
+ !message.tool_calls &&
1557
+ !message.reasoning_content) {
1465
1558
  return true;
1466
1559
  }
1467
1560
  }
1468
1561
  // Check response wrapper (Antigravity envelope)
1469
1562
  if (parsed.response !== undefined) {
1470
1563
  const response = parsed.response;
1471
- if (!response || typeof response !== "object") {
1564
+ if (!response || typeof response !== 'object') {
1472
1565
  return true;
1473
1566
  }
1474
1567
  return isEmptyResponseBody(JSON.stringify(response));
@@ -1482,7 +1575,7 @@ export function isEmptyResponseBody(text) {
1482
1575
  }
1483
1576
  export function createStreamingChunkCounter() {
1484
1577
  let count = 0;
1485
- let hasRealContent = false;
1578
+ const hasRealContent = false;
1486
1579
  return {
1487
1580
  increment: () => {
1488
1581
  count++;
@@ -1498,11 +1591,11 @@ export function createStreamingChunkCounter() {
1498
1591
  * @returns true if the line contains content worth counting
1499
1592
  */
1500
1593
  export function isMeaningfulSseLine(line) {
1501
- if (!line.startsWith("data: ")) {
1594
+ if (!line.startsWith('data: ')) {
1502
1595
  return false;
1503
1596
  }
1504
1597
  const data = line.slice(6).trim();
1505
- if (data === "[DONE]") {
1598
+ if (data === '[DONE]') {
1506
1599
  return false;
1507
1600
  }
1508
1601
  if (!data) {
@@ -1516,7 +1609,7 @@ export function isMeaningfulSseLine(line) {
1516
1609
  const parts = candidate?.content?.parts;
1517
1610
  if (Array.isArray(parts) && parts.length > 0) {
1518
1611
  for (const part of parts) {
1519
- if (typeof part?.text === "string" && part.text.length > 0)
1612
+ if (typeof part?.text === 'string' && part.text.length > 0)
1520
1613
  return true;
1521
1614
  if (part?.functionCall)
1522
1615
  return true;
@@ -1557,29 +1650,29 @@ export function isMeaningfulSseLine(line) {
1557
1650
  */
1558
1651
  // Keys whose string values should NOT be parsed as JSON - they contain literal text content
1559
1652
  const SKIP_PARSE_KEYS = new Set([
1560
- "oldString",
1561
- "newString",
1562
- "content",
1563
- "filePath",
1564
- "path",
1565
- "text",
1566
- "code",
1567
- "source",
1568
- "data",
1569
- "body",
1570
- "message",
1571
- "prompt",
1572
- "input",
1573
- "output",
1574
- "result",
1575
- "value",
1576
- "query",
1577
- "pattern",
1578
- "replacement",
1579
- "template",
1580
- "script",
1581
- "command",
1582
- "snippet",
1653
+ 'oldString',
1654
+ 'newString',
1655
+ 'content',
1656
+ 'filePath',
1657
+ 'path',
1658
+ 'text',
1659
+ 'code',
1660
+ 'source',
1661
+ 'data',
1662
+ 'body',
1663
+ 'message',
1664
+ 'prompt',
1665
+ 'input',
1666
+ 'output',
1667
+ 'result',
1668
+ 'value',
1669
+ 'query',
1670
+ 'pattern',
1671
+ 'replacement',
1672
+ 'template',
1673
+ 'script',
1674
+ 'command',
1675
+ 'snippet',
1583
1676
  ]);
1584
1677
  export function recursivelyParseJsonStrings(obj, skipParseKeys = SKIP_PARSE_KEYS, currentKey) {
1585
1678
  if (obj === null || obj === undefined) {
@@ -1588,14 +1681,14 @@ export function recursivelyParseJsonStrings(obj, skipParseKeys = SKIP_PARSE_KEYS
1588
1681
  if (Array.isArray(obj)) {
1589
1682
  return obj.map((item) => recursivelyParseJsonStrings(item, skipParseKeys));
1590
1683
  }
1591
- if (typeof obj === "object") {
1684
+ if (typeof obj === 'object') {
1592
1685
  const result = {};
1593
1686
  for (const [key, value] of Object.entries(obj)) {
1594
1687
  result[key] = recursivelyParseJsonStrings(value, skipParseKeys, key);
1595
1688
  }
1596
1689
  return result;
1597
1690
  }
1598
- if (typeof obj !== "string") {
1691
+ if (typeof obj !== 'string') {
1599
1692
  return obj;
1600
1693
  }
1601
1694
  if (currentKey && skipParseKeys.has(currentKey)) {
@@ -1604,8 +1697,8 @@ export function recursivelyParseJsonStrings(obj, skipParseKeys = SKIP_PARSE_KEYS
1604
1697
  const stripped = obj.trim();
1605
1698
  // Check if string contains control character escape sequences
1606
1699
  // that need unescaping (\\n, \\t but NOT \\" or \\\\)
1607
- const hasControlCharEscapes = obj.includes("\\n") || obj.includes("\\t");
1608
- const hasIntentionalEscapes = obj.includes('\\"') || obj.includes("\\\\");
1700
+ const hasControlCharEscapes = obj.includes('\\n') || obj.includes('\\t');
1701
+ const hasIntentionalEscapes = obj.includes('\\"') || obj.includes('\\\\');
1609
1702
  if (hasControlCharEscapes && !hasIntentionalEscapes) {
1610
1703
  try {
1611
1704
  // Use JSON.parse with quotes to unescape the string
@@ -1616,10 +1709,10 @@ export function recursivelyParseJsonStrings(obj, skipParseKeys = SKIP_PARSE_KEYS
1616
1709
  }
1617
1710
  }
1618
1711
  // Check if it looks like JSON (starts with { or [)
1619
- if (stripped && (stripped[0] === "{" || stripped[0] === "[")) {
1712
+ if (stripped && (stripped[0] === '{' || stripped[0] === '[')) {
1620
1713
  // Try standard parsing first
1621
- if ((stripped.startsWith("{") && stripped.endsWith("}")) ||
1622
- (stripped.startsWith("[") && stripped.endsWith("]"))) {
1714
+ if ((stripped.startsWith('{') && stripped.endsWith('}')) ||
1715
+ (stripped.startsWith('[') && stripped.endsWith(']'))) {
1623
1716
  try {
1624
1717
  const parsed = JSON.parse(obj);
1625
1718
  return recursivelyParseJsonStrings(parsed);
@@ -1629,13 +1722,13 @@ export function recursivelyParseJsonStrings(obj, skipParseKeys = SKIP_PARSE_KEYS
1629
1722
  }
1630
1723
  }
1631
1724
  // Handle malformed JSON: array that doesn't end with ]
1632
- if (stripped.startsWith("[") && !stripped.endsWith("]")) {
1725
+ if (stripped.startsWith('[') && !stripped.endsWith(']')) {
1633
1726
  try {
1634
- const lastBracket = stripped.lastIndexOf("]");
1727
+ const lastBracket = stripped.lastIndexOf(']');
1635
1728
  if (lastBracket > 0) {
1636
1729
  const cleaned = stripped.slice(0, lastBracket + 1);
1637
1730
  const parsed = JSON.parse(cleaned);
1638
- log.debug("Auto-corrected malformed JSON array", {
1731
+ log.debug('Auto-corrected malformed JSON array', {
1639
1732
  truncatedChars: stripped.length - cleaned.length,
1640
1733
  });
1641
1734
  return recursivelyParseJsonStrings(parsed);
@@ -1646,13 +1739,13 @@ export function recursivelyParseJsonStrings(obj, skipParseKeys = SKIP_PARSE_KEYS
1646
1739
  }
1647
1740
  }
1648
1741
  // Handle malformed JSON: object that doesn't end with }
1649
- if (stripped.startsWith("{") && !stripped.endsWith("}")) {
1742
+ if (stripped.startsWith('{') && !stripped.endsWith('}')) {
1650
1743
  try {
1651
- const lastBrace = stripped.lastIndexOf("}");
1744
+ const lastBrace = stripped.lastIndexOf('}');
1652
1745
  if (lastBrace > 0) {
1653
1746
  const cleaned = stripped.slice(0, lastBrace + 1);
1654
1747
  const parsed = JSON.parse(cleaned);
1655
- log.debug("Auto-corrected malformed JSON object", {
1748
+ log.debug('Auto-corrected malformed JSON object', {
1656
1749
  truncatedChars: stripped.length - cleaned.length,
1657
1750
  });
1658
1751
  return recursivelyParseJsonStrings(parsed);
@@ -1701,7 +1794,7 @@ export function fixToolResponseGrouping(contents) {
1701
1794
  if (responseParts.length > 0) {
1702
1795
  // Collect responses by ID (skip duplicates)
1703
1796
  for (const resp of responseParts) {
1704
- const respId = resp.functionResponse?.id || "";
1797
+ const respId = resp.functionResponse?.id || '';
1705
1798
  if (respId && !collectedResponses.has(respId)) {
1706
1799
  collectedResponses.set(respId, resp);
1707
1800
  }
@@ -1709,30 +1802,29 @@ export function fixToolResponseGrouping(contents) {
1709
1802
  // Try to satisfy the most recent pending group
1710
1803
  for (let i = pendingGroups.length - 1; i >= 0; i--) {
1711
1804
  const group = pendingGroups[i];
1712
- if (group.ids.every(id => collectedResponses.has(id))) {
1805
+ if (group.ids.every((id) => collectedResponses.has(id))) {
1713
1806
  // All IDs found - build the response group
1714
- const groupResponses = group.ids.map(id => {
1807
+ const groupResponses = group.ids.map((id) => {
1715
1808
  const resp = collectedResponses.get(id);
1716
1809
  collectedResponses.delete(id);
1717
1810
  return resp;
1718
1811
  });
1719
- newContents.push({ parts: groupResponses, role: "user" });
1812
+ newContents.push({ parts: groupResponses, role: 'user' });
1720
1813
  pendingGroups.splice(i, 1);
1721
1814
  break; // Only satisfy one group at a time
1722
1815
  }
1723
1816
  }
1724
1817
  continue; // Don't add the original response message
1725
1818
  }
1726
- if (role === "model") {
1819
+ if (role === 'model') {
1727
1820
  // Check for function calls in this model message
1728
1821
  const funcCalls = parts.filter((p) => p?.functionCall);
1729
1822
  newContents.push(content);
1730
1823
  if (funcCalls.length > 0) {
1731
1824
  const callIds = funcCalls
1732
- .map((fc) => fc.functionCall?.id || "")
1825
+ .map((fc) => fc.functionCall?.id || '')
1733
1826
  .filter(Boolean);
1734
- const funcNames = funcCalls
1735
- .map((fc) => fc.functionCall?.name || "");
1827
+ const funcNames = funcCalls.map((fc) => fc.functionCall?.name || '');
1736
1828
  if (callIds.length > 0) {
1737
1829
  pendingGroups.push({
1738
1830
  ids: callIds,
@@ -1753,7 +1845,7 @@ export function fixToolResponseGrouping(contents) {
1753
1845
  const groupResponses = [];
1754
1846
  for (let i = 0; i < group.ids.length; i++) {
1755
1847
  const expectedId = group.ids[i];
1756
- const expectedName = group.funcNames[i] || "";
1848
+ const expectedName = group.funcNames[i] || '';
1757
1849
  if (collectedResponses.has(expectedId)) {
1758
1850
  // Direct ID match - ideal case
1759
1851
  groupResponses.push(collectedResponses.get(expectedId));
@@ -1764,7 +1856,7 @@ export function fixToolResponseGrouping(contents) {
1764
1856
  let matchedId = null;
1765
1857
  // Pass 1: Match by function name
1766
1858
  for (const [orphanId, orphanResp] of collectedResponses) {
1767
- const orphanName = orphanResp.functionResponse?.name || "";
1859
+ const orphanName = orphanResp.functionResponse?.name || '';
1768
1860
  if (orphanName === expectedName) {
1769
1861
  matchedId = orphanId;
1770
1862
  break;
@@ -1773,7 +1865,7 @@ export function fixToolResponseGrouping(contents) {
1773
1865
  // Pass 2: Match "unknown_function" orphans
1774
1866
  if (!matchedId) {
1775
1867
  for (const [orphanId, orphanResp] of collectedResponses) {
1776
- if (orphanResp.functionResponse?.name === "unknown_function") {
1868
+ if (orphanResp.functionResponse?.name === 'unknown_function') {
1777
1869
  matchedId = orphanId;
1778
1870
  break;
1779
1871
  }
@@ -1788,10 +1880,11 @@ export function fixToolResponseGrouping(contents) {
1788
1880
  collectedResponses.delete(matchedId);
1789
1881
  // Fix the ID and name to match expected
1790
1882
  orphanResp.functionResponse.id = expectedId;
1791
- if (orphanResp.functionResponse.name === "unknown_function" && expectedName) {
1883
+ if (orphanResp.functionResponse.name === 'unknown_function' &&
1884
+ expectedName) {
1792
1885
  orphanResp.functionResponse.name = expectedName;
1793
1886
  }
1794
- log.debug("Auto-repaired tool ID mismatch", {
1887
+ log.debug('Auto-repaired tool ID mismatch', {
1795
1888
  mappedFrom: matchedId,
1796
1889
  mappedTo: expectedId,
1797
1890
  functionName: expectedName,
@@ -1803,18 +1896,18 @@ export function fixToolResponseGrouping(contents) {
1803
1896
  // No responses available - create placeholder
1804
1897
  const placeholder = {
1805
1898
  functionResponse: {
1806
- name: expectedName || "unknown_function",
1899
+ name: expectedName || 'unknown_function',
1807
1900
  response: {
1808
1901
  result: {
1809
- error: "Tool response was lost during context processing. " +
1810
- "This is a recovered placeholder.",
1902
+ error: 'Tool response was lost during context processing. ' +
1903
+ 'This is a recovered placeholder.',
1811
1904
  recovered: true,
1812
1905
  },
1813
1906
  },
1814
1907
  id: expectedId,
1815
1908
  },
1816
1909
  };
1817
- log.debug("Created placeholder response for missing tool", {
1910
+ log.debug('Created placeholder response for missing tool', {
1818
1911
  id: expectedId,
1819
1912
  name: expectedName,
1820
1913
  });
@@ -1825,7 +1918,7 @@ export function fixToolResponseGrouping(contents) {
1825
1918
  // Insert at correct position (after the model message that made the calls)
1826
1919
  newContents.splice(group.insertAfterIdx + 1, 0, {
1827
1920
  parts: groupResponses,
1828
- role: "user",
1921
+ role: 'user',
1829
1922
  });
1830
1923
  }
1831
1924
  }
@@ -1853,8 +1946,8 @@ export function detectToolIdMismatches(contents) {
1853
1946
  }
1854
1947
  const expectedSet = new Set(expectedIds);
1855
1948
  const foundSet = new Set(foundIds);
1856
- const missingIds = expectedIds.filter(id => !foundSet.has(id));
1857
- const orphanIds = foundIds.filter(id => !expectedSet.has(id));
1949
+ const missingIds = expectedIds.filter((id) => !foundSet.has(id));
1950
+ const orphanIds = foundIds.filter((id) => !expectedSet.has(id));
1858
1951
  return {
1859
1952
  hasMismatches: missingIds.length > 0 || orphanIds.length > 0,
1860
1953
  expectedIds,
@@ -1876,10 +1969,10 @@ export function findOrphanedToolUseIds(messages) {
1876
1969
  for (const msg of messages) {
1877
1970
  if (Array.isArray(msg.content)) {
1878
1971
  for (const block of msg.content) {
1879
- if (block.type === "tool_use" && block.id) {
1972
+ if (block.type === 'tool_use' && block.id) {
1880
1973
  toolUseIds.add(block.id);
1881
1974
  }
1882
- if (block.type === "tool_result" && block.tool_use_id) {
1975
+ if (block.type === 'tool_result' && block.tool_use_id) {
1883
1976
  toolResultIds.add(block.tool_use_id);
1884
1977
  }
1885
1978
  }
@@ -1906,10 +1999,13 @@ export function fixClaudeToolPairing(messages) {
1906
1999
  const toolUseMap = new Map();
1907
2000
  for (let i = 0; i < messages.length; i++) {
1908
2001
  const msg = messages[i];
1909
- if (msg.role === "assistant" && Array.isArray(msg.content)) {
2002
+ if (msg.role === 'assistant' && Array.isArray(msg.content)) {
1910
2003
  for (const block of msg.content) {
1911
- if (block.type === "tool_use" && block.id) {
1912
- toolUseMap.set(block.id, { name: block.name || `tool-${toolUseMap.size}`, msgIndex: i });
2004
+ if (block.type === 'tool_use' && block.id) {
2005
+ toolUseMap.set(block.id, {
2006
+ name: block.name || `tool-${toolUseMap.size}`,
2007
+ msgIndex: i,
2008
+ });
1913
2009
  }
1914
2010
  }
1915
2011
  }
@@ -1917,9 +2013,9 @@ export function fixClaudeToolPairing(messages) {
1917
2013
  // 2. Collect all tool_result IDs from user messages
1918
2014
  const toolResultIds = new Set();
1919
2015
  for (const msg of messages) {
1920
- if (msg.role === "user" && Array.isArray(msg.content)) {
2016
+ if (msg.role === 'user' && Array.isArray(msg.content)) {
1921
2017
  for (const block of msg.content) {
1922
- if (block.type === "tool_result" && block.tool_use_id) {
2018
+ if (block.type === 'tool_result' && block.tool_use_id) {
1923
2019
  toolResultIds.add(block.tool_use_id);
1924
2020
  }
1925
2021
  }
@@ -1950,10 +2046,10 @@ export function fixClaudeToolPairing(messages) {
1950
2046
  if (orphansForMsg && orphansForMsg.length > 0) {
1951
2047
  // Check if next message is user with tool_result - if so, merge into it
1952
2048
  const nextMsg = messages[i + 1];
1953
- if (nextMsg?.role === "user" && Array.isArray(nextMsg.content)) {
2049
+ if (nextMsg?.role === 'user' && Array.isArray(nextMsg.content)) {
1954
2050
  // Will be handled when we push nextMsg - add to its content
1955
2051
  const placeholders = orphansForMsg.map((o) => ({
1956
- type: "tool_result",
2052
+ type: 'tool_result',
1957
2053
  tool_use_id: o.id,
1958
2054
  content: `[Tool "${o.name}" execution was cancelled or failed]`,
1959
2055
  is_error: true,
@@ -1964,9 +2060,9 @@ export function fixClaudeToolPairing(messages) {
1964
2060
  else {
1965
2061
  // Inject new user message with placeholder tool_results
1966
2062
  result.push({
1967
- role: "user",
2063
+ role: 'user',
1968
2064
  content: orphansForMsg.map((o) => ({
1969
- type: "tool_result",
2065
+ type: 'tool_result',
1970
2066
  tool_use_id: o.id,
1971
2067
  content: `[Tool "${o.name}" execution was cancelled or failed]`,
1972
2068
  is_error: true,
@@ -1984,17 +2080,19 @@ export function fixClaudeToolPairing(messages) {
1984
2080
  function removeOrphanedToolUse(messages, orphanIds) {
1985
2081
  return messages
1986
2082
  .map((msg) => {
1987
- if (msg.role === "assistant" && Array.isArray(msg.content)) {
2083
+ if (msg.role === 'assistant' && Array.isArray(msg.content)) {
1988
2084
  return {
1989
2085
  ...msg,
1990
- content: msg.content.filter((block) => block.type !== "tool_use" || !orphanIds.has(block.id)),
2086
+ content: msg.content.filter((block) => block.type !== 'tool_use' || !orphanIds.has(block.id)),
1991
2087
  };
1992
2088
  }
1993
2089
  return msg;
1994
2090
  })
1995
2091
  .filter((msg) =>
1996
2092
  // Remove empty assistant messages
1997
- !(msg.role === "assistant" && Array.isArray(msg.content) && msg.content.length === 0));
2093
+ !(msg.role === 'assistant' &&
2094
+ Array.isArray(msg.content) &&
2095
+ msg.content.length === 0));
1998
2096
  }
1999
2097
  /**
2000
2098
  * Validate and fix tool pairing with fallback nuclear option.
@@ -2005,7 +2103,7 @@ export function validateAndFixClaudeToolPairing(messages) {
2005
2103
  return messages;
2006
2104
  }
2007
2105
  // First: Try gentle fix (inject placeholder tool_results)
2008
- let fixed = fixClaudeToolPairing(messages);
2106
+ const fixed = fixClaudeToolPairing(messages);
2009
2107
  // Second: Validate - find any remaining orphans
2010
2108
  const orphanIds = findOrphanedToolUseIds(fixed);
2011
2109
  if (orphanIds.size === 0) {
@@ -2013,7 +2111,7 @@ export function validateAndFixClaudeToolPairing(messages) {
2013
2111
  }
2014
2112
  // Third: Nuclear option - remove orphaned tool_use entirely
2015
2113
  // This should rarely happen, but provides defense in depth
2016
- console.warn("[antigravity] fixClaudeToolPairing left orphans, applying nuclear option", {
2114
+ console.warn('[antigravity] fixClaudeToolPairing left orphans, applying nuclear option', {
2017
2115
  orphanIds: [...orphanIds],
2018
2116
  });
2019
2117
  return removeOrphanedToolUse(fixed, orphanIds);
@@ -2026,12 +2124,12 @@ export function validateAndFixClaudeToolPairing(messages) {
2026
2124
  * Port of LLM-API-Key-Proxy's _format_type_hint()
2027
2125
  */
2028
2126
  function formatTypeHint(propData, depth = 0) {
2029
- const type = propData.type ?? "unknown";
2127
+ const type = propData.type ?? 'unknown';
2030
2128
  // Handle enum values
2031
2129
  if (propData.enum && Array.isArray(propData.enum)) {
2032
2130
  const enumVals = propData.enum;
2033
2131
  if (enumVals.length <= 5) {
2034
- return `string ENUM[${enumVals.map(v => JSON.stringify(v)).join(", ")}]`;
2132
+ return `string ENUM[${enumVals.map((v) => JSON.stringify(v)).join(', ')}]`;
2035
2133
  }
2036
2134
  return `string ENUM[${enumVals.length} options]`;
2037
2135
  }
@@ -2039,37 +2137,37 @@ function formatTypeHint(propData, depth = 0) {
2039
2137
  if (propData.const !== undefined) {
2040
2138
  return `string CONST=${JSON.stringify(propData.const)}`;
2041
2139
  }
2042
- if (type === "array") {
2140
+ if (type === 'array') {
2043
2141
  const items = propData.items;
2044
- if (items && typeof items === "object") {
2045
- const itemType = items.type ?? "unknown";
2046
- if (itemType === "object") {
2142
+ if (items && typeof items === 'object') {
2143
+ const itemType = items.type ?? 'unknown';
2144
+ if (itemType === 'object') {
2047
2145
  const nestedProps = items.properties;
2048
2146
  const nestedReq = items.required ?? [];
2049
2147
  if (nestedProps && depth < 1) {
2050
2148
  const nestedList = Object.entries(nestedProps).map(([n, d]) => {
2051
- const t = d.type ?? "unknown";
2052
- const req = nestedReq.includes(n) ? " REQUIRED" : "";
2149
+ const t = d.type ?? 'unknown';
2150
+ const req = nestedReq.includes(n) ? ' REQUIRED' : '';
2053
2151
  return `${n}: ${t}${req}`;
2054
2152
  });
2055
- return `ARRAY_OF_OBJECTS[${nestedList.join(", ")}]`;
2153
+ return `ARRAY_OF_OBJECTS[${nestedList.join(', ')}]`;
2056
2154
  }
2057
- return "ARRAY_OF_OBJECTS";
2155
+ return 'ARRAY_OF_OBJECTS';
2058
2156
  }
2059
2157
  return `ARRAY_OF_${itemType.toUpperCase()}`;
2060
2158
  }
2061
- return "ARRAY";
2159
+ return 'ARRAY';
2062
2160
  }
2063
- if (type === "object") {
2161
+ if (type === 'object') {
2064
2162
  const nestedProps = propData.properties;
2065
2163
  const nestedReq = propData.required ?? [];
2066
2164
  if (nestedProps && depth < 1) {
2067
2165
  const nestedList = Object.entries(nestedProps).map(([n, d]) => {
2068
- const t = d.type ?? "unknown";
2069
- const req = nestedReq.includes(n) ? " REQUIRED" : "";
2166
+ const t = d.type ?? 'unknown';
2167
+ const req = nestedReq.includes(n) ? ' REQUIRED' : '';
2070
2168
  return `${n}: ${t}${req}`;
2071
2169
  });
2072
- return `object{${nestedList.join(", ")}}`;
2170
+ return `object{${nestedList.join(', ')}}`;
2073
2171
  }
2074
2172
  }
2075
2173
  return type;
@@ -2086,7 +2184,7 @@ function formatTypeHint(propData, depth = 0) {
2086
2184
  * @param promptTemplate - Template for the signature (default: "\\n\\nSTRICT PARAMETERS: {params}.")
2087
2185
  * @returns Modified tools array with signatures injected
2088
2186
  */
2089
- export function injectParameterSignatures(tools, promptTemplate = "\n\n⚠️ STRICT PARAMETERS: {params}.") {
2187
+ export function injectParameterSignatures(tools, promptTemplate = '\n\n⚠️ STRICT PARAMETERS: {params}.') {
2090
2188
  if (!tools || !Array.isArray(tools))
2091
2189
  return tools;
2092
2190
  return tools.map((tool) => {
@@ -2095,7 +2193,7 @@ export function injectParameterSignatures(tools, promptTemplate = "\n\n⚠️ ST
2095
2193
  return tool;
2096
2194
  const newDeclarations = declarations.map((decl) => {
2097
2195
  // Skip if signature already injected (avoids duplicate injection)
2098
- if (decl.description?.includes("STRICT PARAMETERS:")) {
2196
+ if (decl.description?.includes('STRICT PARAMETERS:')) {
2099
2197
  return decl;
2100
2198
  }
2101
2199
  const schema = decl.parameters || decl.parametersJsonSchema;
@@ -2108,12 +2206,12 @@ export function injectParameterSignatures(tools, promptTemplate = "\n\n⚠️ ST
2108
2206
  const paramList = Object.entries(properties).map(([propName, propData]) => {
2109
2207
  const typeHint = formatTypeHint(propData);
2110
2208
  const isRequired = required.includes(propName);
2111
- return `${propName} (${typeHint}${isRequired ? ", REQUIRED" : ""})`;
2209
+ return `${propName} (${typeHint}${isRequired ? ', REQUIRED' : ''})`;
2112
2210
  });
2113
- const sigStr = promptTemplate.replace("{params}", paramList.join(", "));
2211
+ const sigStr = promptTemplate.replace('{params}', paramList.join(', '));
2114
2212
  return {
2115
2213
  ...decl,
2116
- description: (decl.description || "") + sigStr,
2214
+ description: (decl.description || '') + sigStr,
2117
2215
  };
2118
2216
  });
2119
2217
  return { ...tool, functionDeclarations: newDeclarations };
@@ -2131,36 +2229,37 @@ export function injectToolHardeningInstruction(payload, instructionText) {
2131
2229
  return;
2132
2230
  // Skip if instruction already present (avoids duplicate injection)
2133
2231
  const existing = payload.systemInstruction;
2134
- if (existing && typeof existing === "object" && "parts" in existing) {
2232
+ if (existing && typeof existing === 'object' && 'parts' in existing) {
2135
2233
  const parts = existing.parts;
2136
- if (Array.isArray(parts) && parts.some(p => p.text?.includes("CRITICAL TOOL USAGE INSTRUCTIONS"))) {
2234
+ if (Array.isArray(parts) &&
2235
+ parts.some((p) => p.text?.includes('CRITICAL TOOL USAGE INSTRUCTIONS'))) {
2137
2236
  return;
2138
2237
  }
2139
2238
  }
2140
2239
  const instructionPart = { text: instructionText };
2141
2240
  if (payload.systemInstruction) {
2142
- if (existing && typeof existing === "object" && "parts" in existing) {
2241
+ if (existing && typeof existing === 'object' && 'parts' in existing) {
2143
2242
  const parts = existing.parts;
2144
2243
  if (Array.isArray(parts)) {
2145
2244
  parts.push(instructionPart);
2146
2245
  }
2147
2246
  }
2148
- else if (typeof existing === "string") {
2247
+ else if (typeof existing === 'string') {
2149
2248
  payload.systemInstruction = {
2150
- role: "user",
2249
+ role: 'user',
2151
2250
  parts: [{ text: existing }, instructionPart],
2152
2251
  };
2153
2252
  }
2154
2253
  else {
2155
2254
  payload.systemInstruction = {
2156
- role: "user",
2255
+ role: 'user',
2157
2256
  parts: [instructionPart],
2158
2257
  };
2159
2258
  }
2160
2259
  }
2161
2260
  else {
2162
2261
  payload.systemInstruction = {
2163
- role: "user",
2262
+ role: 'user',
2164
2263
  parts: [instructionPart],
2165
2264
  };
2166
2265
  }
@@ -2187,12 +2286,12 @@ export function assignToolIdsToContents(contents) {
2187
2286
  return content;
2188
2287
  }
2189
2288
  const newParts = content.parts.map((part) => {
2190
- if (part && typeof part === "object" && part.functionCall) {
2289
+ if (part && typeof part === 'object' && part.functionCall) {
2191
2290
  const call = { ...part.functionCall };
2192
2291
  if (!call.id) {
2193
2292
  call.id = `tool-call-${++toolCallCounter}`;
2194
2293
  }
2195
- const nameKey = typeof call.name === "string" ? call.name : `tool-${toolCallCounter}`;
2294
+ const nameKey = typeof call.name === 'string' ? call.name : `tool-${toolCallCounter}`;
2196
2295
  const queue = pendingCallIdsByName.get(nameKey) || [];
2197
2296
  queue.push(call.id);
2198
2297
  pendingCallIdsByName.set(nameKey, queue);
@@ -2221,9 +2320,9 @@ export function matchResponseIdsToContents(contents, pendingCallIdsByName) {
2221
2320
  return content;
2222
2321
  }
2223
2322
  const newParts = content.parts.map((part) => {
2224
- if (part && typeof part === "object" && part.functionResponse) {
2323
+ if (part && typeof part === 'object' && part.functionResponse) {
2225
2324
  const resp = { ...part.functionResponse };
2226
- if (!resp.id && typeof resp.name === "string") {
2325
+ if (!resp.id && typeof resp.name === 'string') {
2227
2326
  const queue = pendingCallIdsByName.get(resp.name);
2228
2327
  if (queue && queue.length > 0) {
2229
2328
  resp.id = queue.shift();
@@ -2264,7 +2363,7 @@ export function applyToolPairingFixes(payload, isClaude) {
2264
2363
  // Third pass: fix orphan recovery
2265
2364
  payload.contents = fixToolResponseGrouping(contentsWithMatchedIds);
2266
2365
  contentsFixed = true;
2267
- log.debug("Applied tool pairing fixes to contents[]", {
2366
+ log.debug('Applied tool pairing fixes to contents[]', {
2268
2367
  originalLength: payload.contents.length,
2269
2368
  });
2270
2369
  }
@@ -2272,7 +2371,7 @@ export function applyToolPairingFixes(payload, isClaude) {
2272
2371
  if (Array.isArray(payload.messages)) {
2273
2372
  payload.messages = validateAndFixClaudeToolPairing(payload.messages);
2274
2373
  messagesFixed = true;
2275
- log.debug("Applied tool pairing fixes to messages[]", {
2374
+ log.debug('Applied tool pairing fixes to messages[]', {
2276
2375
  originalLength: payload.messages.length,
2277
2376
  });
2278
2377
  }
@@ -2297,10 +2396,10 @@ export function createSyntheticTextResponse(text, extraHeaders = {}) {
2297
2396
  candidates: [
2298
2397
  {
2299
2398
  content: {
2300
- role: "model",
2399
+ role: 'model',
2301
2400
  parts: [{ text }],
2302
2401
  },
2303
- finishReason: "STOP",
2402
+ finishReason: 'STOP',
2304
2403
  },
2305
2404
  ],
2306
2405
  usageMetadata: {
@@ -2312,17 +2411,17 @@ export function createSyntheticTextResponse(text, extraHeaders = {}) {
2312
2411
  return new Response(`data: ${JSON.stringify(event)}\n\n`, {
2313
2412
  status: 200,
2314
2413
  headers: {
2315
- "Content-Type": "text/event-stream",
2316
- "Cache-Control": "no-cache",
2317
- "Connection": "keep-alive",
2318
- "X-Antigravity-Synthetic": "true",
2414
+ 'Content-Type': 'text/event-stream',
2415
+ 'Cache-Control': 'no-cache',
2416
+ Connection: 'keep-alive',
2417
+ 'X-Antigravity-Synthetic': 'true',
2319
2418
  ...extraHeaders,
2320
2419
  },
2321
2420
  });
2322
2421
  }
2323
- export function createSyntheticErrorResponse(errorMessage, _requestedModel = "unknown") {
2422
+ export function createSyntheticErrorResponse(errorMessage, _requestedModel = 'unknown') {
2324
2423
  return createSyntheticTextResponse(errorMessage, {
2325
- "X-Antigravity-Error-Type": "synthetic_error",
2424
+ 'X-Antigravity-Error-Type': 'synthetic_error',
2326
2425
  });
2327
2426
  }
2328
2427
  //# sourceMappingURL=request-helpers.js.map