@bitkyc08/opencodex 2.24.2 → 2.25.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.
- package/gui/dist/assets/{index-DW-DYWmz.js → index-DxJ7kXj9.js} +1 -1
- package/gui/dist/index.html +1 -1
- package/package.json +1 -1
- package/src/adapters/anthropic.ts +42 -0
- package/src/adapters/client-fingerprint.ts +9 -5
- package/src/adapters/cline-pass-deepseek-v4-tool-replay.ts +69 -0
- package/src/adapters/command-code.ts +17 -0
- package/src/adapters/cursor/cursor-errors.ts +49 -0
- package/src/adapters/cursor/live-models.ts +36 -2
- package/src/adapters/cursor/live-transport.ts +55 -4
- package/src/adapters/cursor/native-exec.ts +9 -0
- package/src/adapters/cursor/protobuf-request.ts +160 -9
- package/src/adapters/cursor/request-builder.ts +9 -1
- package/src/adapters/cursor/tool-definitions.ts +7 -2
- package/src/adapters/google-antigravity-wire.ts +1 -1
- package/src/adapters/google.ts +30 -12
- package/src/adapters/openai-responses-url.ts +5 -3
- package/src/adapters/registry.ts +3 -1
- package/src/adapters/tool-catalog-nudge.ts +76 -9
- package/src/bridge.ts +53 -9
- package/src/codex/app-server-processes.ts +69 -35
- package/src/codex/catalog/provider-fetch.ts +5 -1
- package/src/config.ts +1 -0
- package/src/generated/compatibility-version.json +40 -32
- package/src/lib/windows-elevation.ts +8 -2
- package/src/oauth/google-antigravity.ts +7 -2
- package/src/providers/antigravity-models.ts +126 -17
- package/src/providers/derive.ts +11 -1
- package/src/responses/parser.ts +4 -0
- package/src/responses/reasoning-replay-cache.ts +16 -1
- package/src/responses/thought-signature-replay.ts +17 -1
- package/src/responses/truncated-stop-reason.ts +60 -0
- package/src/router.ts +2 -10
- package/src/server/management/provider-routes.ts +22 -0
- package/src/server/request-log.ts +11 -3
- package/src/server/responses/core.ts +2 -0
- package/src/types.ts +13 -1
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
},
|
|
11
11
|
{
|
|
12
12
|
"path": "package.json",
|
|
13
|
-
"sha256": "
|
|
13
|
+
"sha256": "94bdcc17454ccace4e7e201babb428a1c187fe748194ff6a837df22dfe36cd50"
|
|
14
14
|
},
|
|
15
15
|
{
|
|
16
16
|
"path": "scripts/model-metadata.source.json",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
},
|
|
35
35
|
{
|
|
36
36
|
"path": "src/adapters/anthropic.ts",
|
|
37
|
-
"sha256": "
|
|
37
|
+
"sha256": "afd6f5ef9fab45811c67067bdb6731fc8efa3abb7bc2a7bee109445ca9c06467"
|
|
38
38
|
},
|
|
39
39
|
{
|
|
40
40
|
"path": "src/adapters/azure.ts",
|
|
@@ -46,11 +46,15 @@
|
|
|
46
46
|
},
|
|
47
47
|
{
|
|
48
48
|
"path": "src/adapters/client-fingerprint.ts",
|
|
49
|
-
"sha256": "
|
|
49
|
+
"sha256": "70c6e0bf49d942e352396bd6c2983a1456b6ee96497537f4175674e99627223b"
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"path": "src/adapters/cline-pass-deepseek-v4-tool-replay.ts",
|
|
53
|
+
"sha256": "da664327db4e0bae8ab689230deec415ad3f6d0f18c596dcc5b94c8a8d08a345"
|
|
50
54
|
},
|
|
51
55
|
{
|
|
52
56
|
"path": "src/adapters/command-code.ts",
|
|
53
|
-
"sha256": "
|
|
57
|
+
"sha256": "9b4a9eb9ab8c37541d0478ee50d28ea94b9dee127f75fbc85004ca264af67aaa"
|
|
54
58
|
},
|
|
55
59
|
{
|
|
56
60
|
"path": "src/adapters/cursor.ts",
|
|
@@ -66,7 +70,7 @@
|
|
|
66
70
|
},
|
|
67
71
|
{
|
|
68
72
|
"path": "src/adapters/cursor/cursor-errors.ts",
|
|
69
|
-
"sha256": "
|
|
73
|
+
"sha256": "aa27cf53056f48c4ed4ccc2262d5a84c0b96b79a3a77db5be7ca27256dfba9c4"
|
|
70
74
|
},
|
|
71
75
|
{
|
|
72
76
|
"path": "src/adapters/cursor/discovery.ts",
|
|
@@ -94,7 +98,7 @@
|
|
|
94
98
|
},
|
|
95
99
|
{
|
|
96
100
|
"path": "src/adapters/cursor/live-models.ts",
|
|
97
|
-
"sha256": "
|
|
101
|
+
"sha256": "d1ded09df979a490d7b4fb2afb87829561fbc021bdc6f67ad0d122febd9b21e4"
|
|
98
102
|
},
|
|
99
103
|
{
|
|
100
104
|
"path": "src/adapters/cursor/live-smoke-gate.ts",
|
|
@@ -102,7 +106,7 @@
|
|
|
102
106
|
},
|
|
103
107
|
{
|
|
104
108
|
"path": "src/adapters/cursor/live-transport.ts",
|
|
105
|
-
"sha256": "
|
|
109
|
+
"sha256": "c614a08f47c3a71d443484002a978a67afb2169a2eeae540291fcc383ff2a969"
|
|
106
110
|
},
|
|
107
111
|
{
|
|
108
112
|
"path": "src/adapters/cursor/mcp-config.ts",
|
|
@@ -146,7 +150,7 @@
|
|
|
146
150
|
},
|
|
147
151
|
{
|
|
148
152
|
"path": "src/adapters/cursor/native-exec.ts",
|
|
149
|
-
"sha256": "
|
|
153
|
+
"sha256": "3824d4ad75f039019fff8749900cc0b2daff6de0c41bb7a64f76eb5e57dd25a6"
|
|
150
154
|
},
|
|
151
155
|
{
|
|
152
156
|
"path": "src/adapters/cursor/protobuf-events.ts",
|
|
@@ -154,11 +158,11 @@
|
|
|
154
158
|
},
|
|
155
159
|
{
|
|
156
160
|
"path": "src/adapters/cursor/protobuf-request.ts",
|
|
157
|
-
"sha256": "
|
|
161
|
+
"sha256": "28e352e4b0080fc09508bf87cce884ecbecb9d1f414e343a9068145affd223d9"
|
|
158
162
|
},
|
|
159
163
|
{
|
|
160
164
|
"path": "src/adapters/cursor/request-builder.ts",
|
|
161
|
-
"sha256": "
|
|
165
|
+
"sha256": "ecfed9de726cd21126f3a90dac958bd8bba6d9feee5cb48966d3c3cf274b31fd"
|
|
162
166
|
},
|
|
163
167
|
{
|
|
164
168
|
"path": "src/adapters/cursor/thread-continuity.ts",
|
|
@@ -166,7 +170,7 @@
|
|
|
166
170
|
},
|
|
167
171
|
{
|
|
168
172
|
"path": "src/adapters/cursor/tool-definitions.ts",
|
|
169
|
-
"sha256": "
|
|
173
|
+
"sha256": "632535cff0fb7f893b76631344129d13e45aa40c8e3e062ab0010c57e24448e9"
|
|
170
174
|
},
|
|
171
175
|
{
|
|
172
176
|
"path": "src/adapters/cursor/transport-retry.ts",
|
|
@@ -186,7 +190,7 @@
|
|
|
186
190
|
},
|
|
187
191
|
{
|
|
188
192
|
"path": "src/adapters/google-antigravity-wire.ts",
|
|
189
|
-
"sha256": "
|
|
193
|
+
"sha256": "671fc197b9ab46800b64a4d51dec8b80c82e9cf841bb2c244f1087a8de592009"
|
|
190
194
|
},
|
|
191
195
|
{
|
|
192
196
|
"path": "src/adapters/google-errors.ts",
|
|
@@ -210,7 +214,7 @@
|
|
|
210
214
|
},
|
|
211
215
|
{
|
|
212
216
|
"path": "src/adapters/google.ts",
|
|
213
|
-
"sha256": "
|
|
217
|
+
"sha256": "e87a1a968d8cb8e2d20e2ca27a6168f4e97b215ca1c9ef3ac46d907c78e760b5"
|
|
214
218
|
},
|
|
215
219
|
{
|
|
216
220
|
"path": "src/adapters/identity.ts",
|
|
@@ -278,7 +282,7 @@
|
|
|
278
282
|
},
|
|
279
283
|
{
|
|
280
284
|
"path": "src/adapters/openai-responses-url.ts",
|
|
281
|
-
"sha256": "
|
|
285
|
+
"sha256": "ff38228d2033b9f73dbb011b1d5eb3ac09795519ae8b57958d7d8f6253b4d5e4"
|
|
282
286
|
},
|
|
283
287
|
{
|
|
284
288
|
"path": "src/adapters/openai-responses.ts",
|
|
@@ -286,7 +290,7 @@
|
|
|
286
290
|
},
|
|
287
291
|
{
|
|
288
292
|
"path": "src/adapters/registry.ts",
|
|
289
|
-
"sha256": "
|
|
293
|
+
"sha256": "74cef1012f4b481109d1ec5119d49c7634237166f5e73424399feada3d03c963"
|
|
290
294
|
},
|
|
291
295
|
{
|
|
292
296
|
"path": "src/adapters/responses-tool-schema.ts",
|
|
@@ -302,7 +306,7 @@
|
|
|
302
306
|
},
|
|
303
307
|
{
|
|
304
308
|
"path": "src/adapters/tool-catalog-nudge.ts",
|
|
305
|
-
"sha256": "
|
|
309
|
+
"sha256": "9750e8b4ce000ac452482141bfe27add3577341cc30d1403c05a509bee11044c"
|
|
306
310
|
},
|
|
307
311
|
{
|
|
308
312
|
"path": "src/adapters/upstream-http-error.ts",
|
|
@@ -310,7 +314,7 @@
|
|
|
310
314
|
},
|
|
311
315
|
{
|
|
312
316
|
"path": "src/bridge.ts",
|
|
313
|
-
"sha256": "
|
|
317
|
+
"sha256": "5bbfd25c2778989f47c422e57d550b46a6570f9d599e8eee8b189c86fd0cb70c"
|
|
314
318
|
},
|
|
315
319
|
{
|
|
316
320
|
"path": "src/chat/inbound.ts",
|
|
@@ -626,7 +630,7 @@
|
|
|
626
630
|
},
|
|
627
631
|
{
|
|
628
632
|
"path": "src/codex/app-server-processes.ts",
|
|
629
|
-
"sha256": "
|
|
633
|
+
"sha256": "0218c4e432ad02a814d818e04fc5ba8c36864f8fcfd592ef674f9c476e56cb77"
|
|
630
634
|
},
|
|
631
635
|
{
|
|
632
636
|
"path": "src/codex/app-server-restart-service.ts",
|
|
@@ -702,7 +706,7 @@
|
|
|
702
706
|
},
|
|
703
707
|
{
|
|
704
708
|
"path": "src/codex/catalog/provider-fetch.ts",
|
|
705
|
-
"sha256": "
|
|
709
|
+
"sha256": "d800963913619d3e02db4fb616795cac93c336ac18a18c6e24e873e71a6d2255"
|
|
706
710
|
},
|
|
707
711
|
{
|
|
708
712
|
"path": "src/codex/catalog/sync.ts",
|
|
@@ -1022,7 +1026,7 @@
|
|
|
1022
1026
|
},
|
|
1023
1027
|
{
|
|
1024
1028
|
"path": "src/config.ts",
|
|
1025
|
-
"sha256": "
|
|
1029
|
+
"sha256": "2297577079aed2e89e4603050402629fea2df094978ff24c0db5102ca8da91ae"
|
|
1026
1030
|
},
|
|
1027
1031
|
{
|
|
1028
1032
|
"path": "src/generated/model-metadata.ts",
|
|
@@ -1854,7 +1858,7 @@
|
|
|
1854
1858
|
},
|
|
1855
1859
|
{
|
|
1856
1860
|
"path": "src/lib/windows-elevation.ts",
|
|
1857
|
-
"sha256": "
|
|
1861
|
+
"sha256": "168ec95934c25036ec9056f83f89427a82ee2bcd83d098bd4419fcb27051e4ec"
|
|
1858
1862
|
},
|
|
1859
1863
|
{
|
|
1860
1864
|
"path": "src/lib/windows-secret-acl.ts",
|
|
@@ -1926,7 +1930,7 @@
|
|
|
1926
1930
|
},
|
|
1927
1931
|
{
|
|
1928
1932
|
"path": "src/oauth/google-antigravity.ts",
|
|
1929
|
-
"sha256": "
|
|
1933
|
+
"sha256": "ca475ef54f4ed2a36734b560fd29686a33dd11aa45643fe36a9fd3c92c1a6678"
|
|
1930
1934
|
},
|
|
1931
1935
|
{
|
|
1932
1936
|
"path": "src/oauth/health.ts",
|
|
@@ -2002,7 +2006,7 @@
|
|
|
2002
2006
|
},
|
|
2003
2007
|
{
|
|
2004
2008
|
"path": "src/providers/antigravity-models.ts",
|
|
2005
|
-
"sha256": "
|
|
2009
|
+
"sha256": "3b70505caffbf4b42a1574f8824aa3250d3caee5db820f45b45945381dd0298d"
|
|
2006
2010
|
},
|
|
2007
2011
|
{
|
|
2008
2012
|
"path": "src/providers/api-keys.ts",
|
|
@@ -2026,7 +2030,7 @@
|
|
|
2026
2030
|
},
|
|
2027
2031
|
{
|
|
2028
2032
|
"path": "src/providers/derive.ts",
|
|
2029
|
-
"sha256": "
|
|
2033
|
+
"sha256": "babec953990d4045c3861c102a4ed3e2c4654b03b6d707d179bfeefeefd5e9c8"
|
|
2030
2034
|
},
|
|
2031
2035
|
{
|
|
2032
2036
|
"path": "src/providers/free-directory.ts",
|
|
@@ -2142,7 +2146,7 @@
|
|
|
2142
2146
|
},
|
|
2143
2147
|
{
|
|
2144
2148
|
"path": "src/responses/parser.ts",
|
|
2145
|
-
"sha256": "
|
|
2149
|
+
"sha256": "f84fcb37def007781eb71081d3148f4b0f72eca6aebcea7e7a1a67808d014d69"
|
|
2146
2150
|
},
|
|
2147
2151
|
{
|
|
2148
2152
|
"path": "src/responses/provider-opaque-metadata.ts",
|
|
@@ -2154,7 +2158,7 @@
|
|
|
2154
2158
|
},
|
|
2155
2159
|
{
|
|
2156
2160
|
"path": "src/responses/reasoning-replay-cache.ts",
|
|
2157
|
-
"sha256": "
|
|
2161
|
+
"sha256": "c81d1e2173c4c48215468989dafa4ec74a9a01ab1bbbb4556d5d25ccf63739d3"
|
|
2158
2162
|
},
|
|
2159
2163
|
{
|
|
2160
2164
|
"path": "src/responses/schema.ts",
|
|
@@ -2170,15 +2174,19 @@
|
|
|
2170
2174
|
},
|
|
2171
2175
|
{
|
|
2172
2176
|
"path": "src/responses/thought-signature-replay.ts",
|
|
2173
|
-
"sha256": "
|
|
2177
|
+
"sha256": "dc2464036c9d0c78764ac7b2e97e86b77449dd31e9f98cf0c29b5a7d60134976"
|
|
2174
2178
|
},
|
|
2175
2179
|
{
|
|
2176
2180
|
"path": "src/responses/tool-groups.ts",
|
|
2177
2181
|
"sha256": "b2750b33ec7bb5a7f76f27584bf99372fac4f253dd287849b2f3f9821db574cd"
|
|
2178
2182
|
},
|
|
2183
|
+
{
|
|
2184
|
+
"path": "src/responses/truncated-stop-reason.ts",
|
|
2185
|
+
"sha256": "44a1876c045a63f9275410fb9169d2c47ce0c1de309e9cc00a0f51c72698a6dd"
|
|
2186
|
+
},
|
|
2179
2187
|
{
|
|
2180
2188
|
"path": "src/router.ts",
|
|
2181
|
-
"sha256": "
|
|
2189
|
+
"sha256": "26a672d4df978dd7c9764d7533ccc54a9bded6daf4a90fa3ebf41e126d106f67"
|
|
2182
2190
|
},
|
|
2183
2191
|
{
|
|
2184
2192
|
"path": "src/routing/analytics.ts",
|
|
@@ -2422,7 +2430,7 @@
|
|
|
2422
2430
|
},
|
|
2423
2431
|
{
|
|
2424
2432
|
"path": "src/server/management/provider-routes.ts",
|
|
2425
|
-
"sha256": "
|
|
2433
|
+
"sha256": "1a2217a7cdaee6945ef90221f7b9344fc6d3a04e7750092b6c716bb2acbcef47"
|
|
2426
2434
|
},
|
|
2427
2435
|
{
|
|
2428
2436
|
"path": "src/server/management/request-history-routes.ts",
|
|
@@ -2510,7 +2518,7 @@
|
|
|
2510
2518
|
},
|
|
2511
2519
|
{
|
|
2512
2520
|
"path": "src/server/request-log.ts",
|
|
2513
|
-
"sha256": "
|
|
2521
|
+
"sha256": "17c4594009bbacdd95465933ab48b0a5a31e85d80e16de86a1fd1638b2c46510"
|
|
2514
2522
|
},
|
|
2515
2523
|
{
|
|
2516
2524
|
"path": "src/server/responses-custom-tool-repair.ts",
|
|
@@ -2566,7 +2574,7 @@
|
|
|
2566
2574
|
},
|
|
2567
2575
|
{
|
|
2568
2576
|
"path": "src/server/responses/core.ts",
|
|
2569
|
-
"sha256": "
|
|
2577
|
+
"sha256": "1a2fd4ea5e0b1f9b2208cd0365986a465039f262bfd43f9dca56dc43780e6e8a"
|
|
2570
2578
|
},
|
|
2571
2579
|
{
|
|
2572
2580
|
"path": "src/server/responses/empty-completion-guard.ts",
|
|
@@ -2726,7 +2734,7 @@
|
|
|
2726
2734
|
},
|
|
2727
2735
|
{
|
|
2728
2736
|
"path": "src/types.ts",
|
|
2729
|
-
"sha256": "
|
|
2737
|
+
"sha256": "d740769ad835349fbc1d92d1c4186be92d2dca5d9902d0f9bc3eac251644655e"
|
|
2730
2738
|
},
|
|
2731
2739
|
{
|
|
2732
2740
|
"path": "src/update/badge.ts",
|
|
@@ -640,15 +640,21 @@ export function runWindowsElevatedScheduledTaskRegistration(
|
|
|
640
640
|
xml: string,
|
|
641
641
|
): Promise<number> {
|
|
642
642
|
const xmlBase64 = Buffer.from(xml, "utf16le").toString("base64");
|
|
643
|
+
const powerShellPath = windowsPowerShell();
|
|
644
|
+
const powerShellDirectory = powerShellPath.replace(/[\\/][^\\/]+$/, "");
|
|
645
|
+
const scheduledTasksModule = `${powerShellDirectory}\\Modules\\ScheduledTasks\\ScheduledTasks.psd1`;
|
|
643
646
|
const inner = [
|
|
644
647
|
`$taskName = ${psSingleQuote(taskName)}`,
|
|
645
648
|
`$xmlBase64 = ${psSingleQuote(xmlBase64)}`,
|
|
646
649
|
"$xml = [Text.Encoding]::Unicode.GetString([Convert]::FromBase64String($xmlBase64))",
|
|
647
|
-
|
|
650
|
+
`$module = Microsoft.PowerShell.Core\\Import-Module -Name ${psSingleQuote(scheduledTasksModule)} -PassThru -Force -ErrorAction Stop`,
|
|
651
|
+
"$registerTask = $module.ExportedCommands['Register-ScheduledTask']",
|
|
652
|
+
"if ($null -eq $registerTask) { throw 'Trusted ScheduledTasks module does not export Register-ScheduledTask.' }",
|
|
653
|
+
"& $registerTask -TaskName $taskName -Xml $xml -Force -ErrorAction Stop | Out-Null",
|
|
648
654
|
].join("; ");
|
|
649
655
|
const encodedCommand = Buffer.from(inner, "utf16le").toString("base64");
|
|
650
656
|
const script = [
|
|
651
|
-
`$p = Start-Process -FilePath ${psSingleQuote(
|
|
657
|
+
`$p = Start-Process -FilePath ${psSingleQuote(powerShellPath)}`,
|
|
652
658
|
` -ArgumentList ${psSingleQuote(buildWindowsElevatedArgumentList([
|
|
653
659
|
"-NoProfile",
|
|
654
660
|
"-NonInteractive",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
import { OAuthCallbackFlow, type OAuthCallbackFlowOptions } from "./callback-server";
|
|
13
13
|
import { generatePKCE } from "./pkce";
|
|
14
14
|
import type { OAuthController, OAuthCredentials } from "./types";
|
|
15
|
-
import { antigravityUserAgent, ANTIGRAVITY_GOOG_API_CLIENT_UA } from "../adapters/client-fingerprint";
|
|
15
|
+
import { antigravityUserAgent, ANTIGRAVITY_GOOG_API_CLIENT_UA, ANTIGRAVITY_IDE_VERSION } from "../adapters/client-fingerprint";
|
|
16
16
|
|
|
17
17
|
const CLIENT_ID = process.env.GOOGLE_ANTIGRAVITY_CLIENT_ID
|
|
18
18
|
|| "1071006060591-tmhssin2h21lcre235vtolojh4g403ep.apps.googleusercontent.com";
|
|
@@ -111,7 +111,12 @@ async function onboardProject(accessToken: string, signal?: AbortSignal): Promis
|
|
|
111
111
|
const response = await fetch(`${DAILY_API}/${API_VERSION}:onboardUser`, {
|
|
112
112
|
method: "POST",
|
|
113
113
|
headers: { Authorization: `Bearer ${accessToken}`, Accept: "*/*", "Content-Type": "application/json", "User-Agent": antigravityUserAgent(), "x-goog-api-client": ANTIGRAVITY_GOOG_API_CLIENT_UA },
|
|
114
|
-
|
|
114
|
+
// `ide_version` is a version, not a User-Agent. `antigravityUserAgent()` returns the whole
|
|
115
|
+
// header — `antigravity/ide/2.5.5 (aidev_client; os_type=...; arch=...)` — so onboarding was
|
|
116
|
+
// sending a parenthesized UA string in a field the real client fills with `2.5.5`. It is a
|
|
117
|
+
// fingerprint mismatch rather than a crash, which is why nothing failed: the request still
|
|
118
|
+
// succeeds, it just does not look like Antigravity.
|
|
119
|
+
body: JSON.stringify({ tier_id: "free-tier", metadata: { ide_type: "ANTIGRAVITY", ide_name: "antigravity", ide_version: ANTIGRAVITY_IDE_VERSION } }),
|
|
115
120
|
signal: requestSignal(signal),
|
|
116
121
|
});
|
|
117
122
|
if (!response.ok) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { isValidModelDiscoveryModelId, MODEL_DISCOVERY_MAX_MODELS } from "./model-discovery-limits";
|
|
2
|
+
import { isModelCacheGenerationCurrent } from "../codex/model-cache";
|
|
2
3
|
|
|
3
4
|
// Google Antigravity (Cloud Code Assist) bundled model list.
|
|
4
5
|
//
|
|
@@ -74,8 +75,12 @@ const ANTIGRAVITY_DISCOVERY_EFFORTS = ["low", "medium", "high"] as const;
|
|
|
74
75
|
|
|
75
76
|
function pickerModelIdForDiscoveredWireId(
|
|
76
77
|
wireId: string,
|
|
78
|
+
info: Record<string, unknown>,
|
|
77
79
|
available: ReadonlyMap<string, Record<string, unknown>>,
|
|
78
80
|
): string {
|
|
81
|
+
const displayModelId = antigravityDisplayModelId(info.displayName, wireId);
|
|
82
|
+
if (displayModelId) return displayModelId;
|
|
83
|
+
|
|
79
84
|
const explicitPickerId = Object.hasOwn(ANTIGRAVITY_PICKER_MODEL_BY_WIRE_ID, wireId)
|
|
80
85
|
? ANTIGRAVITY_PICKER_MODEL_BY_WIRE_ID[wireId]
|
|
81
86
|
: undefined;
|
|
@@ -240,6 +245,8 @@ export const ANTIGRAVITY_MODEL_INPUT_MODALITIES: Record<string, string[]> = {
|
|
|
240
245
|
|
|
241
246
|
export interface AntigravityAvailableModel {
|
|
242
247
|
id: string;
|
|
248
|
+
/** CCA model id used by the agent envelope when `id` comes from display metadata. */
|
|
249
|
+
wireModelId: string;
|
|
243
250
|
contextWindow?: number;
|
|
244
251
|
inputModalities?: string[];
|
|
245
252
|
}
|
|
@@ -254,6 +261,100 @@ function antigravityPositiveInteger(value: unknown): number | undefined {
|
|
|
254
261
|
return typeof value === "number" && Number.isSafeInteger(value) && value > 0 ? value : undefined;
|
|
255
262
|
}
|
|
256
263
|
|
|
264
|
+
interface DiscoveredWireModelMapping {
|
|
265
|
+
readonly models: ReadonlyMap<string, string>;
|
|
266
|
+
readonly generation?: { provider: string; cacheGeneration: string };
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
const discoveredWireModelsByBaseUrl = new Map<string, DiscoveredWireModelMapping>();
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Strip trailing slashes without a backtracking regex.
|
|
273
|
+
*
|
|
274
|
+
* `/\/+$/` is polynomial-ReDoS on attacker-influenceable input (CodeQL js/polynomial-redos):
|
|
275
|
+
* a long run of slashes makes the engine retry every suffix. The base URL comes from provider
|
|
276
|
+
* config, which is not hostile in the ordinary case — but "not hostile today" is a property of
|
|
277
|
+
* the caller, not of this function, and a linear scan costs nothing.
|
|
278
|
+
*/
|
|
279
|
+
function stripTrailingSlashes(value: string): string {
|
|
280
|
+
let end = value.length;
|
|
281
|
+
while (end > 0 && value.charCodeAt(end - 1) === 47) end -= 1;
|
|
282
|
+
return end === value.length ? value : value.slice(0, end);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
function antigravityBaseUrlKey(baseUrl: string | undefined): string | undefined {
|
|
286
|
+
if (typeof baseUrl !== "string" || !baseUrl.trim()) return undefined;
|
|
287
|
+
const trimmed = stripTrailingSlashes(baseUrl.trim());
|
|
288
|
+
try {
|
|
289
|
+
const url = new URL(trimmed);
|
|
290
|
+
url.hash = "";
|
|
291
|
+
url.search = "";
|
|
292
|
+
return stripTrailingSlashes(url.toString()).toLowerCase();
|
|
293
|
+
} catch {
|
|
294
|
+
return trimmed.toLowerCase();
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/** Remember the wire ids returned by one live CCA discovery for request routing. */
|
|
299
|
+
export function registerAntigravityDiscoveredWireModels(
|
|
300
|
+
baseUrl: string | undefined,
|
|
301
|
+
models: readonly AntigravityAvailableModel[],
|
|
302
|
+
generation?: { provider: string; cacheGeneration: string },
|
|
303
|
+
): void {
|
|
304
|
+
const key = antigravityBaseUrlKey(baseUrl);
|
|
305
|
+
if (!key) return;
|
|
306
|
+
const wireModels = new Map<string, string>();
|
|
307
|
+
for (const model of models) wireModels.set(model.id, model.wireModelId);
|
|
308
|
+
discoveredWireModelsByBaseUrl.set(key, {
|
|
309
|
+
models: wireModels,
|
|
310
|
+
...(generation ? { generation } : {}),
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
function discoveredAntigravityWireModelId(
|
|
315
|
+
modelId: string,
|
|
316
|
+
baseUrl: string | undefined,
|
|
317
|
+
): string | undefined {
|
|
318
|
+
const key = antigravityBaseUrlKey(baseUrl);
|
|
319
|
+
if (!key) return undefined;
|
|
320
|
+
const mapping = discoveredWireModelsByBaseUrl.get(key);
|
|
321
|
+
if (!mapping) return undefined;
|
|
322
|
+
if (mapping.generation
|
|
323
|
+
&& !isModelCacheGenerationCurrent(mapping.generation.provider, mapping.generation.cacheGeneration)) {
|
|
324
|
+
discoveredWireModelsByBaseUrl.delete(key);
|
|
325
|
+
return undefined;
|
|
326
|
+
}
|
|
327
|
+
return mapping.models.get(modelId);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Convert the CCA display label used by `agy` into its public model selector.
|
|
332
|
+
*
|
|
333
|
+
* The wire id is authoritative for requests, while the label is authoritative for the
|
|
334
|
+
* user-facing selector when Google has renamed or re-tiered a model. Keep both instead
|
|
335
|
+
* of maintaining a provider-specific list of known model names.
|
|
336
|
+
*/
|
|
337
|
+
function antigravityDisplayModelId(displayName: unknown, wireId: string): string | undefined {
|
|
338
|
+
if (typeof displayName !== "string") return undefined;
|
|
339
|
+
const label = displayName.trim();
|
|
340
|
+
if (!label || label.length > 512) return undefined;
|
|
341
|
+
const slug = (replaceDots: boolean): string => label
|
|
342
|
+
.normalize("NFKC")
|
|
343
|
+
.toLowerCase()
|
|
344
|
+
.replace(replaceDots ? /\./g : /\s+/g, replaceDots ? "-" : " ")
|
|
345
|
+
.replace(/[^a-z0-9.-]+/g, "-")
|
|
346
|
+
.replace(/-+/g, "-")
|
|
347
|
+
.replace(/^-|-$/g, "");
|
|
348
|
+
const preserved = slug(false);
|
|
349
|
+
const compact = slug(true);
|
|
350
|
+
if (!isValidModelDiscoveryModelId(preserved) && !isValidModelDiscoveryModelId(compact)) return undefined;
|
|
351
|
+
if (preserved === wireId || compact === wireId
|
|
352
|
+
|| preserved === `${wireId}-thinking` || compact === `${wireId}-thinking`) {
|
|
353
|
+
return wireId;
|
|
354
|
+
}
|
|
355
|
+
return isValidModelDiscoveryModelId(preserved) ? preserved : compact;
|
|
356
|
+
}
|
|
357
|
+
|
|
257
358
|
/**
|
|
258
359
|
* Extract the CCA models that are valid for agent requests. The endpoint also returns tab,
|
|
259
360
|
* command, commit-message, transcription, and standalone image-generation models; those are not
|
|
@@ -288,13 +389,6 @@ export function parseAntigravityAvailableModels(
|
|
|
288
389
|
}
|
|
289
390
|
}
|
|
290
391
|
}
|
|
291
|
-
// This model is exposed by Antigravity's agent chat surface even though it is grouped under
|
|
292
|
-
// image generation in the discovery response.
|
|
293
|
-
if (Array.isArray(body.imageGenerationModelIds)
|
|
294
|
-
&& body.imageGenerationModelIds.includes("gemini-3.1-flash-image")) {
|
|
295
|
-
if (ids.length >= limit) return null;
|
|
296
|
-
ids.push("gemini-3.1-flash-image");
|
|
297
|
-
}
|
|
298
392
|
// Newer CCA responses identify tiered Flash models through this index instead of
|
|
299
393
|
// adding their synthetic wire ids to agentModelSorts.
|
|
300
394
|
const tieredModelIds = antigravityRecord(body.tieredModelIds);
|
|
@@ -305,6 +399,12 @@ export function parseAntigravityAvailableModels(
|
|
|
305
399
|
|| !Object.hasOwn(models, id)
|
|
306
400
|
|| !antigravityRecord(models[id])
|
|
307
401
|
|| ids.length >= limit) return null;
|
|
402
|
+
const baseId = id.endsWith("-tiered") ? id.slice(0, -"-tiered".length) : id;
|
|
403
|
+
if (ids.some(agentId =>
|
|
404
|
+
agentId === id
|
|
405
|
+
|| agentId === baseId
|
|
406
|
+
|| ANTIGRAVITY_DISCOVERY_EFFORTS.some(effort => agentId === `${baseId}-${effort}`)
|
|
407
|
+
)) continue;
|
|
308
408
|
ids.push(id);
|
|
309
409
|
}
|
|
310
410
|
}
|
|
@@ -313,23 +413,18 @@ export function parseAntigravityAvailableModels(
|
|
|
313
413
|
for (const wireId of ids) {
|
|
314
414
|
const info = antigravityRecord(models[wireId]);
|
|
315
415
|
if (!info || available.has(wireId)) continue;
|
|
316
|
-
// Legacy compatibility aliases are deliberately routed to newer wire ids for saved
|
|
317
|
-
// selections. They are not safe as independently discovered picker rows.
|
|
318
|
-
const alias = Object.hasOwn(ANTIGRAVITY_MODEL_ALIASES, wireId)
|
|
319
|
-
? ANTIGRAVITY_MODEL_ALIASES[wireId]
|
|
320
|
-
: undefined;
|
|
321
|
-
if (alias && alias !== wireId) continue;
|
|
322
416
|
available.set(wireId, info);
|
|
323
417
|
}
|
|
324
418
|
|
|
325
419
|
const out: AntigravityAvailableModel[] = [];
|
|
326
420
|
const seen = new Set<string>();
|
|
327
421
|
for (const [wireId, info] of available) {
|
|
328
|
-
const id = pickerModelIdForDiscoveredWireId(wireId, available);
|
|
422
|
+
const id = pickerModelIdForDiscoveredWireId(wireId, info, available);
|
|
329
423
|
if (seen.has(id)) continue;
|
|
330
424
|
seen.add(id);
|
|
331
425
|
out.push({
|
|
332
426
|
id,
|
|
427
|
+
wireModelId: wireId,
|
|
333
428
|
...(antigravityPositiveInteger(info.maxTokens) ? { contextWindow: antigravityPositiveInteger(info.maxTokens) } : {}),
|
|
334
429
|
// Tri-state, deliberately not a ternary: `true` asserts image support,
|
|
335
430
|
// `false` asserts against it, and ABSENT is unknown. Collapsing absent into
|
|
@@ -347,7 +442,9 @@ export function parseAntigravityAvailableModels(
|
|
|
347
442
|
return out;
|
|
348
443
|
}
|
|
349
444
|
|
|
350
|
-
export function resolveAntigravityWireModelId(modelId: string): string {
|
|
445
|
+
export function resolveAntigravityWireModelId(modelId: string, baseUrl?: string): string {
|
|
446
|
+
const discovered = discoveredAntigravityWireModelId(modelId, baseUrl);
|
|
447
|
+
if (discovered) return discovered;
|
|
351
448
|
return Object.hasOwn(ANTIGRAVITY_MODEL_ALIASES, modelId)
|
|
352
449
|
? ANTIGRAVITY_MODEL_ALIASES[modelId]
|
|
353
450
|
: modelId;
|
|
@@ -380,7 +477,19 @@ export function retiredAntigravityFlashTier(modelId: string): string | undefined
|
|
|
380
477
|
export function resolveAntigravityEffortWireModel(
|
|
381
478
|
modelId: string,
|
|
382
479
|
effort?: string,
|
|
480
|
+
baseUrl?: string,
|
|
383
481
|
): { wireModelId: string; thinkingLevel?: string } {
|
|
482
|
+
const discoveredWireModelId = discoveredAntigravityWireModelId(modelId, baseUrl);
|
|
483
|
+
if (discoveredWireModelId && (discoveredWireModelId !== modelId || isAntigravitySuffixModelId(modelId))) {
|
|
484
|
+
const defaultLevel = ANTIGRAVITY_THINKING_LEVEL_MODELS[modelId];
|
|
485
|
+
return {
|
|
486
|
+
wireModelId: discoveredWireModelId,
|
|
487
|
+
...(defaultLevel
|
|
488
|
+
? { thinkingLevel: effort ? resolveAntigravityThinkingLevel(effort) ?? defaultLevel : defaultLevel }
|
|
489
|
+
: {}),
|
|
490
|
+
};
|
|
491
|
+
}
|
|
492
|
+
|
|
384
493
|
// Rule 0: retired Flash id — Google has taken the wire id offline, so route to the
|
|
385
494
|
// current generation and carry the tier the retired id encoded. This runs BEFORE the
|
|
386
495
|
// suffix check because those ids are aliases, and rule 1 would drop the tier.
|
|
@@ -394,7 +503,7 @@ export function resolveAntigravityEffortWireModel(
|
|
|
394
503
|
|
|
395
504
|
// Rule 1: suffix/compat alias — suffix IS the effort.
|
|
396
505
|
if (isAntigravitySuffixModelId(modelId)) {
|
|
397
|
-
return { wireModelId: resolveAntigravityWireModelId(modelId) };
|
|
506
|
+
return { wireModelId: resolveAntigravityWireModelId(modelId, baseUrl) };
|
|
398
507
|
}
|
|
399
508
|
|
|
400
509
|
// Rule 1b: single-wire-id Gemini model whose tiers ride on thinkingLevel. Without
|
|
@@ -424,7 +533,7 @@ export function resolveAntigravityEffortWireModel(
|
|
|
424
533
|
}
|
|
425
534
|
|
|
426
535
|
// Rule 5: everything else.
|
|
427
|
-
return { wireModelId: resolveAntigravityWireModelId(modelId) };
|
|
536
|
+
return { wireModelId: resolveAntigravityWireModelId(modelId, baseUrl) };
|
|
428
537
|
}
|
|
429
538
|
|
|
430
539
|
|
package/src/providers/derive.ts
CHANGED
|
@@ -393,6 +393,14 @@ function enrichReasoningSummariesByDestination(prov: OcxProviderConfig): void {
|
|
|
393
393
|
applyReasoningSummaryDefaults(prov, destination?.modelSupportsReasoningSummaries);
|
|
394
394
|
}
|
|
395
395
|
|
|
396
|
+
/** Repair the exact low-only ClinePass ladder generated by older key-login presets. */
|
|
397
|
+
export function hasLegacyClinePassReasoningEfforts(name: string, prov: OcxProviderConfig): boolean {
|
|
398
|
+
return name === "cline-pass"
|
|
399
|
+
&& prov.reasoningWireFormat === "gateway-object"
|
|
400
|
+
&& prov.reasoningEfforts?.length === 1
|
|
401
|
+
&& prov.reasoningEfforts[0] === "low";
|
|
402
|
+
}
|
|
403
|
+
|
|
396
404
|
export function enrichProviderFromRegistry(name: string, prov: OcxProviderConfig): void {
|
|
397
405
|
const entry = PROVIDER_REGISTRY.find(row => row.id === name);
|
|
398
406
|
if (!entry || !providerMatchesRegistryTransportWithStaticGuards(name, prov)) {
|
|
@@ -426,7 +434,9 @@ export function enrichProviderFromRegistry(name: string, prov: OcxProviderConfig
|
|
|
426
434
|
if (seed.modelInputModalities) prov.modelInputModalities = fillRecordOfArrays(seed.modelInputModalities, prov.modelInputModalities);
|
|
427
435
|
if (prov.defaultMaxOutputTokens === undefined && seed.defaultMaxOutputTokens !== undefined) prov.defaultMaxOutputTokens = seed.defaultMaxOutputTokens;
|
|
428
436
|
if (!prov.modelMaxOutputTokens && seed.modelMaxOutputTokens) prov.modelMaxOutputTokens = { ...seed.modelMaxOutputTokens };
|
|
429
|
-
if (!prov.reasoningEfforts
|
|
437
|
+
if ((!prov.reasoningEfforts || hasLegacyClinePassReasoningEfforts(name, prov)) && seed.reasoningEfforts) {
|
|
438
|
+
prov.reasoningEfforts = [...seed.reasoningEfforts];
|
|
439
|
+
}
|
|
430
440
|
if (!prov.modelReasoningEfforts && seed.modelReasoningEfforts) prov.modelReasoningEfforts = cloneRecordOfArrays(seed.modelReasoningEfforts);
|
|
431
441
|
if (!prov.modelDefaultReasoningEfforts && seed.modelDefaultReasoningEfforts) prov.modelDefaultReasoningEfforts = { ...seed.modelDefaultReasoningEfforts };
|
|
432
442
|
if (!prov.reasoningEffortMap && seed.reasoningEffortMap) prov.reasoningEffortMap = { ...seed.reasoningEffortMap };
|
package/src/responses/parser.ts
CHANGED
|
@@ -171,6 +171,10 @@ function buildTools(tools: unknown[] | undefined): OcxTool[] | undefined {
|
|
|
171
171
|
};
|
|
172
172
|
for (const t of tools) {
|
|
173
173
|
if (!isObj(t)) continue;
|
|
174
|
+
if (t.type === "function" && isObj(t.function) && typeof t.function.name === "string" && t.function.name.length > 0) {
|
|
175
|
+
pushFn(t.function as Record<string, unknown>);
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
174
178
|
if (t.type === "function" && typeof t.name === "string") {
|
|
175
179
|
pushFn(t);
|
|
176
180
|
} else if (t.type === "namespace" && Array.isArray(t.tools)) {
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
* long-lived proxy cannot grow without limit.
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
|
-
import { createHmac, randomBytes } from "node:crypto";
|
|
22
|
+
import { createHash, createHmac, randomBytes } from "node:crypto";
|
|
23
23
|
import type {
|
|
24
24
|
OcxProviderConfig,
|
|
25
25
|
OcxReasoningReplayIdentity,
|
|
@@ -108,6 +108,21 @@ export function reasoningReplayDestinationIdentity(baseUrl: string | undefined):
|
|
|
108
108
|
return `destination:${processLocalIdentity("destination", canonical)}`;
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
+
/**
|
|
112
|
+
* The same destination identity, but stable across restarts.
|
|
113
|
+
*
|
|
114
|
+
* The process-local form above is keyed by `randomBytes(32)` minted at module load, which
|
|
115
|
+
* is correct for an in-memory cache and fatal for a durable one: every key would change on
|
|
116
|
+
* restart and the store would silently stop matching anything. A plain digest of the same
|
|
117
|
+
* canonical URL is equally non-reversible for this purpose — the input is a configured
|
|
118
|
+
* endpoint, not a secret — and needs no persisted salt or new on-disk state.
|
|
119
|
+
*/
|
|
120
|
+
export function durableReplayDestinationIdentity(baseUrl: string | undefined): string | undefined {
|
|
121
|
+
if (!nonEmpty(baseUrl)) return undefined;
|
|
122
|
+
const canonical = baseUrl.trim().replace(/\/+$/, "");
|
|
123
|
+
return `destination:${createHash("sha256").update("destination\0").update(canonical).digest("hex")}`;
|
|
124
|
+
}
|
|
125
|
+
|
|
111
126
|
/** Produce a non-reversible process-local identity for credential material. */
|
|
112
127
|
export function reasoningReplayCredentialIdentity(
|
|
113
128
|
kind: "key" | "oauth" | "codex",
|
|
@@ -27,6 +27,11 @@ import type { OcxProviderOpaqueToolCallMetadata, OcxReasoningReplayScopeRef } fr
|
|
|
27
27
|
import { isCarryableSignature, responsesExtraContentFromProviderMetadata } from "./provider-opaque-metadata";
|
|
28
28
|
|
|
29
29
|
const STORE_FILE_NAME = "thought-signature-replay.json";
|
|
30
|
+
/**
|
|
31
|
+
* Bumped whenever `keyFor` changes shape. v3 added the durable destination identity, so a
|
|
32
|
+
* v2 file's keys can never match and are dropped on load instead of aging out invisibly.
|
|
33
|
+
*/
|
|
34
|
+
const STORE_VERSION = 3;
|
|
30
35
|
|
|
31
36
|
/** Bound on remembered entries; real signatures are a few hundred bytes, so this stays small. */
|
|
32
37
|
const MAX_ENTRIES = 16_384;
|
|
@@ -83,6 +88,11 @@ function keyFor(callId: string, scope: OcxReasoningReplayScopeRef | undefined):
|
|
|
83
88
|
return JSON.stringify([
|
|
84
89
|
scope.clientThreadId,
|
|
85
90
|
identity.providerName,
|
|
91
|
+
// Destination, unlike the credential identity, has a restart-stable form: it is a
|
|
92
|
+
// configured endpoint rather than a secret, so a plain digest works where the
|
|
93
|
+
// reasoning cache's randomBytes-keyed HMAC cannot. Without it, one provider NAME
|
|
94
|
+
// serving two endpoints shares signatures across both.
|
|
95
|
+
identity.providerDestinationDurableIdentity ?? "destination:unknown",
|
|
86
96
|
identity.adapterName,
|
|
87
97
|
identity.modelId,
|
|
88
98
|
callId,
|
|
@@ -103,6 +113,12 @@ function load(): void {
|
|
|
103
113
|
if (typeof parsed !== "object" || parsed === null || !Array.isArray((parsed as { entries?: unknown }).entries)) {
|
|
104
114
|
return;
|
|
105
115
|
}
|
|
116
|
+
// The version was written but never read, so a key-shape change could not be
|
|
117
|
+
// announced — old entries simply went dead and aged out on TTL, which is silent and
|
|
118
|
+
// indistinguishable from a store that is not working. Reading it makes a shape change
|
|
119
|
+
// an explicit drop: entries keyed by an older scheme are discarded on load rather than
|
|
120
|
+
// lingering as permanent misses.
|
|
121
|
+
if ((parsed as { version?: unknown }).version !== STORE_VERSION) return;
|
|
106
122
|
const nowMs = Date.now();
|
|
107
123
|
for (const entry of (parsed as { entries: unknown[] }).entries) {
|
|
108
124
|
if (typeof entry !== "object" || entry === null) continue;
|
|
@@ -141,7 +157,7 @@ function persist(): Promise<void> {
|
|
|
141
157
|
persistChain = persistChain
|
|
142
158
|
.then(async () => {
|
|
143
159
|
const snapshot = JSON.stringify({
|
|
144
|
-
version:
|
|
160
|
+
version: STORE_VERSION,
|
|
145
161
|
entries: [...entries].map(([key, entry]) => ({ key, sig: entry.sig, savedAt: entry.savedAt })),
|
|
146
162
|
});
|
|
147
163
|
await atomicWriteFileAsync(storePath(), snapshot);
|