opencode-antigravity-auth-tweaked 1.9.4 → 1.9.6

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 (206) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +28 -32
  3. package/dist/index.d.ts +3 -3
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/index.js +2 -2
  6. package/dist/index.js.map +1 -1
  7. package/dist/src/antigravity/oauth.d.ts.map +1 -1
  8. package/dist/src/antigravity/oauth.js +4 -4
  9. package/dist/src/antigravity/oauth.js.map +1 -1
  10. package/dist/src/constants.d.ts +1 -1
  11. package/dist/src/constants.d.ts.map +1 -1
  12. package/dist/src/constants.js +29 -29
  13. package/dist/src/constants.js.map +1 -1
  14. package/dist/src/generated/headers.d.ts +3 -3
  15. package/dist/src/generated/headers.js +3 -3
  16. package/dist/src/generated/headers.js.map +1 -1
  17. package/dist/src/hooks/auto-update-checker/cache.js +1 -1
  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 +2 -2
  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.map +1 -1
  25. package/dist/src/hooks/auto-update-checker/index.d.ts +4 -4
  26. package/dist/src/hooks/auto-update-checker/index.d.ts.map +1 -1
  27. package/dist/src/hooks/auto-update-checker/index.js +6 -6
  28. package/dist/src/hooks/auto-update-checker/index.js.map +1 -1
  29. package/dist/src/hooks/auto-update-checker/logging.js +1 -1
  30. package/dist/src/hooks/auto-update-checker/logging.js.map +1 -1
  31. package/dist/src/hooks/auto-update-checker/types.d.ts.map +1 -1
  32. package/dist/src/plugin/accounts.d.ts +16 -9
  33. package/dist/src/plugin/accounts.d.ts.map +1 -1
  34. package/dist/src/plugin/accounts.js +106 -29
  35. package/dist/src/plugin/accounts.js.map +1 -1
  36. package/dist/src/plugin/auth.d.ts +1 -1
  37. package/dist/src/plugin/auth.d.ts.map +1 -1
  38. package/dist/src/plugin/auth.js.map +1 -1
  39. package/dist/src/plugin/cache/index.d.ts +1 -1
  40. package/dist/src/plugin/cache/index.d.ts.map +1 -1
  41. package/dist/src/plugin/cache/index.js +1 -1
  42. package/dist/src/plugin/cache/index.js.map +1 -1
  43. package/dist/src/plugin/cache/signature-cache.d.ts +1 -1
  44. package/dist/src/plugin/cache/signature-cache.d.ts.map +1 -1
  45. package/dist/src/plugin/cache/signature-cache.js +1 -1
  46. package/dist/src/plugin/cache/signature-cache.js.map +1 -1
  47. package/dist/src/plugin/cache.d.ts +5 -5
  48. package/dist/src/plugin/cache.d.ts.map +1 -1
  49. package/dist/src/plugin/cache.js +3 -3
  50. package/dist/src/plugin/cache.js.map +1 -1
  51. package/dist/src/plugin/cli.d.ts +3 -3
  52. package/dist/src/plugin/cli.d.ts.map +1 -1
  53. package/dist/src/plugin/cli.js +3 -3
  54. package/dist/src/plugin/cli.js.map +1 -1
  55. package/dist/src/plugin/concurrency.d.ts.map +1 -1
  56. package/dist/src/plugin/concurrency.js.map +1 -1
  57. package/dist/src/plugin/config/index.d.ts +4 -4
  58. package/dist/src/plugin/config/index.d.ts.map +1 -1
  59. package/dist/src/plugin/config/index.js +4 -4
  60. package/dist/src/plugin/config/index.js.map +1 -1
  61. package/dist/src/plugin/config/loader.d.ts +1 -1
  62. package/dist/src/plugin/config/loader.d.ts.map +1 -1
  63. package/dist/src/plugin/config/loader.js +3 -3
  64. package/dist/src/plugin/config/loader.js.map +1 -1
  65. package/dist/src/plugin/config/models.d.ts +1 -1
  66. package/dist/src/plugin/config/models.d.ts.map +1 -1
  67. package/dist/src/plugin/config/models.js.map +1 -1
  68. package/dist/src/plugin/config/schema.d.ts +18 -0
  69. package/dist/src/plugin/config/schema.d.ts.map +1 -1
  70. package/dist/src/plugin/config/schema.js +21 -0
  71. package/dist/src/plugin/config/schema.js.map +1 -1
  72. package/dist/src/plugin/config/updater.d.ts.map +1 -1
  73. package/dist/src/plugin/config/updater.js +1 -1
  74. package/dist/src/plugin/config/updater.js.map +1 -1
  75. package/dist/src/plugin/core/streaming/index.d.ts +2 -2
  76. package/dist/src/plugin/core/streaming/index.d.ts.map +1 -1
  77. package/dist/src/plugin/core/streaming/index.js +2 -2
  78. package/dist/src/plugin/core/streaming/index.js.map +1 -1
  79. package/dist/src/plugin/core/streaming/transformer.d.ts +1 -1
  80. package/dist/src/plugin/core/streaming/transformer.d.ts.map +1 -1
  81. package/dist/src/plugin/core/streaming/transformer.js +1 -1
  82. package/dist/src/plugin/core/streaming/transformer.js.map +1 -1
  83. package/dist/src/plugin/core/streaming/types.d.ts.map +1 -1
  84. package/dist/src/plugin/debug.d.ts +1 -1
  85. package/dist/src/plugin/debug.d.ts.map +1 -1
  86. package/dist/src/plugin/debug.js +2 -2
  87. package/dist/src/plugin/debug.js.map +1 -1
  88. package/dist/src/plugin/error-extraction.js +1 -1
  89. package/dist/src/plugin/error-extraction.js.map +1 -1
  90. package/dist/src/plugin/errors.d.ts.map +1 -1
  91. package/dist/src/plugin/errors.js.map +1 -1
  92. package/dist/src/plugin/fingerprint.d.ts.map +1 -1
  93. package/dist/src/plugin/fingerprint.js +1 -1
  94. package/dist/src/plugin/fingerprint.js.map +1 -1
  95. package/dist/src/plugin/image-saver.js.map +1 -1
  96. package/dist/src/plugin/logger.d.ts +4 -4
  97. package/dist/src/plugin/logger.d.ts.map +1 -1
  98. package/dist/src/plugin/logger.js +5 -5
  99. package/dist/src/plugin/logger.js.map +1 -1
  100. package/dist/src/plugin/project.d.ts +1 -1
  101. package/dist/src/plugin/project.d.ts.map +1 -1
  102. package/dist/src/plugin/project.js +4 -4
  103. package/dist/src/plugin/project.js.map +1 -1
  104. package/dist/src/plugin/quota-sync.d.ts +42 -0
  105. package/dist/src/plugin/quota-sync.d.ts.map +1 -0
  106. package/dist/src/plugin/quota-sync.js +170 -0
  107. package/dist/src/plugin/quota-sync.js.map +1 -0
  108. package/dist/src/plugin/quota.d.ts +2 -2
  109. package/dist/src/plugin/quota.d.ts.map +1 -1
  110. package/dist/src/plugin/quota.js +6 -6
  111. package/dist/src/plugin/quota.js.map +1 -1
  112. package/dist/src/plugin/recovery/constants.d.ts.map +1 -1
  113. package/dist/src/plugin/recovery/constants.js.map +1 -1
  114. package/dist/src/plugin/recovery/index.d.ts +3 -3
  115. package/dist/src/plugin/recovery/index.d.ts.map +1 -1
  116. package/dist/src/plugin/recovery/index.js +3 -3
  117. package/dist/src/plugin/recovery/index.js.map +1 -1
  118. package/dist/src/plugin/recovery/storage.d.ts +1 -1
  119. package/dist/src/plugin/recovery/storage.d.ts.map +1 -1
  120. package/dist/src/plugin/recovery/storage.js +1 -1
  121. package/dist/src/plugin/recovery/storage.js.map +1 -1
  122. package/dist/src/plugin/recovery/types.d.ts.map +1 -1
  123. package/dist/src/plugin/recovery.d.ts +3 -3
  124. package/dist/src/plugin/recovery.d.ts.map +1 -1
  125. package/dist/src/plugin/recovery.js +7 -12
  126. package/dist/src/plugin/recovery.js.map +1 -1
  127. package/dist/src/plugin/refresh-queue.d.ts +2 -2
  128. package/dist/src/plugin/refresh-queue.d.ts.map +1 -1
  129. package/dist/src/plugin/refresh-queue.js +2 -2
  130. package/dist/src/plugin/refresh-queue.js.map +1 -1
  131. package/dist/src/plugin/request-helpers.d.ts +121 -15
  132. package/dist/src/plugin/request-helpers.d.ts.map +1 -1
  133. package/dist/src/plugin/request-helpers.js +130 -92
  134. package/dist/src/plugin/request-helpers.js.map +1 -1
  135. package/dist/src/plugin/request.d.ts +19 -18
  136. package/dist/src/plugin/request.d.ts.map +1 -1
  137. package/dist/src/plugin/request.js +80 -78
  138. package/dist/src/plugin/request.js.map +1 -1
  139. package/dist/src/plugin/rotation.d.ts +2 -2
  140. package/dist/src/plugin/rotation.d.ts.map +1 -1
  141. package/dist/src/plugin/rotation.js +7 -5
  142. package/dist/src/plugin/rotation.js.map +1 -1
  143. package/dist/src/plugin/search.d.ts.map +1 -1
  144. package/dist/src/plugin/search.js +2 -2
  145. package/dist/src/plugin/search.js.map +1 -1
  146. package/dist/src/plugin/server.d.ts.map +1 -1
  147. package/dist/src/plugin/server.js +125 -125
  148. package/dist/src/plugin/server.js.map +1 -1
  149. package/dist/src/plugin/sessions.d.ts.map +1 -1
  150. package/dist/src/plugin/sessions.js.map +1 -1
  151. package/dist/src/plugin/storage.d.ts +3 -3
  152. package/dist/src/plugin/storage.d.ts.map +1 -1
  153. package/dist/src/plugin/storage.js +2 -2
  154. package/dist/src/plugin/storage.js.map +1 -1
  155. package/dist/src/plugin/stores/signature-store.d.ts +1 -1
  156. package/dist/src/plugin/stores/signature-store.d.ts.map +1 -1
  157. package/dist/src/plugin/stores/signature-store.js.map +1 -1
  158. package/dist/src/plugin/thinking-recovery.d.ts.map +1 -1
  159. package/dist/src/plugin/thinking-recovery.js.map +1 -1
  160. package/dist/src/plugin/token.d.ts +1 -1
  161. package/dist/src/plugin/token.d.ts.map +1 -1
  162. package/dist/src/plugin/token.js +6 -6
  163. package/dist/src/plugin/token.js.map +1 -1
  164. package/dist/src/plugin/transform/claude.d.ts +1 -1
  165. package/dist/src/plugin/transform/claude.d.ts.map +1 -1
  166. package/dist/src/plugin/transform/claude.js +1 -1
  167. package/dist/src/plugin/transform/claude.js.map +1 -1
  168. package/dist/src/plugin/transform/cross-model-sanitizer.d.ts.map +1 -1
  169. package/dist/src/plugin/transform/cross-model-sanitizer.js +2 -2
  170. package/dist/src/plugin/transform/cross-model-sanitizer.js.map +1 -1
  171. package/dist/src/plugin/transform/gemini.d.ts +1 -1
  172. package/dist/src/plugin/transform/gemini.d.ts.map +1 -1
  173. package/dist/src/plugin/transform/gemini.js.map +1 -1
  174. package/dist/src/plugin/transform/index.d.ts +9 -9
  175. package/dist/src/plugin/transform/index.d.ts.map +1 -1
  176. package/dist/src/plugin/transform/index.js +4 -4
  177. package/dist/src/plugin/transform/index.js.map +1 -1
  178. package/dist/src/plugin/transform/model-resolver.d.ts +1 -1
  179. package/dist/src/plugin/transform/model-resolver.d.ts.map +1 -1
  180. package/dist/src/plugin/transform/model-resolver.js.map +1 -1
  181. package/dist/src/plugin/transform/types.d.ts +1 -1
  182. package/dist/src/plugin/transform/types.d.ts.map +1 -1
  183. package/dist/src/plugin/types.d.ts +1 -1
  184. package/dist/src/plugin/types.d.ts.map +1 -1
  185. package/dist/src/plugin/ui/ansi.d.ts.map +1 -1
  186. package/dist/src/plugin/ui/ansi.js.map +1 -1
  187. package/dist/src/plugin/ui/auth-menu.d.ts +1 -1
  188. package/dist/src/plugin/ui/auth-menu.d.ts.map +1 -1
  189. package/dist/src/plugin/ui/auth-menu.js +4 -4
  190. package/dist/src/plugin/ui/auth-menu.js.map +1 -1
  191. package/dist/src/plugin/ui/confirm.js +1 -1
  192. package/dist/src/plugin/ui/confirm.js.map +1 -1
  193. package/dist/src/plugin/ui/select.d.ts.map +1 -1
  194. package/dist/src/plugin/ui/select.js +1 -1
  195. package/dist/src/plugin/ui/select.js.map +1 -1
  196. package/dist/src/plugin/ui/toast.d.ts +22 -1
  197. package/dist/src/plugin/ui/toast.d.ts.map +1 -1
  198. package/dist/src/plugin/ui/toast.js +59 -5
  199. package/dist/src/plugin/ui/toast.js.map +1 -1
  200. package/dist/src/plugin/version.js +2 -2
  201. package/dist/src/plugin/version.js.map +1 -1
  202. package/dist/src/plugin.d.ts +4 -4
  203. package/dist/src/plugin.d.ts.map +1 -1
  204. package/dist/src/plugin.js +97 -143
  205. package/dist/src/plugin.js.map +1 -1
  206. package/package.json +69 -69
@@ -1,10 +1,10 @@
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";
1
+ import { getKeepThinking } from "./config/index.js";
2
+ import { createLogger } from "./logger.js";
3
+ import { cacheSignature } from "./cache.js";
4
+ import { EMPTY_SCHEMA_PLACEHOLDER_NAME, EMPTY_SCHEMA_PLACEHOLDER_DESCRIPTION, SKIP_THOUGHT_SIGNATURE, } from "../constants.js";
5
+ import { processImageData } from "./image-saver.js";
6
6
  const log = createLogger("request-helpers");
7
- const ANTIGRAVITY_PREVIEW_LINK = "https://goo.gle/enable-preview-features"; // TODO: Update to Antigravity link if available
7
+ const ANTIGRAVITY_PREVIEW_LINK = "https://goo.gle/enable-preview-features"; // Link for enabling preview features
8
8
  // ============================================================================
9
9
  // JSON SCHEMA CLEANING FOR ANTIGRAVITY API
10
10
  // Ported from CLIProxyAPI's CleanJSONSchemaForAntigravity (gemini_schema.go)
@@ -30,10 +30,13 @@ const UNSUPPORTED_KEYWORDS = [
30
30
  * Appends a hint to a schema's description field.
31
31
  */
32
32
  function appendDescriptionHint(schema, hint) {
33
- if (!schema || typeof schema !== "object") {
33
+ if (!schema || typeof schema !== "object" || !hint) {
34
34
  return schema;
35
35
  }
36
36
  const existing = typeof schema.description === "string" ? schema.description : "";
37
+ if (existing.includes(hint)) {
38
+ return schema;
39
+ }
37
40
  const newDescription = existing ? `${existing} (${hint})` : hint;
38
41
  return { ...schema, description: newDescription };
39
42
  }
@@ -242,10 +245,10 @@ function scoreSchemaOption(schema) {
242
245
  }
243
246
  // Any other non-null type
244
247
  if (type && type !== "null") {
245
- return { score: 1, typeName: type };
248
+ return { score: 1, typeName: typeof type === "string" ? type : type[0] || "unknown" };
246
249
  }
247
250
  // Null or no type
248
- return { score: 0, typeName: type || "null" };
251
+ return { score: 0, typeName: (typeof type === "string" ? type : type?.[0]) || "null" };
249
252
  }
250
253
  /**
251
254
  * Checks if an anyOf/oneOf array represents enum choices.
@@ -261,38 +264,48 @@ function tryMergeEnumFromUnion(options) {
261
264
  return null;
262
265
  }
263
266
  const enumValues = [];
267
+ let hasEnumPattern = false;
264
268
  for (const option of options) {
265
269
  if (!option || typeof option !== "object") {
266
- return null;
270
+ continue;
271
+ }
272
+ // Handle nested anyOf/oneOf (recursive)
273
+ if (Array.isArray(option.anyOf)) {
274
+ const nested = tryMergeEnumFromUnion(option.anyOf);
275
+ if (nested) {
276
+ enumValues.push(...nested);
277
+ hasEnumPattern = true;
278
+ }
279
+ continue;
280
+ }
281
+ if (Array.isArray(option.oneOf)) {
282
+ const nested = tryMergeEnumFromUnion(option.oneOf);
283
+ if (nested) {
284
+ enumValues.push(...nested);
285
+ hasEnumPattern = true;
286
+ }
287
+ continue;
267
288
  }
268
289
  // Check for const value
269
290
  if (option.const !== undefined) {
270
291
  enumValues.push(String(option.const));
292
+ hasEnumPattern = true;
271
293
  continue;
272
294
  }
273
- // Check for single-value enum
274
- if (Array.isArray(option.enum) && option.enum.length === 1) {
275
- enumValues.push(String(option.enum[0]));
276
- continue;
277
- }
278
- // Check for multi-value enum (merge all values)
295
+ // Check for enum
279
296
  if (Array.isArray(option.enum) && option.enum.length > 0) {
280
297
  for (const val of option.enum) {
281
298
  enumValues.push(String(val));
282
299
  }
300
+ hasEnumPattern = true;
283
301
  continue;
284
302
  }
285
- // 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) {
287
- return null;
288
- }
289
- // If option has only type (no const/enum), it's not an enum pattern
290
- if (option.type && !option.const && !option.enum) {
291
- return null;
292
- }
293
303
  }
294
- // Only return if we found actual enum values
295
- return enumValues.length > 0 ? enumValues : null;
304
+ // Only return if we found actual enum values and it looks like an enum pattern
305
+ if (enumValues.length > 0 && hasEnumPattern) {
306
+ return Array.from(new Set(enumValues));
307
+ }
308
+ return null;
296
309
  }
297
310
  /**
298
311
  * Phase 2b: Flattens anyOf/oneOf to the best option with type hints.
@@ -331,6 +344,16 @@ function flattenAnyOfOneOf(schema) {
331
344
  if (parentDesc) {
332
345
  result.description = parentDesc;
333
346
  }
347
+ // If any option was null, add nullable hint
348
+ const hasNullOption = options.some(opt => opt && typeof opt === "object" && opt.type === "null");
349
+ if (hasNullOption) {
350
+ result = appendDescriptionHint(result, "nullable");
351
+ }
352
+ // Add enum hint if we just created/merged an enum
353
+ if (mergedEnum.length > 1 && mergedEnum.length <= 10) {
354
+ const vals = mergedEnum.join(", ");
355
+ result = appendDescriptionHint(result, `Allowed: ${vals}`);
356
+ }
334
357
  continue;
335
358
  }
336
359
  // Not an enum pattern - use standard flattening logic
@@ -364,6 +387,10 @@ function flattenAnyOfOneOf(schema) {
364
387
  const uniqueTypes = Array.from(new Set(allTypes));
365
388
  const hint = `Accepts: ${uniqueTypes.join(" | ")}`;
366
389
  selected = appendDescriptionHint(selected, hint);
390
+ // If 'null' was one of the options, add 'nullable' hint explicitly
391
+ if (uniqueTypes.includes("null")) {
392
+ selected = appendDescriptionHint(selected, "nullable");
393
+ }
367
394
  }
368
395
  // Replace result with selected schema, preserving other fields
369
396
  const { [unionKey]: _, description: __, ...rest } = result;
@@ -790,32 +817,34 @@ function isOurCachedSignature(part, sessionId, getCachedSignatureFn) {
790
817
  if (!sessionId || !getCachedSignatureFn) {
791
818
  return false;
792
819
  }
793
- const text = getThinkingText(part);
794
- if (!text) {
820
+ const textContent = getThinkingText(part);
821
+ if (!textContent) {
795
822
  return false;
796
823
  }
797
824
  const partSignature = getSignature(part);
798
825
  if (!partSignature) {
799
826
  return false;
800
827
  }
801
- const cachedSignature = getCachedSignatureFn(sessionId, text);
828
+ const cachedSignature = getCachedSignatureFn(sessionId, textContent);
802
829
  return cachedSignature === partSignature;
803
830
  }
804
831
  /**
805
832
  * Gets the text content from a thinking part.
806
833
  */
807
834
  function getThinkingText(part) {
808
- if (typeof part.text === "string")
809
- return part.text;
810
- if (typeof part.thinking === "string")
811
- return part.thinking;
812
- if (part.text && typeof part.text === "object") {
813
- const maybeText = part.text.text;
835
+ const text = part.text;
836
+ const thinking = part.thinking;
837
+ if (typeof text === "string")
838
+ return text;
839
+ if (typeof thinking === "string")
840
+ return thinking;
841
+ if (text && typeof text === "object") {
842
+ const maybeText = text.text;
814
843
  if (typeof maybeText === "string")
815
844
  return maybeText;
816
845
  }
817
- if (part.thinking && typeof part.thinking === "object") {
818
- const maybeText = part.thinking.text ?? part.thinking.thinking;
846
+ if (thinking && typeof thinking === "object") {
847
+ const maybeText = thinking.text ?? thinking.thinking;
819
848
  if (typeof maybeText === "string")
820
849
  return maybeText;
821
850
  }
@@ -924,12 +953,13 @@ function filterContentArray(contentArray, sessionId, getCachedSignatureFn, isCla
924
953
  filtered.push(item);
925
954
  continue;
926
955
  }
927
- if (isToolBlock(item)) {
956
+ const itemRecord = item;
957
+ if (isToolBlock(itemRecord)) {
928
958
  if (!isClaudeModel) {
929
959
  filtered.push(item);
930
960
  continue;
931
961
  }
932
- const sanitizedToolBlock = { ...item };
962
+ const sanitizedToolBlock = { ...itemRecord };
933
963
  delete sanitizedToolBlock.signature;
934
964
  delete sanitizedToolBlock.thoughtSignature;
935
965
  delete sanitizedToolBlock.thought_signature;
@@ -937,16 +967,16 @@ function filterContentArray(contentArray, sessionId, getCachedSignatureFn, isCla
937
967
  filtered.push(sanitizedToolBlock);
938
968
  continue;
939
969
  }
940
- const isThinking = isThinkingPart(item);
941
- const hasSignature = hasSignatureField(item);
970
+ const isThinking = isThinkingPart(itemRecord);
971
+ const hasSignature = hasSignatureField(itemRecord);
942
972
  if (!isThinking && !hasSignature) {
943
973
  filtered.push(item);
944
974
  continue;
945
975
  }
946
976
  if (isClaudeModel && (isThinking || hasSignature)) {
947
- const thinkingText = getThinkingText(item) || "";
977
+ const thinkingText = getThinkingText(itemRecord) || "";
948
978
  const sentinelPart = {
949
- type: item.type === "redacted_thinking" ? "redacted_thinking" : "thinking",
979
+ type: itemRecord.type === "redacted_thinking" ? "redacted_thinking" : "thinking",
950
980
  thinking: thinkingText,
951
981
  signature: SKIP_THOUGHT_SIGNATURE,
952
982
  };
@@ -960,38 +990,38 @@ function filterContentArray(contentArray, sessionId, getCachedSignatureFn, isCla
960
990
  // its own signatures which are long but invalid for Antigravity.
961
991
  if (isLastAssistantMessage && (isThinking || hasSignature)) {
962
992
  // First check if it's our cached signature
963
- if (isOurCachedSignature(item, sessionId, getCachedSignatureFn)) {
964
- const sanitized = sanitizeThinkingPart(item);
993
+ if (isOurCachedSignature(itemRecord, sessionId, getCachedSignatureFn)) {
994
+ const sanitized = sanitizeThinkingPart(itemRecord);
965
995
  if (sanitized)
966
996
  filtered.push(sanitized);
967
997
  continue;
968
998
  }
969
999
  // Not our signature (or no signature) - inject sentinel
970
- const thinkingText = getThinkingText(item) || "";
971
- const existingSignature = item.signature || item.thoughtSignature;
1000
+ const thinkingText = getThinkingText(itemRecord) || "";
1001
+ const existingSignature = itemRecord.signature || itemRecord.thoughtSignature;
972
1002
  const signatureInfo = existingSignature ? `foreign signature (${String(existingSignature).length} chars)` : "no signature";
973
1003
  log.debug(`Injecting sentinel for last-message thinking block with ${signatureInfo}`);
974
1004
  const sentinelPart = {
975
- type: item.type || "thinking",
1005
+ type: itemRecord.type || "thinking",
976
1006
  thinking: thinkingText,
977
1007
  signature: SKIP_THOUGHT_SIGNATURE,
978
1008
  };
979
1009
  filtered.push(sentinelPart);
980
1010
  continue;
981
1011
  }
982
- if (isOurCachedSignature(item, sessionId, getCachedSignatureFn)) {
983
- const sanitized = sanitizeThinkingPart(item);
1012
+ if (isOurCachedSignature(itemRecord, sessionId, getCachedSignatureFn)) {
1013
+ const sanitized = sanitizeThinkingPart(itemRecord);
984
1014
  if (sanitized)
985
1015
  filtered.push(sanitized);
986
1016
  continue;
987
1017
  }
988
1018
  if (sessionId && getCachedSignatureFn) {
989
- const text = getThinkingText(item);
990
- if (text) {
991
- const cachedSignature = getCachedSignatureFn(sessionId, text);
1019
+ const textContent = getThinkingText(itemRecord);
1020
+ if (textContent) {
1021
+ const cachedSignature = getCachedSignatureFn(sessionId, textContent);
992
1022
  if (cachedSignature && cachedSignature.length >= 50) {
993
- const restoredPart = { ...item };
994
- if (item.thought === true) {
1023
+ const restoredPart = { ...itemRecord };
1024
+ if (itemRecord.thought === true) {
995
1025
  restoredPart.thoughtSignature = cachedSignature;
996
1026
  }
997
1027
  else {
@@ -1029,11 +1059,12 @@ export function filterUnsignedThinkingBlocks(contents, sessionId, getCachedSigna
1029
1059
  : filteredParts;
1030
1060
  return { ...content, parts: trimmedParts };
1031
1061
  }
1032
- if (Array.isArray(content.content)) {
1062
+ const contentAsAny = content;
1063
+ if (Array.isArray(contentAsAny.content)) {
1033
1064
  const isAssistantRole = content.role === "assistant";
1034
1065
  const isLastAssistantContent = idx === lastAssistantIdx ||
1035
1066
  (isAssistantRole && idx === findLastAssistantIndex(contents, "assistant"));
1036
- const filteredContent = filterContentArray(content.content, sessionId, getCachedSignatureFn, isClaudeModel, isLastAssistantContent);
1067
+ const filteredContent = filterContentArray(contentAsAny.content, sessionId, getCachedSignatureFn, isClaudeModel, isLastAssistantContent);
1037
1068
  const trimmedContent = isAssistantRole && !isClaudeModel
1038
1069
  ? removeTrailingThinkingBlocks(filteredContent, sessionId, getCachedSignatureFn)
1039
1070
  : filteredContent;
@@ -1109,9 +1140,9 @@ function transformGeminiCandidate(candidate) {
1109
1140
  }
1110
1141
  // Handle Gemini-style: thought: true
1111
1142
  if (part.thought === true) {
1112
- const thinkingText = part.text || "";
1143
+ const thinkingText = getThinkingText(part);
1113
1144
  thinkingTexts.push(thinkingText);
1114
- const transformed = { ...part, type: "reasoning" };
1145
+ const transformed = { ...part, type: "reasoning", text: thinkingText };
1115
1146
  if (part.cache_control)
1116
1147
  transformed.cache_control = part.cache_control;
1117
1148
  // Convert signature to providerMetadata format for OpenCode
@@ -1127,7 +1158,7 @@ function transformGeminiCandidate(candidate) {
1127
1158
  }
1128
1159
  // Handle Anthropic-style in candidates: type: "thinking"
1129
1160
  if (part.type === "thinking") {
1130
- const thinkingText = part.thinking || part.text || "";
1161
+ const thinkingText = getThinkingText(part);
1131
1162
  thinkingTexts.push(thinkingText);
1132
1163
  const transformed = {
1133
1164
  ...part,
@@ -1199,7 +1230,7 @@ export function transformThinkingParts(response) {
1199
1230
  const transformedContent = [];
1200
1231
  for (const block of resp.content) {
1201
1232
  if (block && typeof block === "object" && block.type === "thinking") {
1202
- const thinkingText = block.thinking || block.text || "";
1233
+ const thinkingText = getThinkingText(block);
1203
1234
  reasoningTexts.push(thinkingText);
1204
1235
  const transformed = {
1205
1236
  ...block,
@@ -1327,7 +1358,7 @@ export function rewriteAntigravityPreviewAccessError(body, status, requestedMode
1327
1358
  if (!needsPreviewAccessOverride(status, body, requestedModel)) {
1328
1359
  return null;
1329
1360
  }
1330
- const error = body.error ?? {};
1361
+ const error = (body.error ?? {});
1331
1362
  const trimmedMessage = typeof error.message === "string" ? error.message.trim() : "";
1332
1363
  const messagePrefix = trimmedMessage.length > 0
1333
1364
  ? trimmedMessage
@@ -1349,7 +1380,7 @@ function needsPreviewAccessOverride(status, body, requestedModel) {
1349
1380
  return true;
1350
1381
  }
1351
1382
  const errorMessage = typeof body.error?.message === "string" ? body.error.message : "";
1352
- return isAntigravityModel(errorMessage);
1383
+ return isAntigravityModel(errorMessage || undefined);
1353
1384
  }
1354
1385
  function isAntigravityModel(target) {
1355
1386
  if (!target) {
@@ -1575,13 +1606,18 @@ export function recursivelyParseJsonStrings(obj, skipParseKeys = SKIP_PARSE_KEYS
1575
1606
  return obj;
1576
1607
  }
1577
1608
  const stripped = obj.trim();
1578
- // Check if string contains control character escape sequences
1579
- // that need unescaping (\\n, \\t but NOT \\" or \\\\)
1580
- const hasControlCharEscapes = obj.includes("\\n") || obj.includes("\\t");
1609
+ // Check if string contains control character escape sequences that need unescaping
1610
+ // (e.g. \n, \t, \r, \b, \f, \uXXXX)
1611
+ const hasControlCharEscapes = /\\[nrtbf]/.test(obj) || /\\u[0-9a-fA-F]{4}/.test(obj);
1581
1612
  const hasIntentionalEscapes = obj.includes('\\"') || obj.includes("\\\\");
1582
1613
  if (hasControlCharEscapes && !hasIntentionalEscapes) {
1583
- const unescaped = safeJsonParse(`"${obj}"`, null);
1584
- if (unescaped !== null) {
1614
+ // Robust unescaping by wrapping in a JSON object property.
1615
+ // We must escape literal double quotes and real control characters first.
1616
+ const escaped = obj
1617
+ .replace(/"/g, '\\"')
1618
+ .replace(/[\u0000-\u001f]/g, (c) => `\\u${c.charCodeAt(0).toString(16).padStart(4, '0')}`);
1619
+ const unescaped = safeJsonParse(`{"v":"${escaped}"}`, null)?.v;
1620
+ if (unescaped !== undefined && unescaped !== null) {
1585
1621
  return unescaped;
1586
1622
  }
1587
1623
  }
@@ -1658,7 +1694,7 @@ export function fixToolResponseGrouping(contents) {
1658
1694
  const role = content.role;
1659
1695
  const parts = content.parts || [];
1660
1696
  // Check if this is a tool response message
1661
- const responseParts = parts.filter((p) => p?.functionResponse);
1697
+ const responseParts = parts.filter((p) => !!p?.functionResponse);
1662
1698
  if (responseParts.length > 0) {
1663
1699
  // Collect responses by ID (skip duplicates)
1664
1700
  for (const resp of responseParts) {
@@ -1686,7 +1722,7 @@ export function fixToolResponseGrouping(contents) {
1686
1722
  }
1687
1723
  if (role === "model") {
1688
1724
  // Check for function calls in this model message
1689
- const funcCalls = parts.filter((p) => p?.functionCall);
1725
+ const funcCalls = parts.filter((p) => !!p?.functionCall);
1690
1726
  newContents.push(content);
1691
1727
  if (funcCalls.length > 0) {
1692
1728
  const callIds = funcCalls
@@ -1748,9 +1784,11 @@ export function fixToolResponseGrouping(contents) {
1748
1784
  const orphanResp = collectedResponses.get(matchedId);
1749
1785
  collectedResponses.delete(matchedId);
1750
1786
  // Fix the ID and name to match expected
1751
- orphanResp.functionResponse.id = expectedId;
1752
- if (orphanResp.functionResponse.name === "unknown_function" && expectedName) {
1753
- orphanResp.functionResponse.name = expectedName;
1787
+ if (orphanResp.functionResponse) {
1788
+ orphanResp.functionResponse.id = expectedId;
1789
+ if (orphanResp.functionResponse.name === "unknown_function" && expectedName) {
1790
+ orphanResp.functionResponse.name = expectedName;
1791
+ }
1754
1792
  }
1755
1793
  log.debug("Auto-repaired tool ID mismatch", {
1756
1794
  mappedFrom: matchedId,
@@ -2059,7 +2097,7 @@ export function injectParameterSignatures(tools, promptTemplate = "\n\n⚠️ ST
2059
2097
  if (decl.description?.includes("STRICT PARAMETERS:")) {
2060
2098
  return decl;
2061
2099
  }
2062
- const schema = decl.parameters || decl.parametersJsonSchema;
2100
+ const schema = (decl.parameters || decl.parametersJsonSchema);
2063
2101
  if (!schema)
2064
2102
  return decl;
2065
2103
  const required = schema.required ?? [];
@@ -2262,7 +2300,7 @@ export function createSyntheticErrorResponse(errorMessage, requestedModel = "unk
2262
2300
  // Build Claude SSE events that represent a complete message with error text
2263
2301
  const events = [];
2264
2302
  // 1. message_start event
2265
- events.push(`event: message_start
2303
+ events.push(`event: message_start
2266
2304
  data: ${JSON.stringify({
2267
2305
  type: "message_start",
2268
2306
  message: {
@@ -2275,48 +2313,48 @@ data: ${JSON.stringify({
2275
2313
  stop_sequence: null,
2276
2314
  usage: { input_tokens: 0, output_tokens: 0 },
2277
2315
  },
2278
- })}
2279
-
2316
+ })}
2317
+
2280
2318
  `);
2281
2319
  // 2. content_block_start event
2282
- events.push(`event: content_block_start
2320
+ events.push(`event: content_block_start
2283
2321
  data: ${JSON.stringify({
2284
2322
  type: "content_block_start",
2285
2323
  index: 0,
2286
2324
  content_block: { type: "text", text: "" },
2287
- })}
2288
-
2325
+ })}
2326
+
2289
2327
  `);
2290
2328
  // 3. content_block_delta event with the error message
2291
- events.push(`event: content_block_delta
2329
+ events.push(`event: content_block_delta
2292
2330
  data: ${JSON.stringify({
2293
2331
  type: "content_block_delta",
2294
2332
  index: 0,
2295
2333
  delta: { type: "text_delta", text: errorMessage },
2296
- })}
2297
-
2334
+ })}
2335
+
2298
2336
  `);
2299
2337
  // 4. content_block_stop event
2300
- events.push(`event: content_block_stop
2338
+ events.push(`event: content_block_stop
2301
2339
  data: ${JSON.stringify({
2302
2340
  type: "content_block_stop",
2303
2341
  index: 0,
2304
- })}
2305
-
2342
+ })}
2343
+
2306
2344
  `);
2307
2345
  // 5. message_delta event (end_turn)
2308
- events.push(`event: message_delta
2346
+ events.push(`event: message_delta
2309
2347
  data: ${JSON.stringify({
2310
2348
  type: "message_delta",
2311
2349
  delta: { stop_reason: "end_turn", stop_sequence: null },
2312
2350
  usage: { output_tokens: Math.ceil(errorMessage.length / 4) },
2313
- })}
2314
-
2351
+ })}
2352
+
2315
2353
  `);
2316
2354
  // 6. message_stop event
2317
- events.push(`event: message_stop
2318
- data: ${JSON.stringify({ type: "message_stop" })}
2319
-
2355
+ events.push(`event: message_stop
2356
+ data: ${JSON.stringify({ type: "message_stop" })}
2357
+
2320
2358
  `);
2321
2359
  const body = events.join("");
2322
2360
  return new Response(body, {