@herbertgao/pi-extensions 2026.9.3 → 2026.9.4

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 (37) hide show
  1. package/README.md +2 -1
  2. package/THIRD_PARTY_NOTICES.md +25 -0
  3. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/compact-mode.ts +3 -2
  4. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/default-mode.ts +16 -11
  5. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-renderer.ts +20 -6
  6. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/grouping.ts +12 -7
  7. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/result.ts +98 -0
  8. package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
  9. package/node_modules/pi-antigravity/LICENSE +21 -0
  10. package/node_modules/pi-antigravity/README.md +194 -0
  11. package/node_modules/pi-antigravity/package.json +67 -0
  12. package/node_modules/pi-antigravity/src/auth/index.ts +14 -0
  13. package/node_modules/pi-antigravity/src/auth/oauth.ts +442 -0
  14. package/node_modules/pi-antigravity/src/client/client.ts +561 -0
  15. package/node_modules/pi-antigravity/src/client/index.ts +1 -0
  16. package/node_modules/pi-antigravity/src/diagnostics/diagnostics.ts +96 -0
  17. package/node_modules/pi-antigravity/src/diagnostics/index.ts +1 -0
  18. package/node_modules/pi-antigravity/src/image/image.ts +336 -0
  19. package/node_modules/pi-antigravity/src/image/index.ts +1 -0
  20. package/node_modules/pi-antigravity/src/index.ts +280 -0
  21. package/node_modules/pi-antigravity/src/models/discovery.ts +154 -0
  22. package/node_modules/pi-antigravity/src/models/grouping.ts +424 -0
  23. package/node_modules/pi-antigravity/src/models/index.ts +3 -0
  24. package/node_modules/pi-antigravity/src/models/models.ts +500 -0
  25. package/node_modules/pi-antigravity/src/stream/index.ts +1 -0
  26. package/node_modules/pi-antigravity/src/stream/stream.ts +1460 -0
  27. package/node_modules/pi-antigravity/src/types/enums.ts +42 -0
  28. package/node_modules/pi-antigravity/src/types/index.ts +2 -0
  29. package/node_modules/pi-antigravity/src/types/types.ts +292 -0
  30. package/node_modules/pi-antigravity/src/usage/index.ts +1 -0
  31. package/node_modules/pi-antigravity/src/usage/usage.ts +371 -0
  32. package/node_modules/pi-antigravity/src/utils/http.ts +91 -0
  33. package/node_modules/pi-antigravity/src/utils/index.ts +3 -0
  34. package/node_modules/pi-antigravity/src/utils/security.ts +73 -0
  35. package/node_modules/pi-antigravity/src/utils/util.ts +132 -0
  36. package/node_modules/pi-antigravity/tsconfig.json +21 -0
  37. package/package.json +5 -2
@@ -0,0 +1,500 @@
1
+ import type { ProviderModelConfig } from "@earendil-works/pi-coding-agent";
2
+ import type { AntigravityRouting, ThinkingWire } from "../types/types.js";
3
+ import { ThinkingEffort } from "../types/enums.js";
4
+ import type { AntigravityCatalog } from "./grouping.js";
5
+
6
+ export const PROVIDER_ID = "antigravity";
7
+ export const PROVIDER_NAME = "Antigravity";
8
+
9
+ /**
10
+ * Public selectable model IDs → backend request model IDs by thinking effort.
11
+ *
12
+ * Catalog mirrors `agy models` (Antigravity CLI), which currently advertises:
13
+ * - Gemini 3.8 Flash (Low / Medium / High)
14
+ * - Gemini 3.7 Flash (Low / Medium / High)
15
+ * - Gemini 3.6 Flash (Low / Medium / High)
16
+ * - Gemini 3.5 Flash (Low / Medium / High)
17
+ * - Gemini 3.1 Pro (Low / High)
18
+ * - Claude Sonnet 4.6 (Thinking)
19
+ * - Claude Opus 4.6 (Thinking)
20
+ * - GPT-OSS 120B (Medium)
21
+ *
22
+ * Pi exposes those as public model IDs and only surfaces the exact thinking levels
23
+ * advertised by the backend for each model.
24
+ */
25
+ export const ANTIGRAVITY_ROUTING: Record<string, AntigravityRouting> = {
26
+ "claude-opus-4-6": {
27
+ routing: {
28
+ minimal: "claude-opus-4-6-thinking",
29
+ low: "claude-opus-4-6-thinking",
30
+ medium: "claude-opus-4-6-thinking",
31
+ high: "claude-opus-4-6-thinking",
32
+ },
33
+ defaultRequestId: "claude-opus-4-6-thinking",
34
+ },
35
+ // Live fetchAvailableModels exposes `claude-sonnet-4-6` (display: Thinking), not a separate *-thinking id.
36
+ "claude-sonnet-4-6": {
37
+ off: "claude-sonnet-4-6",
38
+ routing: {
39
+ minimal: "claude-sonnet-4-6",
40
+ low: "claude-sonnet-4-6",
41
+ medium: "claude-sonnet-4-6",
42
+ high: "claude-sonnet-4-6",
43
+ xhigh: "claude-sonnet-4-6",
44
+ },
45
+ defaultRequestId: "claude-sonnet-4-6",
46
+ },
47
+ "gemini-3.1-pro": {
48
+ // `gemini-3.1-pro-high` is advertised but currently 400s for agent streamGenerateContent;
49
+ // `gemini-pro-agent` is the working High runtime id (same display name in fetchAvailableModels).
50
+ off: "gemini-3.1-pro-low",
51
+ routing: {
52
+ minimal: "gemini-3.1-pro-low",
53
+ low: "gemini-3.1-pro-low",
54
+ medium: "gemini-3.1-pro-low",
55
+ high: "gemini-pro-agent",
56
+ xhigh: "gemini-pro-agent",
57
+ },
58
+ defaultRequestId: "gemini-3.1-pro-low",
59
+ },
60
+ "gemini-3.8-flash": {
61
+ off: "gemini-3.8-flash-low",
62
+ routing: {
63
+ minimal: "gemini-3.8-flash-low",
64
+ low: "gemini-3.8-flash-low",
65
+ medium: "gemini-3.8-flash-medium",
66
+ high: "gemini-3.8-flash-high",
67
+ xhigh: "gemini-3.8-flash-high",
68
+ },
69
+ defaultRequestId: "gemini-3.8-flash-low",
70
+ },
71
+ "gemini-3.7-flash": {
72
+ off: "gemini-3.7-flash-low",
73
+ routing: {
74
+ minimal: "gemini-3.7-flash-low",
75
+ low: "gemini-3.7-flash-low",
76
+ medium: "gemini-3.7-flash-medium",
77
+ high: "gemini-3.7-flash-high",
78
+ xhigh: "gemini-3.7-flash-high",
79
+ },
80
+ defaultRequestId: "gemini-3.7-flash-low",
81
+ },
82
+ "gemini-3.6-flash": {
83
+ // agy models: gemini-3.6-flash-low / -medium / -high
84
+ off: "gemini-3.6-flash-low",
85
+ routing: {
86
+ minimal: "gemini-3.6-flash-low",
87
+ low: "gemini-3.6-flash-low",
88
+ medium: "gemini-3.6-flash-medium",
89
+ high: "gemini-3.6-flash-high",
90
+ xhigh: "gemini-3.6-flash-high",
91
+ },
92
+ defaultRequestId: "gemini-3.6-flash-low",
93
+ },
94
+ "gemini-3.5-flash": {
95
+ off: "gemini-3.5-flash-extra-low",
96
+ routing: {
97
+ minimal: "gemini-3.5-flash-extra-low",
98
+ low: "gemini-3.5-flash-extra-low",
99
+ medium: "gemini-3.5-flash-low",
100
+ high: "gemini-3-flash-agent",
101
+ xhigh: "gemini-3-flash-agent",
102
+ },
103
+ defaultRequestId: "gemini-3.5-flash-extra-low",
104
+ },
105
+ "gpt-oss-120b": {
106
+ off: "gpt-oss-120b-medium",
107
+ routing: {
108
+ minimal: "gpt-oss-120b-medium",
109
+ low: "gpt-oss-120b-medium",
110
+ medium: "gpt-oss-120b-medium",
111
+ high: "gpt-oss-120b-medium",
112
+ },
113
+ defaultRequestId: "gpt-oss-120b-medium",
114
+ },
115
+ };
116
+
117
+ /**
118
+ * Verified maximum output tokens accepted by the Cloud Code Assist backend per model/runtime ID.
119
+ * Requesting more than these limits returns a 400 Bad Request from the API.
120
+ */
121
+ export const RUNTIME_MAX_OUTPUT_TOKENS: Record<string, number> = {
122
+ "gemini-3.8-flash": 65536,
123
+ "gemini-3.8-flash-low": 65536,
124
+ "gemini-3.8-flash-medium": 65536,
125
+ "gemini-3.8-flash-high": 65536,
126
+ "gemini-3.7-flash": 65536,
127
+ "gemini-3.7-flash-tiered": 65536,
128
+ // Retain rollout-era IDs for compatibility with pinned runtime overrides.
129
+ "gemini-3.7-flash-low": 65536,
130
+ "gemini-3.7-flash-medium": 65536,
131
+ "gemini-3.7-flash-high": 65536,
132
+ "gemini-3.6-flash": 65536,
133
+ "gemini-3.6-flash-low": 65536,
134
+ "gemini-3.6-flash-medium": 65536,
135
+ "gemini-3.6-flash-high": 65536,
136
+ "gemini-3.5-flash": 65536,
137
+ "gemini-3.5-flash-extra-low": 65536,
138
+ "gemini-3.5-flash-low": 65536,
139
+ "gemini-3-flash-agent": 65536,
140
+ "gemini-3.1-pro": 65535,
141
+ "gemini-3.1-pro-low": 65535,
142
+ "gemini-3.1-pro-high": 65535,
143
+ "gemini-pro-agent": 65535,
144
+ "claude-opus-4-6": 64000,
145
+ "claude-opus-4-6-thinking": 64000,
146
+ "claude-sonnet-4-6": 64000,
147
+ "gpt-oss-120b": 32768,
148
+ "gpt-oss-120b-medium": 32768,
149
+ };
150
+
151
+ export function getMaxOutputTokens(modelId: string, runtimeModel?: string): number {
152
+ if (runtimeModel && RUNTIME_MAX_OUTPUT_TOKENS[runtimeModel] !== undefined) {
153
+ return RUNTIME_MAX_OUTPUT_TOKENS[runtimeModel];
154
+ }
155
+ if (RUNTIME_MAX_OUTPUT_TOKENS[modelId] !== undefined) {
156
+ return RUNTIME_MAX_OUTPUT_TOKENS[modelId];
157
+ }
158
+ if (runtimeModel) {
159
+ if (runtimeModel.startsWith("claude-")) return 64000;
160
+ if (runtimeModel.startsWith("gpt-oss-")) return 32768;
161
+ if (runtimeModel.startsWith("gemini-3.1-pro") || runtimeModel === "gemini-pro-agent")
162
+ return 65535;
163
+ if (runtimeModel.startsWith("gemini-")) return 65536;
164
+ }
165
+ return 8192;
166
+ }
167
+
168
+ const geminiFlashCost = { input: 0.1, output: 0.4, cacheRead: 0.025, cacheWrite: 0.1 };
169
+ const geminiProCost = { input: 1.25, output: 5.0, cacheRead: 0.3125, cacheWrite: 1.25 };
170
+ const claudeSonnetCost = { input: 3.0, output: 15.0, cacheRead: 0.3, cacheWrite: 3.75 };
171
+ const claudeOpusCost = { input: 15.0, output: 75.0, cacheRead: 1.5, cacheWrite: 18.75 };
172
+ const gptOssCost = { input: 0.6, output: 2.4, cacheRead: 0.15, cacheWrite: 0.6 };
173
+
174
+ // A null entry is intentionally hidden by Pi. Do not collapse levels that happen to
175
+ // route to the same runtime ID: the UI must reflect the levels the backend advertises.
176
+ const thinkingLevelMaps = {
177
+ lowMediumHigh: {
178
+ off: null,
179
+ minimal: null,
180
+ low: "low",
181
+ medium: "medium",
182
+ high: "high",
183
+ xhigh: null,
184
+ max: null,
185
+ },
186
+ lowHigh: {
187
+ off: null,
188
+ minimal: null,
189
+ low: "low",
190
+ medium: null,
191
+ high: "high",
192
+ xhigh: null,
193
+ max: null,
194
+ },
195
+ thinking: {
196
+ off: null,
197
+ minimal: null,
198
+ low: null,
199
+ medium: null,
200
+ high: "high",
201
+ xhigh: null,
202
+ max: null,
203
+ },
204
+ medium: {
205
+ off: null,
206
+ minimal: null,
207
+ low: null,
208
+ medium: "medium",
209
+ high: null,
210
+ xhigh: null,
211
+ max: null,
212
+ },
213
+ } satisfies Record<string, ProviderModelConfig["thinkingLevelMap"]>;
214
+
215
+ /** Same set as `agy models`, collapsed to public Pi model IDs. */
216
+ export const ANTIGRAVITY_MODELS: ProviderModelConfig[] = [
217
+ {
218
+ id: "gemini-3.8-flash",
219
+ name: "Gemini 3.8 Flash (Antigravity)",
220
+ reasoning: true,
221
+ thinkingLevelMap: thinkingLevelMaps.lowMediumHigh,
222
+ input: ["text", "image"],
223
+ cost: geminiFlashCost,
224
+ contextWindow: 1048576,
225
+ maxTokens: 65536,
226
+ },
227
+ {
228
+ id: "gemini-3.7-flash",
229
+ name: "Gemini 3.7 Flash (Antigravity)",
230
+ reasoning: true,
231
+ thinkingLevelMap: thinkingLevelMaps.lowMediumHigh,
232
+ input: ["text", "image"],
233
+ cost: geminiFlashCost,
234
+ contextWindow: 1048576,
235
+ maxTokens: 65536,
236
+ },
237
+ {
238
+ id: "gemini-3.6-flash",
239
+ name: "Gemini 3.6 Flash (Antigravity)",
240
+ reasoning: true,
241
+ thinkingLevelMap: thinkingLevelMaps.lowMediumHigh,
242
+ input: ["text", "image"],
243
+ cost: geminiFlashCost,
244
+ contextWindow: 1048576,
245
+ maxTokens: 65536,
246
+ },
247
+ {
248
+ id: "claude-opus-4-6",
249
+ name: "Claude Opus 4.6 (Antigravity)",
250
+ reasoning: true,
251
+ thinkingLevelMap: thinkingLevelMaps.thinking,
252
+ input: ["text", "image"],
253
+ cost: claudeOpusCost,
254
+ contextWindow: 250000,
255
+ maxTokens: 64000,
256
+ },
257
+ {
258
+ id: "claude-sonnet-4-6",
259
+ name: "Claude Sonnet 4.6 (Antigravity)",
260
+ reasoning: true,
261
+ thinkingLevelMap: thinkingLevelMaps.thinking,
262
+ input: ["text", "image"],
263
+ cost: claudeSonnetCost,
264
+ contextWindow: 200000,
265
+ maxTokens: 64000,
266
+ },
267
+ {
268
+ id: "gemini-3.1-pro",
269
+ name: "Gemini 3.1 Pro (Antigravity)",
270
+ reasoning: true,
271
+ thinkingLevelMap: thinkingLevelMaps.lowHigh,
272
+ input: ["text", "image"],
273
+ cost: geminiProCost,
274
+ contextWindow: 1048576,
275
+ maxTokens: 65535,
276
+ },
277
+ {
278
+ id: "gemini-3.5-flash",
279
+ name: "Gemini 3.5 Flash (Antigravity)",
280
+ reasoning: true,
281
+ thinkingLevelMap: thinkingLevelMaps.lowMediumHigh,
282
+ input: ["text", "image"],
283
+ cost: geminiFlashCost,
284
+ contextWindow: 1048576,
285
+ maxTokens: 65536,
286
+ },
287
+ {
288
+ id: "gpt-oss-120b",
289
+ name: "GPT-OSS 120B (Antigravity)",
290
+ reasoning: true,
291
+ thinkingLevelMap: thinkingLevelMaps.medium,
292
+ input: ["text"],
293
+ cost: gptOssCost,
294
+ contextWindow: 131072,
295
+ maxTokens: 32768,
296
+ },
297
+ ];
298
+
299
+ let currentModels: ProviderModelConfig[] = ANTIGRAVITY_MODELS;
300
+ let currentRouting: Record<string, AntigravityRouting> = { ...ANTIGRAVITY_ROUTING };
301
+
302
+ export function getCurrentAntigravityModels(): ProviderModelConfig[] {
303
+ return currentModels;
304
+ }
305
+
306
+ export function getCurrentAntigravityRouting(): Record<string, AntigravityRouting> {
307
+ return currentRouting;
308
+ }
309
+
310
+ export function getCurrentAntigravityCatalog(): AntigravityCatalog {
311
+ return { models: currentModels, routing: currentRouting };
312
+ }
313
+
314
+ export function applyAntigravityCatalog(catalog: AntigravityCatalog): void {
315
+ currentModels = catalog.models;
316
+ currentRouting = catalog.routing;
317
+ }
318
+
319
+ export function resetAntigravityCatalogForTests(): void {
320
+ currentModels = ANTIGRAVITY_MODELS;
321
+ currentRouting = { ...ANTIGRAVITY_ROUTING };
322
+ }
323
+
324
+ /** Resolve public model id + thinking effort to Antigravity runtime model id. */
325
+ export function getAntigravityRequestModelId(modelId: string, effort: string | undefined): string {
326
+ const r = currentRouting[modelId] ?? ANTIGRAVITY_ROUTING[modelId];
327
+ if (!r) return modelId;
328
+
329
+ if (effort === undefined || effort === "off") {
330
+ return r.off ?? r.routing?.minimal ?? r.routing?.low ?? r.defaultRequestId ?? modelId;
331
+ }
332
+
333
+ const effortKey = effort as ThinkingEffort;
334
+ if (effortKey === ThinkingEffort.Xhigh) {
335
+ return (
336
+ r.routing?.xhigh ??
337
+ r.routing?.high ??
338
+ r.routing?.low ??
339
+ r.routing?.minimal ??
340
+ r.off ??
341
+ r.defaultRequestId ??
342
+ modelId
343
+ );
344
+ }
345
+
346
+ return (
347
+ r.routing?.[effortKey] ??
348
+ r.routing?.low ??
349
+ r.routing?.minimal ??
350
+ r.off ??
351
+ r.defaultRequestId ??
352
+ modelId
353
+ );
354
+ }
355
+
356
+ /**
357
+ * If a next-gen model (e.g. Gemini 3.8 Flash) is not yet available on the backend,
358
+ * provide a fallback runtime model ID (e.g. Gemini 3.7 Flash) to maintain availability.
359
+ */
360
+ export function getFallbackRuntimeModel(runtimeModel: string, effort?: string): string | undefined {
361
+ if (runtimeModel.startsWith("gemini-3.8-flash-")) {
362
+ return runtimeModel.replace("gemini-3.8-flash-", "gemini-3.7-flash-");
363
+ }
364
+ if (runtimeModel === "gemini-3.8-flash") {
365
+ return "gemini-3.7-flash-low";
366
+ }
367
+ if (runtimeModel === "gemini-3.7-flash-tiered") {
368
+ return getAntigravityRequestModelId("gemini-3.6-flash", effort);
369
+ }
370
+ if (runtimeModel.startsWith("gemini-3.7-flash-")) {
371
+ return runtimeModel.replace("gemini-3.7-flash-", "gemini-3.6-flash-");
372
+ }
373
+ if (runtimeModel === "gemini-3.7-flash") {
374
+ return "gemini-3.6-flash-low";
375
+ }
376
+ return undefined;
377
+ }
378
+
379
+ export type { ThinkingWire };
380
+
381
+ export const ANTIGRAVITY_MODEL_ENUM: Record<string, string> = {
382
+ // Gemini 3.8 Flash
383
+ "gemini-3.8-flash": "MODEL_PLACEHOLDER_M318",
384
+ "gemini-3.8-flash-high": "MODEL_PLACEHOLDER_M318",
385
+ "gemini-3.8-flash-medium": "MODEL_PLACEHOLDER_M319",
386
+ "gemini-3.8-flash-low": "MODEL_PLACEHOLDER_M320",
387
+ "gemini-3.8-flash-tiered": "MODEL_PLACEHOLDER_M322",
388
+ // Gemini 3.7 Flash
389
+ "gemini-3.7-flash": "MODEL_PLACEHOLDER_M298",
390
+ "gemini-3.7-flash-high": "MODEL_PLACEHOLDER_M298",
391
+ "gemini-3.7-flash-medium": "MODEL_PLACEHOLDER_M299",
392
+ "gemini-3.7-flash-low": "MODEL_PLACEHOLDER_M300",
393
+ "gemini-3.7-flash-tiered": "MODEL_PLACEHOLDER_M301",
394
+ // Gemini 3.6 Flash
395
+ "gemini-3.6-flash": "MODEL_PLACEHOLDER_M71",
396
+ "gemini-3.6-flash-high": "MODEL_PLACEHOLDER_M71",
397
+ "gemini-3.6-flash-medium": "MODEL_PLACEHOLDER_M72",
398
+ "gemini-3.6-flash-low": "MODEL_PLACEHOLDER_M73",
399
+ "gemini-3.6-flash-tiered": "MODEL_PLACEHOLDER_M196",
400
+ // Gemini 3.5 Flash
401
+ "gemini-3.5-flash": "MODEL_PLACEHOLDER_M20",
402
+ "gemini-3.5-flash-extra-low": "MODEL_PLACEHOLDER_M187",
403
+ "gemini-3.5-flash-low": "MODEL_PLACEHOLDER_M20",
404
+ "gemini-3-flash-agent": "MODEL_PLACEHOLDER_M84",
405
+ // Gemini 3.1 Pro
406
+ "gemini-3.1-pro": "MODEL_PLACEHOLDER_M36",
407
+ "gemini-3.1-pro-low": "MODEL_PLACEHOLDER_M36",
408
+ "gemini-3.1-pro-high": "MODEL_PLACEHOLDER_M37",
409
+ "gemini-pro-agent": "MODEL_PLACEHOLDER_M16",
410
+ // Claude
411
+ "claude-sonnet-4-6": "MODEL_PLACEHOLDER_M35",
412
+ "claude-opus-4-6": "MODEL_PLACEHOLDER_M26",
413
+ "claude-opus-4-6-thinking": "MODEL_PLACEHOLDER_M26",
414
+ // GPT-OSS
415
+ "gpt-oss-120b": "MODEL_OPENAI_GPT_OSS_120B_MEDIUM",
416
+ "gpt-oss-120b-medium": "MODEL_OPENAI_GPT_OSS_120B_MEDIUM",
417
+ };
418
+
419
+ const modelEnumCache = new Map<string, string>();
420
+
421
+ /** Register dynamically discovered model enum (e.g. from fetchAvailableModels). */
422
+ export function registerModelEnum(wireModelId: string, modelEnum: string): void {
423
+ if (wireModelId && modelEnum) {
424
+ modelEnumCache.set(wireModelId, modelEnum);
425
+ }
426
+ }
427
+
428
+ /** Register batch of discovered model enums from fetchAvailableModels raw models dictionary. */
429
+ export function registerDiscoveredModelEnums(
430
+ models: Record<string, { model?: unknown }> | undefined,
431
+ ): void {
432
+ if (!models) return;
433
+ for (const [wireId, info] of Object.entries(models)) {
434
+ if (typeof info?.model === "string" && info.model) {
435
+ modelEnumCache.set(wireId, info.model);
436
+ }
437
+ }
438
+ }
439
+
440
+ /** Get model_enum label for a given wire model id (dynamic cache first, then static fallback). */
441
+ export function getModelEnum(wireModelId: string): string | undefined {
442
+ const direct = modelEnumCache.get(wireModelId) || ANTIGRAVITY_MODEL_ENUM[wireModelId];
443
+ if (direct) return direct;
444
+
445
+ // Runtime overrides may name a public/base model while discovery only returned
446
+ // an enum for its selected runtime variant (for example `-low`).
447
+ const routed = getAntigravityRequestModelId(wireModelId, undefined);
448
+ return modelEnumCache.get(routed) || ANTIGRAVITY_MODEL_ENUM[routed];
449
+ }
450
+
451
+ /** Return a serializable snapshot of model enums learned from discovery. */
452
+ export function snapshotDynamicModelEnums(): Record<string, string> {
453
+ return Object.fromEntries(modelEnumCache);
454
+ }
455
+
456
+ /** Replace dynamically learned model enums with a previously persisted snapshot. */
457
+ export function restoreDynamicModelEnums(modelEnums: Record<string, string>): void {
458
+ modelEnumCache.clear();
459
+ for (const [wireModelId, modelEnum] of Object.entries(modelEnums)) {
460
+ if (wireModelId && modelEnum) modelEnumCache.set(wireModelId, modelEnum);
461
+ }
462
+ }
463
+
464
+ export function clearModelEnumCache(): void {
465
+ modelEnumCache.clear();
466
+ }
467
+
468
+ export function getThinkingConfig(
469
+ modelId: string,
470
+ effort: string | undefined,
471
+ ): ThinkingWire | undefined {
472
+ if (modelId.startsWith("claude-")) {
473
+ if (!effort || effort === "off") return { includeThoughts: false, thinkingBudget: 0 };
474
+ return { includeThoughts: true, thinkingBudget: 1024 };
475
+ }
476
+ if (modelId.startsWith("gpt-oss-")) {
477
+ if (!effort || effort === "off") return { includeThoughts: false, thinkingBudget: 0 };
478
+ return { includeThoughts: true, thinkingBudget: 8192 };
479
+ }
480
+ if (modelId.startsWith("gemini-3.5-flash") || modelId === "gemini-3-flash-agent") {
481
+ if (!effort || effort === "off") return { includeThoughts: false, thinkingBudget: 0 };
482
+ const thinkingBudget =
483
+ effort === "high" || effort === "xhigh" ? 10_000 : effort === "medium" ? 4_000 : 1_000;
484
+ return { includeThoughts: true, thinkingBudget };
485
+ }
486
+ if (modelId.startsWith("gemini-3.1-pro") || modelId === "gemini-pro-agent") {
487
+ if (!effort || effort === "off") return { includeThoughts: false, thinkingBudget: 0 };
488
+ return {
489
+ includeThoughts: true,
490
+ thinkingBudget: effort === "high" || effort === "xhigh" ? 10_001 : 1_001,
491
+ };
492
+ }
493
+ if (modelId.startsWith("gemini-")) {
494
+ if (!effort || effort === "off") return { includeThoughts: false, thinkingBudget: 0 };
495
+ const thinkingBudget =
496
+ effort === "high" || effort === "xhigh" ? -1 : effort === "medium" ? 4_000 : 1_000;
497
+ return { includeThoughts: true, thinkingBudget };
498
+ }
499
+ return undefined;
500
+ }
@@ -0,0 +1 @@
1
+ export * from "./stream.js";