@centerforagenticai/pi-multi-account 0.1.1
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/LICENSE +21 -0
- package/NOTICE +29 -0
- package/README.md +999 -0
- package/config/models/pi-multi-account.v1.json +32 -0
- package/config/subscription-plans.v1.json +122 -0
- package/package.json +76 -0
- package/packages/pi-anthropic-oauth/LICENSE +21 -0
- package/packages/pi-anthropic-oauth/package.json +54 -0
- package/packages/pi-anthropic-oauth/src/auth.ts +396 -0
- package/packages/pi-anthropic-oauth/src/context.ts +116 -0
- package/packages/pi-anthropic-oauth/src/convert.ts +303 -0
- package/packages/pi-anthropic-oauth/src/index.ts +37 -0
- package/packages/pi-anthropic-oauth/src/prompt.ts +137 -0
- package/packages/pi-anthropic-oauth/src/stream.ts +476 -0
- package/packages/pi-antigravity/LICENSE +21 -0
- package/packages/pi-antigravity/package.json +77 -0
- package/packages/pi-antigravity/src/auth/index.ts +14 -0
- package/packages/pi-antigravity/src/auth/oauth.ts +442 -0
- package/packages/pi-antigravity/src/client/client.ts +561 -0
- package/packages/pi-antigravity/src/client/index.ts +1 -0
- package/packages/pi-antigravity/src/context.ts +110 -0
- package/packages/pi-antigravity/src/diagnostics/diagnostics.ts +96 -0
- package/packages/pi-antigravity/src/diagnostics/index.ts +1 -0
- package/packages/pi-antigravity/src/image/image.ts +336 -0
- package/packages/pi-antigravity/src/image/index.ts +1 -0
- package/packages/pi-antigravity/src/index.ts +280 -0
- package/packages/pi-antigravity/src/models/discovery.ts +154 -0
- package/packages/pi-antigravity/src/models/grouping.ts +424 -0
- package/packages/pi-antigravity/src/models/index.ts +3 -0
- package/packages/pi-antigravity/src/models/models.ts +500 -0
- package/packages/pi-antigravity/src/stream/index.ts +1 -0
- package/packages/pi-antigravity/src/stream/stream.ts +1478 -0
- package/packages/pi-antigravity/src/types/enums.ts +42 -0
- package/packages/pi-antigravity/src/types/index.ts +2 -0
- package/packages/pi-antigravity/src/types/types.ts +292 -0
- package/packages/pi-antigravity/src/usage/index.ts +1 -0
- package/packages/pi-antigravity/src/usage/usage.ts +416 -0
- package/packages/pi-antigravity/src/utils/http.ts +91 -0
- package/packages/pi-antigravity/src/utils/index.ts +3 -0
- package/packages/pi-antigravity/src/utils/security.ts +73 -0
- package/packages/pi-antigravity/src/utils/util.ts +132 -0
- package/scripts/multi-account.mjs +44 -0
- package/src/account-labels.ts +223 -0
- package/src/account-plan-assignment.ts +340 -0
- package/src/account-rate-history.ts +372 -0
- package/src/anthropic-adaptive-stream.ts +531 -0
- package/src/anthropic-alias-stream.ts +140 -0
- package/src/anthropic-context-compat.ts +80 -0
- package/src/api-pricing.ts +579 -0
- package/src/bounded-file-lines.ts +97 -0
- package/src/catalog-rebinding.ts +177 -0
- package/src/catalog-registration-probe.ts +111 -0
- package/src/codex-adapter.ts +345 -0
- package/src/codex-model-defaults.ts +785 -0
- package/src/command-completions.ts +404 -0
- package/src/commands.ts +2000 -0
- package/src/compaction.ts +14 -0
- package/src/config.ts +1317 -0
- package/src/continuation.ts +569 -0
- package/src/cooldowns.ts +110 -0
- package/src/cost-digest-store.ts +332 -0
- package/src/cost-digest.ts +1044 -0
- package/src/cost-history.ts +251 -0
- package/src/cost-period-closer.ts +160 -0
- package/src/cost-report-json.ts +318 -0
- package/src/cost-report-reader.ts +368 -0
- package/src/cost-report-render.ts +207 -0
- package/src/cost-report.ts +1104 -0
- package/src/coverage-attestation.ts +397 -0
- package/src/credential-lifecycle.ts +169 -0
- package/src/credential-refresh.ts +248 -0
- package/src/declaration-notice-marker.ts +238 -0
- package/src/diagnostic-store.ts +276 -0
- package/src/diagnostics.ts +309 -0
- package/src/discovery.ts +471 -0
- package/src/duration.ts +13 -0
- package/src/error-classification.ts +256 -0
- package/src/fuzzy.ts +15 -0
- package/src/group-policy.ts +81 -0
- package/src/history-store.ts +897 -0
- package/src/index.ts +5572 -0
- package/src/lifecycle.ts +378 -0
- package/src/logical-dispatch.ts +279 -0
- package/src/logical-model-selector.ts +254 -0
- package/src/logical-model-switcher.ts +430 -0
- package/src/logical-provider-attribution.ts +544 -0
- package/src/logical-provider.ts +1237 -0
- package/src/logical-route-indicator.ts +215 -0
- package/src/machine-lease.ts +445 -0
- package/src/model-support.ts +66 -0
- package/src/models-declaration.ts +1091 -0
- package/src/openai-adapter.ts +117 -0
- package/src/openrouter-budget.ts +304 -0
- package/src/openrouter-fallback.ts +146 -0
- package/src/period-boundaries.ts +376 -0
- package/src/pi-anthropic-oauth.d.ts +6 -0
- package/src/preflight.ts +253 -0
- package/src/pricing-cache.ts +235 -0
- package/src/project-identity.ts +100 -0
- package/src/provider-registration.ts +942 -0
- package/src/rate-formula.ts +163 -0
- package/src/recovery-engine.ts +853 -0
- package/src/recovery-output.ts +837 -0
- package/src/recovery-plan.ts +239 -0
- package/src/report-range.ts +203 -0
- package/src/route-resolver.ts +789 -0
- package/src/routing-config-transaction.ts +232 -0
- package/src/routing.ts +1163 -0
- package/src/runtime-state.ts +630 -0
- package/src/session-account-groups.ts +284 -0
- package/src/session-restore.ts +287 -0
- package/src/shared-usage.ts +1392 -0
- package/src/standalone-cli.ts +720 -0
- package/src/status-view.ts +578 -0
- package/src/subscription-plan-catalog.ts +346 -0
- package/src/tier-model-resolver.ts +46 -0
- package/src/upstream-anthropic.ts +315 -0
- package/src/upstream-antigravity.ts +327 -0
- package/src/usage-fetch.ts +1634 -0
- package/src/usage.ts +1026 -0
- package/src/vendor.ts +87 -0
- package/src/warmer.ts +231 -0
- package/src/watchdog.ts +219 -0
- package/src/window-history.ts +270 -0
|
@@ -0,0 +1,424 @@
|
|
|
1
|
+
import type { ProviderModelConfig } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
import { ThinkingEffort } from "../types/enums.js";
|
|
3
|
+
import type { AntigravityRouting, ModelInfoRaw } from "../types/types.js";
|
|
4
|
+
|
|
5
|
+
export type AntigravityCatalog = {
|
|
6
|
+
models: ProviderModelConfig[];
|
|
7
|
+
routing: Record<string, AntigravityRouting>;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
type ThinkingLevel = ThinkingEffort;
|
|
11
|
+
|
|
12
|
+
type RuntimeGroup = {
|
|
13
|
+
publicId: string;
|
|
14
|
+
variants: Partial<Record<ThinkingLevel, string>>;
|
|
15
|
+
unsuffixed?: string;
|
|
16
|
+
displayNames: string[];
|
|
17
|
+
/** Catalog capability: true/false when advertised, undefined when omitted. */
|
|
18
|
+
supportsThinking?: boolean;
|
|
19
|
+
supportsImages?: boolean;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const THINKING_SUFFIXES: Array<{ suffix: string; level: ThinkingLevel }> = [
|
|
23
|
+
{ suffix: "extra-low", level: ThinkingEffort.Low },
|
|
24
|
+
{ suffix: "extra-high", level: ThinkingEffort.Xhigh },
|
|
25
|
+
{ suffix: "thinking", level: ThinkingEffort.High },
|
|
26
|
+
{ suffix: "minimal", level: ThinkingEffort.Minimal },
|
|
27
|
+
{ suffix: "medium", level: ThinkingEffort.Medium },
|
|
28
|
+
{ suffix: "high", level: ThinkingEffort.High },
|
|
29
|
+
{ suffix: "low", level: ThinkingEffort.Low },
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
const DISPLAY_LEVELS: Array<{ pattern: RegExp; level: ThinkingLevel }> = [
|
|
33
|
+
{ pattern: /\(\s*extra\s*low\s*\)/i, level: ThinkingEffort.Low },
|
|
34
|
+
{ pattern: /\(\s*extra\s*high\s*\)/i, level: ThinkingEffort.Xhigh },
|
|
35
|
+
{ pattern: /\(\s*thinking\s*\)/i, level: ThinkingEffort.High },
|
|
36
|
+
{ pattern: /\(\s*minimal\s*\)/i, level: ThinkingEffort.Minimal },
|
|
37
|
+
{ pattern: /\(\s*medium\s*\)/i, level: ThinkingEffort.Medium },
|
|
38
|
+
{ pattern: /\(\s*high\s*\)/i, level: ThinkingEffort.High },
|
|
39
|
+
{ pattern: /\(\s*low\s*\)/i, level: ThinkingEffort.Low },
|
|
40
|
+
];
|
|
41
|
+
|
|
42
|
+
/** Known backend aliases whose runtime IDs do not share a thinking suffix with the public family. */
|
|
43
|
+
const RUNTIME_ALIASES: Record<string, { publicId: string; level: ThinkingLevel }> = {
|
|
44
|
+
"gemini-3-flash-agent": { publicId: "gemini-3.5-flash", level: ThinkingEffort.High },
|
|
45
|
+
"gemini-pro-agent": { publicId: "gemini-3.1-pro", level: ThinkingEffort.High },
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const PI_LEVELS = [
|
|
49
|
+
ThinkingEffort.Off,
|
|
50
|
+
ThinkingEffort.Minimal,
|
|
51
|
+
ThinkingEffort.Low,
|
|
52
|
+
ThinkingEffort.Medium,
|
|
53
|
+
ThinkingEffort.High,
|
|
54
|
+
ThinkingEffort.Xhigh,
|
|
55
|
+
"max",
|
|
56
|
+
] as const;
|
|
57
|
+
|
|
58
|
+
const ZERO_COST = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
|
|
59
|
+
|
|
60
|
+
export function isSelectableRuntimeModelId(id: string): boolean {
|
|
61
|
+
if (!/^(gemini-|claude-|gpt-oss-)/i.test(id) || /\s/.test(id) || /^MODEL_/i.test(id)) {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
if (/^(chat_|tab_)/i.test(id)) return false;
|
|
65
|
+
if (/image/i.test(id)) return false;
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function resolvedCatalog(
|
|
70
|
+
discovered: AntigravityCatalog | undefined,
|
|
71
|
+
current: AntigravityCatalog,
|
|
72
|
+
): AntigravityCatalog {
|
|
73
|
+
if (discovered && discovered.models.length > 0) return discovered;
|
|
74
|
+
return current;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function buildAntigravityCatalog(
|
|
78
|
+
rawModels: Record<string, ModelInfoRaw>,
|
|
79
|
+
fallback: AntigravityCatalog,
|
|
80
|
+
): AntigravityCatalog {
|
|
81
|
+
const groups = new Map<string, RuntimeGroup>();
|
|
82
|
+
|
|
83
|
+
for (const [runtimeId, info] of Object.entries(rawModels)) {
|
|
84
|
+
if (!isSelectableRuntimeModelId(runtimeId)) continue;
|
|
85
|
+
if (info?.isInternal) continue;
|
|
86
|
+
|
|
87
|
+
const displayName = modelDisplayName(info);
|
|
88
|
+
if (runtimeId.endsWith("-tiered")) {
|
|
89
|
+
const baseId = runtimeId.slice(0, -"-tiered".length);
|
|
90
|
+
const group = ensureGroup(groups, baseId);
|
|
91
|
+
absorbMetadata(group, info, displayName);
|
|
92
|
+
if (!group.unsuffixed) group.unsuffixed = runtimeId;
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const alias = RUNTIME_ALIASES[runtimeId];
|
|
97
|
+
const suffix = alias ? undefined : parseThinkingSuffix(runtimeId);
|
|
98
|
+
const publicId = alias?.publicId ?? suffix?.baseId ?? runtimeId;
|
|
99
|
+
const group = ensureGroup(groups, publicId);
|
|
100
|
+
absorbMetadata(group, info, displayName);
|
|
101
|
+
|
|
102
|
+
const level = alias?.level ?? levelFromDisplayName(displayName) ?? suffix?.level;
|
|
103
|
+
if (level) group.variants[level] = runtimeId;
|
|
104
|
+
else group.unsuffixed = runtimeId;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
mergeAgentSingletons(groups);
|
|
108
|
+
|
|
109
|
+
if (groups.size === 0) return fallback;
|
|
110
|
+
|
|
111
|
+
const models: ProviderModelConfig[] = [];
|
|
112
|
+
const routing: Record<string, AntigravityRouting> = {};
|
|
113
|
+
|
|
114
|
+
for (const group of groups.values()) {
|
|
115
|
+
const fallbackModel = fallback.models.find((model) => model.id === group.publicId);
|
|
116
|
+
const fallbackRouting = fallback.routing[group.publicId];
|
|
117
|
+
if (fallbackModel && fallbackRouting) {
|
|
118
|
+
models.push(fallbackModel);
|
|
119
|
+
routing[group.publicId] = fallbackRouting;
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const synthesized = synthesizeModel(group, fallback.models);
|
|
124
|
+
models.push(synthesized.model);
|
|
125
|
+
routing[group.publicId] = synthesized.routing;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
for (const fallbackModel of fallback.models) {
|
|
129
|
+
if (routing[fallbackModel.id]) continue;
|
|
130
|
+
const fallbackRouting = fallback.routing[fallbackModel.id];
|
|
131
|
+
if (!fallbackRouting) continue;
|
|
132
|
+
models.push(fallbackModel);
|
|
133
|
+
routing[fallbackModel.id] = fallbackRouting;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
models.sort(comparePublicModels);
|
|
137
|
+
return { models, routing };
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function ensureGroup(groups: Map<string, RuntimeGroup>, publicId: string): RuntimeGroup {
|
|
141
|
+
const existing = groups.get(publicId);
|
|
142
|
+
if (existing) return existing;
|
|
143
|
+
const created: RuntimeGroup = {
|
|
144
|
+
publicId,
|
|
145
|
+
variants: {},
|
|
146
|
+
displayNames: [],
|
|
147
|
+
};
|
|
148
|
+
groups.set(publicId, created);
|
|
149
|
+
return created;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function absorbMetadata(
|
|
153
|
+
group: RuntimeGroup,
|
|
154
|
+
info: ModelInfoRaw | undefined,
|
|
155
|
+
displayName: string | undefined,
|
|
156
|
+
): void {
|
|
157
|
+
if (displayName) group.displayNames.push(displayName);
|
|
158
|
+
if (info?.supportsThinking === true) group.supportsThinking = true;
|
|
159
|
+
else if (info?.supportsThinking === false && group.supportsThinking !== true) {
|
|
160
|
+
group.supportsThinking = false;
|
|
161
|
+
}
|
|
162
|
+
if (info?.supportsImages === true) group.supportsImages = true;
|
|
163
|
+
if (info?.supportsImages === false && group.supportsImages === undefined) {
|
|
164
|
+
group.supportsImages = false;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function mergeAgentSingletons(groups: Map<string, RuntimeGroup>): void {
|
|
169
|
+
for (const [publicId, group] of [...groups.entries()]) {
|
|
170
|
+
if (!publicId.endsWith("-agent")) continue;
|
|
171
|
+
if (Object.keys(group.variants).length > 0) continue;
|
|
172
|
+
const family = displayFamily(group.displayNames[0]);
|
|
173
|
+
if (!family) continue;
|
|
174
|
+
const target = [...groups.values()].find(
|
|
175
|
+
(candidate) =>
|
|
176
|
+
candidate.publicId !== publicId &&
|
|
177
|
+
candidate.displayNames.some((name) => displayFamily(name) === family),
|
|
178
|
+
);
|
|
179
|
+
if (!target || !group.unsuffixed) continue;
|
|
180
|
+
const level = levelFromDisplayName(group.displayNames[0]) ?? ThinkingEffort.High;
|
|
181
|
+
target.variants[level] = group.unsuffixed;
|
|
182
|
+
absorbMetadata(target, { supportsThinking: group.supportsThinking }, group.displayNames[0]);
|
|
183
|
+
groups.delete(publicId);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function parseThinkingSuffix(
|
|
188
|
+
runtimeId: string,
|
|
189
|
+
): { baseId: string; level: ThinkingLevel } | undefined {
|
|
190
|
+
const lower = runtimeId.toLowerCase();
|
|
191
|
+
for (const { suffix, level } of THINKING_SUFFIXES) {
|
|
192
|
+
if (lower.endsWith(`-${suffix}`)) {
|
|
193
|
+
return { baseId: runtimeId.slice(0, -(suffix.length + 1)), level };
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return undefined;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function levelFromDisplayName(displayName: string | undefined): ThinkingLevel | undefined {
|
|
200
|
+
if (!displayName) return undefined;
|
|
201
|
+
for (const { pattern, level } of DISPLAY_LEVELS) {
|
|
202
|
+
if (pattern.test(displayName)) return level;
|
|
203
|
+
}
|
|
204
|
+
return undefined;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function modelDisplayName(info: ModelInfoRaw | undefined): string | undefined {
|
|
208
|
+
if (!info) return undefined;
|
|
209
|
+
if (typeof info.displayName === "string" && info.displayName) return info.displayName;
|
|
210
|
+
if (typeof info.label === "string" && info.label) return info.label;
|
|
211
|
+
if (typeof info.modelName === "string" && info.modelName) return info.modelName;
|
|
212
|
+
return undefined;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function displayFamily(displayName: string | undefined): string | undefined {
|
|
216
|
+
if (!displayName) return undefined;
|
|
217
|
+
return displayName
|
|
218
|
+
.replace(/\s*\((?:extra\s*low|extra\s*high|low|medium|high|minimal|thinking)\)\s*$/i, "")
|
|
219
|
+
.trim()
|
|
220
|
+
.toLowerCase();
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
function synthesizeModel(
|
|
224
|
+
group: RuntimeGroup,
|
|
225
|
+
fallbackModels: ProviderModelConfig[],
|
|
226
|
+
): { model: ProviderModelConfig; routing: AntigravityRouting } {
|
|
227
|
+
const template = familyTemplate(group.publicId, fallbackModels);
|
|
228
|
+
const advertisedLevels = advertisedThinkingLevels(group);
|
|
229
|
+
const routing = routingFromVariants(group.publicId, group.variants, group.unsuffixed);
|
|
230
|
+
const supportsImages = group.supportsImages ?? template?.input.includes("image") ?? true;
|
|
231
|
+
const reasoning =
|
|
232
|
+
advertisedLevels.size > 0 ||
|
|
233
|
+
group.supportsThinking === true ||
|
|
234
|
+
(group.supportsThinking === undefined && Boolean(template?.reasoning));
|
|
235
|
+
return {
|
|
236
|
+
model: {
|
|
237
|
+
id: group.publicId,
|
|
238
|
+
name: publicModelName(group),
|
|
239
|
+
reasoning,
|
|
240
|
+
thinkingLevelMap: reasoning ? thinkingLevelMapFromLevels(advertisedLevels) : undefined,
|
|
241
|
+
input: supportsImages ? ["text", "image"] : ["text"],
|
|
242
|
+
cost: template?.cost ?? ZERO_COST,
|
|
243
|
+
contextWindow: template?.contextWindow ?? 128000,
|
|
244
|
+
maxTokens: template?.maxTokens ?? 8192,
|
|
245
|
+
},
|
|
246
|
+
routing,
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
function advertisedThinkingLevels(group: RuntimeGroup): Set<string> {
|
|
251
|
+
const levels = new Set(Object.keys(group.variants));
|
|
252
|
+
if (levels.size > 0) return levels;
|
|
253
|
+
// Explicit false from the catalog must not grow a fake High control.
|
|
254
|
+
if (group.supportsThinking === false) return levels;
|
|
255
|
+
if (group.supportsThinking === true || group.unsuffixed) {
|
|
256
|
+
levels.add(ThinkingEffort.High);
|
|
257
|
+
}
|
|
258
|
+
return levels;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
function routingFromVariants(
|
|
262
|
+
publicId: string,
|
|
263
|
+
variants: Partial<Record<ThinkingLevel, string>>,
|
|
264
|
+
unsuffixed?: string,
|
|
265
|
+
): AntigravityRouting {
|
|
266
|
+
const defaultRequestId =
|
|
267
|
+
variants[ThinkingEffort.Low] ??
|
|
268
|
+
variants[ThinkingEffort.Minimal] ??
|
|
269
|
+
variants[ThinkingEffort.Medium] ??
|
|
270
|
+
variants[ThinkingEffort.High] ??
|
|
271
|
+
unsuffixed ??
|
|
272
|
+
publicId;
|
|
273
|
+
|
|
274
|
+
const pick = (...keys: ThinkingLevel[]): string => {
|
|
275
|
+
for (const key of keys) {
|
|
276
|
+
const id = variants[key];
|
|
277
|
+
if (id) return id;
|
|
278
|
+
}
|
|
279
|
+
return unsuffixed ?? defaultRequestId;
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
return {
|
|
283
|
+
off: pick(
|
|
284
|
+
ThinkingEffort.Low,
|
|
285
|
+
ThinkingEffort.Minimal,
|
|
286
|
+
ThinkingEffort.Medium,
|
|
287
|
+
ThinkingEffort.High,
|
|
288
|
+
),
|
|
289
|
+
routing: {
|
|
290
|
+
minimal: pick(
|
|
291
|
+
ThinkingEffort.Minimal,
|
|
292
|
+
ThinkingEffort.Low,
|
|
293
|
+
ThinkingEffort.Medium,
|
|
294
|
+
ThinkingEffort.High,
|
|
295
|
+
),
|
|
296
|
+
low: pick(
|
|
297
|
+
ThinkingEffort.Low,
|
|
298
|
+
ThinkingEffort.Minimal,
|
|
299
|
+
ThinkingEffort.Medium,
|
|
300
|
+
ThinkingEffort.High,
|
|
301
|
+
),
|
|
302
|
+
medium: pick(
|
|
303
|
+
ThinkingEffort.Medium,
|
|
304
|
+
ThinkingEffort.Low,
|
|
305
|
+
ThinkingEffort.High,
|
|
306
|
+
ThinkingEffort.Minimal,
|
|
307
|
+
),
|
|
308
|
+
high: pick(
|
|
309
|
+
ThinkingEffort.High,
|
|
310
|
+
ThinkingEffort.Medium,
|
|
311
|
+
ThinkingEffort.Low,
|
|
312
|
+
ThinkingEffort.Minimal,
|
|
313
|
+
),
|
|
314
|
+
xhigh: pick(
|
|
315
|
+
ThinkingEffort.Xhigh,
|
|
316
|
+
ThinkingEffort.High,
|
|
317
|
+
ThinkingEffort.Medium,
|
|
318
|
+
ThinkingEffort.Low,
|
|
319
|
+
),
|
|
320
|
+
},
|
|
321
|
+
defaultRequestId,
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
function thinkingLevelMapFromLevels(levels: Set<string>): ProviderModelConfig["thinkingLevelMap"] {
|
|
326
|
+
const map: NonNullable<ProviderModelConfig["thinkingLevelMap"]> = {};
|
|
327
|
+
for (const level of PI_LEVELS) {
|
|
328
|
+
map[level] = levels.has(level) ? level : null;
|
|
329
|
+
}
|
|
330
|
+
if (levels.size === 0) map.high = "high";
|
|
331
|
+
return map;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
function familyTemplate(
|
|
335
|
+
publicId: string,
|
|
336
|
+
fallbackModels: ProviderModelConfig[],
|
|
337
|
+
): ProviderModelConfig | undefined {
|
|
338
|
+
if (/^gemini-.*-flash/i.test(publicId)) {
|
|
339
|
+
return fallbackModels.find((model) => /^gemini-.*-flash/i.test(model.id));
|
|
340
|
+
}
|
|
341
|
+
if (/^gemini-.*-pro/i.test(publicId)) {
|
|
342
|
+
return fallbackModels.find((model) => /^gemini-.*-pro/i.test(model.id));
|
|
343
|
+
}
|
|
344
|
+
if (publicId.startsWith("claude-opus")) {
|
|
345
|
+
return fallbackModels.find((model) => model.id.startsWith("claude-opus"));
|
|
346
|
+
}
|
|
347
|
+
if (publicId.startsWith("claude-")) {
|
|
348
|
+
return (
|
|
349
|
+
fallbackModels.find((model) => model.id.startsWith("claude-sonnet")) ??
|
|
350
|
+
fallbackModels.find((model) => model.id.startsWith("claude-"))
|
|
351
|
+
);
|
|
352
|
+
}
|
|
353
|
+
if (publicId.startsWith("gpt-oss")) {
|
|
354
|
+
return fallbackModels.find((model) => model.id.startsWith("gpt-oss"));
|
|
355
|
+
}
|
|
356
|
+
if (publicId.startsWith("gemini-")) {
|
|
357
|
+
return fallbackModels.find((model) => model.id.startsWith("gemini-"));
|
|
358
|
+
}
|
|
359
|
+
return undefined;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
function publicModelName(group: RuntimeGroup): string {
|
|
363
|
+
const family = group.displayNames.map((name) => displayFamily(name)).find(Boolean);
|
|
364
|
+
if (family) {
|
|
365
|
+
return `${titleCase(family)} (Antigravity)`;
|
|
366
|
+
}
|
|
367
|
+
return `${humanizePublicId(group.publicId)} (Antigravity)`;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
function titleCase(value: string): string {
|
|
371
|
+
return value.replace(/\b([a-z])/g, (char) => char.toUpperCase());
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
export function humanizePublicId(id: string): string {
|
|
375
|
+
const tokens = id.split("-");
|
|
376
|
+
const words: string[] = [];
|
|
377
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
378
|
+
const token = tokens[i];
|
|
379
|
+
if (!token) continue;
|
|
380
|
+
const next = tokens[i + 1];
|
|
381
|
+
if (token === "gpt" && next === "oss") {
|
|
382
|
+
words.push("GPT-OSS");
|
|
383
|
+
i++;
|
|
384
|
+
continue;
|
|
385
|
+
}
|
|
386
|
+
if (/^\d+$/.test(token) && next && /^\d+$/.test(next)) {
|
|
387
|
+
words.push(`${token}.${next}`);
|
|
388
|
+
i++;
|
|
389
|
+
continue;
|
|
390
|
+
}
|
|
391
|
+
if (/^\d/.test(token)) {
|
|
392
|
+
words.push(token.toUpperCase());
|
|
393
|
+
continue;
|
|
394
|
+
}
|
|
395
|
+
words.push(token.charAt(0).toUpperCase() + token.slice(1));
|
|
396
|
+
}
|
|
397
|
+
return words.join(" ");
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
function parseGeminiVersion(id: string): number {
|
|
401
|
+
const match = id.match(/^gemini-(\d+)(?:\.(\d+))?/i);
|
|
402
|
+
if (!match) return 0;
|
|
403
|
+
return Number(match[1]) * 1000 + Number(match[2] || 0);
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
function comparePublicModels(a: ProviderModelConfig, b: ProviderModelConfig): number {
|
|
407
|
+
const rankA = modelRank(a.id);
|
|
408
|
+
const rankB = modelRank(b.id);
|
|
409
|
+
if (rankA[0] !== rankB[0]) return rankA[0] - rankB[0];
|
|
410
|
+
if (rankA[1] !== rankB[1]) return rankA[1] - rankB[1];
|
|
411
|
+
return a.id.localeCompare(b.id);
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
function modelRank(id: string): [number, number] {
|
|
415
|
+
const version = parseGeminiVersion(id);
|
|
416
|
+
if (/^gemini-.*flash/i.test(id) && !/pro/i.test(id)) return [0, -version];
|
|
417
|
+
if (id.startsWith("claude-opus")) return [1, 0];
|
|
418
|
+
if (id.startsWith("claude-sonnet")) return [2, 0];
|
|
419
|
+
if (id.startsWith("claude-")) return [3, 0];
|
|
420
|
+
if (/^gemini-.*pro/i.test(id)) return [4, -version];
|
|
421
|
+
if (id.startsWith("gemini-")) return [5, -version];
|
|
422
|
+
if (id.startsWith("gpt-oss")) return [6, 0];
|
|
423
|
+
return [7, 0];
|
|
424
|
+
}
|