pi-provider-antigravity 0.13.0 → 0.14.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/README.md CHANGED
@@ -22,7 +22,7 @@ Use Google Antigravity models directly in [Pi](https://pi.dev).
22
22
 
23
23
  ## Requirements
24
24
 
25
- - Pi >= 0.80.0
25
+ - Pi >= 0.86.0 (For Pi 0.80.0 ~ 0.85.x, see [Legacy Pi Support](#legacy-pi-support))
26
26
  - A Google account with Antigravity access
27
27
 
28
28
  ## Installation
@@ -37,6 +37,20 @@ Or try it without installing:
37
37
  pi -e npm:pi-provider-antigravity
38
38
  ```
39
39
 
40
+ ### Legacy Pi Support
41
+
42
+ For Pi 0.80.0 ~ 0.85.x, install the compatible `0.13.0` release:
43
+
44
+ ```bash
45
+ pi install npm:pi-provider-antigravity@0.13.0
46
+ ```
47
+
48
+ Or try it without installing:
49
+
50
+ ```bash
51
+ pi -e npm:pi-provider-antigravity@0.13.0
52
+ ```
53
+
40
54
  ## Quick Start
41
55
 
42
56
  1. Authenticate:
package/dist/index.js CHANGED
@@ -1389,6 +1389,13 @@ import {
1389
1389
 
1390
1390
  // src/builder.ts
1391
1391
  import { createHash as createHash2, randomUUID } from "node:crypto";
1392
+ import {
1393
+ collapseSystemMessages,
1394
+ getCurrentSystemPrompt,
1395
+ getCurrentTools,
1396
+ normalizeContext,
1397
+ withoutInitialSystemMessage
1398
+ } from "@earendil-works/pi-ai";
1392
1399
  var BASE64_SIGNATURE_PATTERN = /^[A-Za-z0-9+/_-]+={0,2}$/;
1393
1400
  var SKIP_THOUGHT_SIGNATURE_VALIDATOR = "skip_thought_signature_validator";
1394
1401
  function isValidThoughtSignature(sig) {
@@ -1400,11 +1407,11 @@ function resolveThoughtSignature(isSameProviderAndModel, sig) {
1400
1407
  if (!isSameProviderAndModel) return void 0;
1401
1408
  return isValidThoughtSignature(sig) ? sig : void 0;
1402
1409
  }
1403
- function deriveSessionId(context, explicitSessionId) {
1410
+ function deriveSessionId(conversation, explicitSessionId) {
1404
1411
  if (explicitSessionId && typeof explicitSessionId === "string" && explicitSessionId.trim().length > 0) {
1405
1412
  return explicitSessionId.trim();
1406
1413
  }
1407
- const firstMsg = context.messages?.[0];
1414
+ const firstMsg = conversation?.[0];
1408
1415
  if (!firstMsg) {
1409
1416
  return randomUUID();
1410
1417
  }
@@ -1497,9 +1504,9 @@ function convertTools(tools) {
1497
1504
  }
1498
1505
  ];
1499
1506
  }
1500
- function translateTurnTrace(context, runtimeModelId) {
1507
+ function translateTurnTrace(conversation, runtimeModelId) {
1501
1508
  const contents = [];
1502
- const messages = context.messages || [];
1509
+ const messages = conversation || [];
1503
1510
  const isGeminiRequest = classifyModelFamily(runtimeModelId) === "gemini";
1504
1511
  const isGptRequest = classifyModelFamily(runtimeModelId) === "gpt";
1505
1512
  for (const msg of messages) {
@@ -1690,9 +1697,13 @@ function buildAntigravityRequestBody(params) {
1690
1697
  maxOutputTokens = 65536
1691
1698
  } = params;
1692
1699
  const runtimeModelId = plan.runtimeModelId;
1693
- const sessionId = deriveSessionId(context, params.sessionId);
1700
+ const transcript = collapseSystemMessages(context);
1701
+ const systemPrompt = getCurrentSystemPrompt(transcript.messages);
1702
+ const tools = convertTools(getCurrentTools(transcript.messages));
1703
+ const conversation = withoutInitialSystemMessage(transcript.messages);
1704
+ const sessionId = deriveSessionId(conversation, params.sessionId);
1694
1705
  const trajectoryId = params.trajectoryId && typeof params.trajectoryId === "string" && params.trajectoryId.trim().length > 0 ? params.trajectoryId.trim() : resolveSessionTrajectory(sessionId);
1695
- const contents = translateTurnTrace(context, runtimeModelId);
1706
+ const contents = translateTurnTrace(conversation, runtimeModelId);
1696
1707
  const requestIndex = contents.filter(
1697
1708
  (c) => c.role === "model" && !c.parts?.some((p) => p.functionResponse)
1698
1709
  ).length;
@@ -1714,13 +1725,12 @@ function buildAntigravityRequestBody(params) {
1714
1725
  const request = {
1715
1726
  contents
1716
1727
  };
1717
- if (context.systemPrompt) {
1728
+ if (systemPrompt) {
1718
1729
  request.systemInstruction = {
1719
1730
  role: "user",
1720
- parts: [{ text: context.systemPrompt }]
1731
+ parts: [{ text: systemPrompt }]
1721
1732
  };
1722
1733
  }
1723
- const tools = convertTools(context.tools);
1724
1734
  if (tools) {
1725
1735
  request.tools = tools;
1726
1736
  }
@@ -1792,6 +1802,9 @@ function processLine(rawLine, state, onEvent) {
1792
1802
  return;
1793
1803
  }
1794
1804
  const response = payload.response || payload;
1805
+ if (response.responseId && !state.responseId) {
1806
+ state.responseId = response.responseId;
1807
+ }
1795
1808
  if (response.usageMetadata) {
1796
1809
  const um = response.usageMetadata;
1797
1810
  const promptTokens = typeof um.promptTokenCount === "number" ? um.promptTokenCount : 0;
@@ -1912,6 +1925,9 @@ async function consumeAntigravityStream(streamBody, output, stream, modelCost) {
1912
1925
  total: inputCost + outputCost + cacheCost
1913
1926
  };
1914
1927
  }
1928
+ if (state.responseId) {
1929
+ output.responseId ||= state.responseId;
1930
+ }
1915
1931
  output.stopReason = state.stopReason;
1916
1932
  };
1917
1933
  const dispatchEvent = (ev) => {
@@ -1960,7 +1976,7 @@ function streamAntigravity(model, context, options, catalog) {
1960
1976
  context,
1961
1977
  sessionId: options?.sessionId,
1962
1978
  trajectoryId,
1963
- maxOutputTokens: model.maxTokens,
1979
+ maxOutputTokens: options?.maxTokens ?? model.maxTokens,
1964
1980
  toolChoice: options?.toolChoice
1965
1981
  });
1966
1982
  const streamBody = await postAntigravityStream({
package/dist/index.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/index.ts", "../src/auth.ts", "../src/protocol.ts", "../src/model-identity.ts", "../src/model-catalog.ts", "../src/config.ts", "../src/quota-status.ts", "../src/stream.ts", "../src/builder.ts", "../src/search.ts", "../src/commands.ts"],
4
- "sourcesContent": ["import type { ExtensionAPI, ExtensionCommandContext } from \"@earendil-works/pi-coding-agent\";\nimport { Type } from \"@earendil-works/pi-ai\";\nimport { loginAntigravity, refreshAntigravityToken, getApiKey, resolveCredentials } from \"./auth.ts\";\nimport { DEFAULT_ENDPOINT, PROVIDER_ID } from \"./protocol.ts\";\nimport { createModelCatalog } from \"./model-catalog.ts\";\nimport { QuotaStatusCoordinator, registerQuotaSettings } from \"./quota-status.ts\";\nimport { streamAntigravity } from \"./stream.ts\";\nimport { completeSubcommands, runAntigravitySubcommand } from \"./commands.ts\";\nimport { performWebSearch } from \"./search.ts\";\n\nexport { PROVIDER_ID };\nexport const PROVIDER_NAME = \"Antigravity\";\n\nexport default function (pi: ExtensionAPI): void {\n const quotaStatus = new QuotaStatusCoordinator();\n registerQuotaSettings(quotaStatus);\n // The one deep Model Catalog seam for this extension: handles Pi refreshModels,\n // Model Plan resolution for streaming, and CLI formatting for subcommands.\n const catalog = createModelCatalog();\n\n pi.registerProvider(PROVIDER_ID, {\n name: PROVIDER_NAME,\n baseUrl: DEFAULT_ENDPOINT,\n api: \"antigravity-api\",\n models: [], // Purely dynamic provider per Pi SDK architecture\n oauth: {\n name: PROVIDER_NAME,\n login: loginAntigravity,\n refreshToken: refreshAntigravityToken,\n getApiKey,\n },\n streamSimple: (model, context, options) => streamAntigravity(model, context, options, catalog),\n refreshModels: async (context) => catalog.refresh(context),\n });\n\n pi.registerCommand(\"antigravity\", {\n description: \"Antigravity quota, models and settings\",\n getArgumentCompletions: (prefix) => completeSubcommands(prefix),\n handler: async (args: string, ctx: ExtensionCommandContext) => {\n await runAntigravitySubcommand(args, ctx, quotaStatus, catalog);\n },\n });\n\n if (typeof pi.registerTool === \"function\") {\n pi.registerTool({\n name: \"antigravity_websearch\",\n label: \"Antigravity Web Search\",\n description:\n \"Performs a web search for a given query. Returns a summary of relevant information along with URL citations.\",\n promptSnippet: \"Search the web using Google Search Grounding with source citations\",\n promptGuidelines: [\n \"Use antigravity_websearch when you need real-time web search, latest documentation, or up-to-date facts with verified citations.\",\n ],\n parameters: Type.Object({\n query: Type.String({ description: \"The search query string to look up on the web.\" }),\n domain: Type.Optional(\n Type.String({\n description: \"Optional domain to recommend the search prioritize (e.g. 'github.com', 'developer.mozilla.org').\",\n }),\n ),\n }),\n async execute(_toolCallId, params, signal, _onUpdate, ctx) {\n const creds = await resolveCredentials(ctx);\n if (!creds) {\n return {\n content: [{ type: \"text\", text: \"Error: Not logged in. Run /login antigravity first.\" }],\n details: { error: \"not_logged_in\" },\n };\n }\n try {\n const result = await performWebSearch(creds, {\n query: params.query,\n domain: params.domain,\n signal,\n });\n return {\n content: [{ type: \"text\", text: result.formattedOutput }],\n details: {\n sources: result.sources,\n queries: result.queries,\n },\n };\n } catch (err: any) {\n return {\n content: [{ type: \"text\", text: `Search failed: ${err.message}` }],\n details: { error: err.message },\n };\n }\n },\n });\n }\n\n // Footer quota slot: paint cached text instantly, refresh in background.\n pi.on(\"session_start\", async (_event, ctx) => {\n await quotaStatus.refreshAndPaint(ctx);\n });\n\n // Model switch changes which Quota Pool backs the footer \u2014 repaint instantly,\n // then fill in fresh text when switching (back) to an Antigravity model.\n pi.on(\"model_select\", async (event, ctx) => {\n const modelCtx = {\n ui: ctx.ui,\n modelRegistry: ctx.modelRegistry,\n model: event.model || ctx.model,\n };\n await quotaStatus.refreshAndPaint(modelCtx);\n });\n\n // Turn settled: refresh only when the throttle window expired.\n pi.on(\"agent_settled\", async (_event, ctx) => {\n await quotaStatus.refreshAndPaint(ctx);\n });\n}\n", "import { createHash, randomBytes } from \"node:crypto\";\nimport type { OAuthCredentials, OAuthLoginCallbacks } from \"@earendil-works/pi-ai\";\nimport { postAntigravityJson, PROVIDER_ID } from \"./protocol.ts\";\n\nexport interface AntigravityCredentials {\n token: string;\n projectId: string;\n}\n\nexport type CredentialSource =\n | { modelRegistry?: { getApiKeyForProvider?: (provider: string) => Promise<string | undefined> } }\n | { apiKey?: string }\n | { credential?: { access?: string; type?: string } }\n | string\n | null\n | undefined;\n\nexport const REDIRECT_URI = \"https://antigravity.google/oauth-callback\";\nexport const AUTH_URL = \"https://accounts.google.com/o/oauth2/auth\";\nexport const TOKEN_URL = \"https://oauth2.googleapis.com/token\";\nexport const OAUTH_CALLBACK_TIMEOUT_MS = 5 * 60 * 1000;\nexport const FALLBACK_PROJECT_ID = \"aicode-consumers\";\n\nexport const SCOPES = [\n \"https://www.googleapis.com/auth/cloud-platform\",\n \"https://www.googleapis.com/auth/userinfo.email\",\n \"https://www.googleapis.com/auth/userinfo.profile\",\n \"https://www.googleapis.com/auth/cclog\",\n \"https://www.googleapis.com/auth/experimentsandconfigs\",\n \"https://www.googleapis.com/auth/aicode\",\n \"openid\",\n];\n\nexport const CLIENT_ID =\n process.env.ANTIGRAVITY_CLIENT_ID ||\n Buffer.from(\n \"MTA3MTAwNjA2MDU5MS10bWhzc2luMmgyMWxjcmUyMzV2dG9sb2poNGc0MDNlcC5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbQ==\",\n \"base64\"\n ).toString(\"utf-8\");\n\nexport const CLIENT_SECRET =\n process.env.ANTIGRAVITY_CLIENT_SECRET ||\n Buffer.from(\"R09DU1BYLUs1OEZXUjQ4NkxkTEoxbUxCOHNYQzR6NnFEQWY=\", \"base64\").toString(\"utf-8\");\n\nfunction base64Url(buf: Buffer): string {\n return buf.toString(\"base64url\");\n}\n\nexport function extractCodeFromInput(rawInput: string): string {\n let code = rawInput.trim();\n if (!code) {\n throw new Error(\"No authorization code provided\");\n }\n\n if (code.startsWith(\"code=\")) {\n code = code.slice(5).trim();\n if (!code) {\n throw new Error(\"No authorization code provided\");\n }\n }\n\n // Reject callback URLs and other non-code input here instead of passing\n // garbage downstream (Google rejects those with a bare invalid_grant).\n // Note: real codes contain \"/\" (e.g. \"4/0ATs\u2026\"), so only reject\n // characters a code can never contain.\n if (/[\\s:?#&=%+]/.test(code)) {\n throw new Error(\"Invalid authorization code: paste the code value itself, not the callback URL\");\n }\n\n return code;\n}\n\nfunction generatePKCE(): { verifier: string; challenge: string } {\n const verifier = base64Url(randomBytes(32));\n const challenge = base64Url(createHash(\"sha256\").update(verifier).digest());\n return { verifier, challenge };\n}\n\nexport async function fetchProjectId(token: string, signal?: AbortSignal): Promise<string> {\n try {\n const data = await postAntigravityJson<{ cloudaicompanionProject?: string }>({\n auth: token,\n path: \"v1internal:loadCodeAssist\",\n body: { metadata: { ideType: \"ANTIGRAVITY\" } },\n signal,\n });\n if (data.cloudaicompanionProject) {\n return data.cloudaicompanionProject;\n }\n } catch {\n // Fall back to standard project\n }\n return FALLBACK_PROJECT_ID;\n}\n\nexport async function loginAntigravity(callbacks: OAuthLoginCallbacks): Promise<OAuthCredentials> {\n const { verifier, challenge } = generatePKCE();\n // state is sent for OAuth wire parity, but never validated back:\n // with code-only paste the callback URL (and its state) never reaches us.\n const state = randomBytes(16).toString(\"hex\");\n\n const authParams = new URLSearchParams({\n client_id: CLIENT_ID,\n response_type: \"code\",\n redirect_uri: REDIRECT_URI,\n scope: SCOPES.join(\" \"),\n code_challenge: challenge,\n code_challenge_method: \"S256\",\n state,\n access_type: \"offline\",\n prompt: \"consent\",\n });\n\n const authUrl = `${AUTH_URL}?${authParams.toString()}`;\n callbacks.onAuth({ url: authUrl });\n\n const manualPromptPromise = (async () => {\n const input = await callbacks.onPrompt({\n message: \"Paste authorization code from browser:\",\n });\n return extractCodeFromInput(input);\n })();\n\n const timeout = new Promise<never>((_, rej) =>\n setTimeout(() => rej(new Error(\"Timed out waiting for authorization code (5 minutes)\")), OAUTH_CALLBACK_TIMEOUT_MS)\n );\n\n const code = await Promise.race([manualPromptPromise, timeout]);\n\n const tokenParams = new URLSearchParams({\n client_id: CLIENT_ID,\n client_secret: CLIENT_SECRET,\n code,\n grant_type: \"authorization_code\",\n redirect_uri: REDIRECT_URI,\n code_verifier: verifier,\n });\n\n const tokenRes = await fetch(TOKEN_URL, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: tokenParams.toString(),\n });\n\n if (!tokenRes.ok) {\n const errText = await tokenRes.text();\n throw new Error(`Failed to exchange token (${tokenRes.status}): ${errText}`);\n }\n\n const tokens = (await tokenRes.json()) as {\n access_token: string;\n refresh_token?: string;\n expires_in?: number;\n };\n const projectId = await fetchProjectId(tokens.access_token);\n\n return {\n refresh: tokens.refresh_token || \"\",\n access: JSON.stringify({ token: tokens.access_token, projectId }),\n expires: Date.now() + (tokens.expires_in || 3600) * 1000,\n };\n}\n\nexport async function refreshAntigravityToken(\n credentials: OAuthCredentials,\n signal?: AbortSignal\n): Promise<OAuthCredentials> {\n const params = new URLSearchParams({\n client_id: CLIENT_ID,\n client_secret: CLIENT_SECRET,\n refresh_token: credentials.refresh,\n grant_type: \"refresh_token\",\n });\n\n const res = await fetch(TOKEN_URL, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: params.toString(),\n signal,\n });\n\n if (!res.ok) {\n const errText = await res.text();\n throw new Error(`Failed to refresh token (${res.status}): ${errText}`);\n }\n\n const tokens = (await res.json()) as {\n access_token: string;\n refresh_token?: string;\n expires_in?: number;\n };\n\n let existingProjectId = FALLBACK_PROJECT_ID;\n try {\n const parsed = JSON.parse(credentials.access);\n if (parsed.projectId) existingProjectId = parsed.projectId;\n } catch {\n // ignore\n }\n\n // Re-resolve: a login-time lookup failure pins the \"aicode-consumers\"\n // default forever unless refresh retries it. A failed lookup yields that\n // same default, which must never clobber a known value.\n const freshProjectId = await fetchProjectId(tokens.access_token, signal);\n const projectId = freshProjectId !== FALLBACK_PROJECT_ID ? freshProjectId : existingProjectId;\n\n return {\n refresh: tokens.refresh_token || credentials.refresh,\n access: JSON.stringify({ token: tokens.access_token, projectId }),\n expires: Date.now() + (tokens.expires_in || 3600) * 1000,\n };\n}\n\nexport function getApiKey(credentials: OAuthCredentials): string {\n return credentials.access;\n}\n\n/**\n * Deep credential resolution seam: extracts and normalizes Antigravity credentials\n * ({ token, projectId }) from any Pi context (command context, model registry,\n * stream options, refresh context, or raw API key strings).\n * Returns null when credentials are not found.\n */\nexport async function resolveCredentials(\n source: CredentialSource\n): Promise<AntigravityCredentials | null> {\n if (!source) return null;\n\n let raw: string | undefined;\n\n if (typeof source === \"string\") {\n raw = source.trim();\n } else if (typeof source === \"object\") {\n if (\"modelRegistry\" in source && source.modelRegistry?.getApiKeyForProvider) {\n raw = await source.modelRegistry.getApiKeyForProvider(PROVIDER_ID);\n } else if (\"apiKey\" in source && typeof source.apiKey === \"string\") {\n raw = source.apiKey;\n } else if (\"credential\" in source && source.credential) {\n raw = source.credential.type === \"oauth\" || !source.credential.type\n ? source.credential.access\n : undefined;\n }\n }\n\n if (!raw || typeof raw !== \"string\" || !raw.trim()) {\n return null;\n }\n\n const parsed = parseStoredCredentials(raw);\n if (!parsed.token || !parsed.token.trim()) {\n return null;\n }\n return parsed;\n}\n\n/**\n * One wording for the one state: the request path (\"I am not signed in\") and the\n * subcommands say the same thing, so a user learns it once.\n */\nexport const NOT_LOGGED_IN = \"Not logged in. Run /login antigravity first.\";\n\n/**\n * Ensures credentials exist or throws a clear error message.\n */\nexport async function requireCredentials(\n source: CredentialSource,\n errorMessage = NOT_LOGGED_IN\n): Promise<AntigravityCredentials> {\n const creds = await resolveCredentials(source);\n if (!creds) {\n throw new Error(errorMessage);\n }\n return creds;\n}\n\nexport function parseStoredCredentials(rawApiKey: string): AntigravityCredentials {\n try {\n const parsed = JSON.parse(rawApiKey);\n if (parsed.token) {\n return { token: parsed.token, projectId: parsed.projectId || FALLBACK_PROJECT_ID };\n }\n } catch {\n // If plain token\n }\n return { token: rawApiKey, projectId: FALLBACK_PROJECT_ID };\n}\n", "export const DEFAULT_ENDPOINT = \"https://daily-cloudcode-pa.googleapis.com\";\nexport const DEFAULT_USER_AGENT =\n \"antigravity/cli/1.2.5 (aidev_client; os_type=linux; arch=amd64; cl=982839923; auth_method=consumer)\";\n\nexport const PROVIDER_ID = \"antigravity\";\n\n/**\n * Structured error thrown when an Antigravity HTTP endpoint responds with a non-2xx status code.\n * Preserves status, endpoint path, and raw error body for error inspection without string parsing.\n */\nexport class AntigravityHttpError extends Error {\n readonly status: number;\n readonly path: string;\n readonly errorBody: string;\n\n constructor(status: number, path: string, errorBody: string) {\n super(`Antigravity request to ${path} failed (${status}): ${errorBody}`);\n this.name = \"AntigravityHttpError\";\n this.status = status;\n this.path = path;\n this.errorBody = errorBody;\n }\n}\n\nexport interface AntigravityPostParams {\n auth: string | { token: string };\n /** Path below the endpoint, e.g. \"v1internal:retrieveUserQuotaSummary\". */\n path: string;\n body: unknown;\n signal?: AbortSignal;\n}\n\nfunction resolveToken(auth: string | { token: string }): string {\n if (typeof auth === \"string\") return auth;\n if (auth && typeof auth.token === \"string\") return auth.token;\n throw new Error(\"Invalid auth parameter: missing token string\");\n}\n\nasync function postAntigravityRaw({\n auth,\n path,\n body,\n signal,\n}: AntigravityPostParams): Promise<Response> {\n const token = resolveToken(auth);\n return fetch(`${DEFAULT_ENDPOINT}/${path}`, {\n method: \"POST\",\n headers: buildAntigravityHeaders(token),\n body: JSON.stringify(body),\n signal,\n });\n}\n\n/**\n * Deep protocol JSON client: validates HTTP status, decodes JSON payloads,\n * and throws structured AntigravityHttpError on failures.\n */\nexport async function postAntigravityJson<T>(params: AntigravityPostParams): Promise<T> {\n const res = await postAntigravityRaw(params);\n if (!res.ok) {\n const errText = await res.text();\n throw new AntigravityHttpError(res.status, params.path, errText);\n }\n return (await res.json()) as T;\n}\n\n/**\n * Deep protocol stream client: validates HTTP status, checks stream presence,\n * and returns the validated ReadableStream.\n */\nexport async function postAntigravityStream(\n params: AntigravityPostParams\n): Promise<ReadableStream<Uint8Array>> {\n const res = await postAntigravityRaw(params);\n if (!res.ok) {\n const errText = await res.text();\n throw new AntigravityHttpError(res.status, params.path, errText);\n }\n if (!res.body) {\n throw new Error(`No response stream received from Antigravity for ${params.path}.`);\n }\n return res.body;\n}\n\n/**\n * Builds the canonical HTTP request headers for the Antigravity Wire Fingerprint.\n */\nexport function buildAntigravityHeaders(token: string, userAgent = DEFAULT_USER_AGENT): Record<string, string> {\n return {\n Host: \"daily-cloudcode-pa.googleapis.com\",\n \"User-Agent\": userAgent,\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${token}`,\n };\n}\n\n", "/**\n * Pure domain module encapsulating Model Family classification across\n * Turn Trace request construction, Quota Pool grouping, and Model Catalog resolution.\n */\n\nexport type ModelFamily = \"gemini\" | \"claude\" | \"gpt\" | \"unknown\";\n\n/**\n * The single model-identity predicate: which\n * family a model ID belongs to. Accepts any ID space \u2014 Public or Runtime\n * Model ID, with or without a `provider/` prefix \u2014 by stripping the prefix\n * before the prefix match, so every caller classifies identically. Unknown\n * (including missing) IDs report \"unknown\"; mapping that onto a Quota Pool\n * or plan flags stays with the consumer, preserving each caller's default.\n */\nexport function classifyModelFamily(modelId?: string): ModelFamily {\n const bare = ((modelId || \"\").split(\"/\").pop() || \"\").toLowerCase();\n if (bare.startsWith(\"gemini-\")) return \"gemini\";\n if (bare.startsWith(\"claude-\")) return \"claude\";\n if (bare.startsWith(\"gpt-\")) return \"gpt\";\n return \"unknown\";\n}\n\n/**\n * Checks Model Family compatibility for thoughtSignature replay.\n * Protocol specifications demonstrate that:\n * - Gemini models (gemini-3.7, gemini-3.8, etc.) share thoughtSignatures seamlessly.\n * - Claude models replay thoughtSignatures within the Claude family, part-split like Gemini.\n * - Non-Gemini models (Claude, GPT-OSS) do NOT share signatures with Gemini models.\n */\nexport function isCompatibleFamily(msgModel?: string, targetModelId?: string): boolean {\n if (!msgModel || !targetModelId) return true;\n if (msgModel === targetModelId) return true;\n\n const msgFamily = classifyModelFamily(msgModel);\n if (msgFamily !== \"unknown\" && msgFamily === classifyModelFamily(targetModelId)) return true;\n\n return false;\n}\n", "import type { Model, RefreshModelsContext } from \"@earendil-works/pi-ai\";\nimport { resolveCredentials, type AntigravityCredentials } from \"./auth.ts\";\nimport { DEFAULT_ENDPOINT, postAntigravityJson, PROVIDER_ID } from \"./protocol.ts\";\nimport { classifyModelFamily } from \"./model-identity.ts\";\n\nexport const PRIVATE_SNAPSHOT_KEY = \"pi-provider-antigravity\";\n\ntype CanonicalTier = \"low\" | \"medium\" | \"high\";\n\n/**\n * Canonical Tier Suffix: The wire suffix that mirrors the user-requested thinking\n * effort by name (-low, -medium, -high), attempted first when resolving a Runtime Model ID.\n */\nconst CANONICAL_TIER_SUFFIXES: Record<CanonicalTier, string> = Object.freeze({\n low: \"-low\",\n medium: \"-medium\",\n high: \"-high\",\n});\n\n/**\n * Tier Alias: Alternative wire spellings representing the same thinking effort tier\n * (-thinking or -agent for high, -extra-low for low, or an unsuffixed base identifier\n * for the default tier), resolved when the canonical suffix is absent.\n */\nconst TIER_ALIASES: Record<CanonicalTier, readonly string[]> = Object.freeze({\n low: Object.freeze([\"-extra-low\"]),\n medium: Object.freeze([]),\n high: Object.freeze([\"-thinking\", \"-agent\"]),\n});\n\n/**\n * Special suffixes in the catalog that designate non-effort variant types (e.g. server-directed\n * dynamic thinking selection). Stripped for base model grouping and recognized as runtime IDs,\n * but not selectable as a user thinking effort tier.\n */\nconst SPECIAL_TIER_SUFFIXES: readonly string[] = Object.freeze([\"-tiered\"]);\n\n/**\n * Union of all known model ID tier suffixes (canonical, aliases, and special tokens).\n */\nconst ALL_TIER_SUFFIXES: readonly string[] = Object.freeze([\n ...new Set([\n ...Object.values(CANONICAL_TIER_SUFFIXES),\n ...Object.values(TIER_ALIASES).flat(),\n ...SPECIAL_TIER_SUFFIXES,\n ]),\n]);\n\n/**\n * Strips any known tier suffix from a model ID for grouping.\n */\nconst TIER_SUFFIX_PATTERN = new RegExp(\n `-(?:${ALL_TIER_SUFFIXES.map((s) => s.replace(/^-/, \"\")).join(\"|\")})$`,\n);\n\nfunction tierSpellings(tier: CanonicalTier): readonly string[] {\n return [CANONICAL_TIER_SUFFIXES[tier], ...TIER_ALIASES[tier]];\n}\n\nfunction extractBaseModelId(runtimeId: string): string {\n if (runtimeId === \"gemini-pro-agent\") return \"gemini-3.1-pro\";\n if (runtimeId.startsWith(\"gemini-3.1-pro-\")) return \"gemini-3.1-pro\";\n\n return runtimeId.replace(TIER_SUFFIX_PATTERN, \"\");\n}\n\n/**\n * Ordered candidate suffixes attempted when resolving a Runtime Model ID for an effort.\n * Canonical suffix comes first, followed by fallbacks.\n */\nconst TIER_FALLBACKS: Record<string, readonly string[]> = Object.freeze({\n minimal: Object.freeze([\"-low\", \"-extra-low\", \"\"]),\n low: Object.freeze([\"-extra-low\", \"\"]),\n medium: Object.freeze([\"\", \"-high\"]), // Gemini 3.1 Pro lists no -medium: up to high, never down\n high: Object.freeze([\"-thinking\", \"-agent\", \"\"]), // Claude's high tier is -thinking\n xhigh: Object.freeze([\"-high\", \"-thinking\", \"-agent\", \"\"]),\n max: Object.freeze([\"-high\", \"-thinking\", \"-agent\", \"\"]),\n});\n\nconst DEFAULT_TIER_ORDER: readonly string[] = Object.freeze([\n CANONICAL_TIER_SUFFIXES.high,\n ...TIER_ALIASES.high,\n \"\",\n]);\n\nfunction tierCandidateOrder(effort?: string): readonly string[] {\n if (!effort) return DEFAULT_TIER_ORDER;\n const canonical = effort in CANONICAL_TIER_SUFFIXES\n ? [CANONICAL_TIER_SUFFIXES[effort as CanonicalTier]]\n : [`-${effort}`];\n const fallbacks = TIER_FALLBACKS[effort] ?? DEFAULT_TIER_ORDER;\n return [...new Set([...canonical, ...fallbacks])];\n}\n\ntype StoreEntry = NonNullable<RefreshModelsContext[\"stored\"]>;\n\n/**\n * Context passed to refreshModels by Pi Core, minus internal fields the\n * extension does not touch.\n */\nexport type RefreshContext = Omit<RefreshModelsContext, \"stored\" | \"publish\"> & {\n stored?: Readonly<StoreEntry> & { [PRIVATE_SNAPSHOT_KEY]?: PersistedSnapshot };\n publish?(publication: {\n persist?: (StoreEntry & { [PRIVATE_SNAPSHOT_KEY]?: PersistedSnapshot }) | null;\n update?: () => void;\n }): Promise<boolean>;\n};\n\nexport interface CatalogRefreshOutcome {\n status: \"fresh\" | \"stale\" | \"failed\";\n catalog?: AvailableModelsCatalog;\n}\n\nexport interface AvailableModelItem {\n id: string;\n displayName?: string;\n modelEnum?: string;\n remainingFraction?: number;\n resetTime?: string;\n supportsThinking?: boolean;\n thinkingBudget?: number;\n minThinkingBudget?: number;\n supportsImages?: boolean;\n maxTokens?: number;\n maxOutputTokens?: number;\n}\n\nexport interface AvailableModelsCatalog {\n models: AvailableModelItem[];\n modelEnums: Record<string, string>;\n agentModelSorts?: string[];\n /** Server-directed renames: old Runtime Model ID \u2192 current Runtime Model ID. */\n deprecated?: Record<string, string>;\n}\n\nexport interface CatalogThinking {\n budget?: number;\n supportsThinking: boolean;\n}\n\nexport interface CatalogSnapshot {\n enums: Record<string, string>;\n runtimeIds: string[];\n thinking: Record<string, CatalogThinking>;\n deprecated: Record<string, string>;\n}\n\nexport interface CatalogGeneration {\n snapshot: CatalogSnapshot;\n /** Full item list of the recorded refresh; absent after an offline restore. */\n items?: AvailableModelsCatalog;\n /** Fetch successes recorded in this process; 0 until one is recorded. */\n version: number;\n}\n\n// Catalog Persistence codec: the private entry this provider keeps inside its\n// own Pi store entry (PRIVATE_SNAPSHOT_KEY). The key spells a snapshot's `enums`\n// as `modelEnums` and must keep doing so \u2014 Pi persists unknown keys verbatim.\nexport interface PersistedSnapshot {\n modelEnums: Record<string, string>;\n runtimeIds: string[];\n thinking: Record<string, CatalogThinking>;\n deprecated: Record<string, string>;\n}\n\nexport interface ModelPlan {\n runtimeModelId: string;\n modelEnum: string;\n thinkingConfig: { includeThoughts: boolean; thinkingBudget: number };\n isNonGemini: boolean;\n isClaude: boolean;\n}\n\n/**\n * The single deep Model Catalog interface. Encapsulates wire decoding, snapshot generations,\n * persistence codecs, network refresh, plan resolution, and CLI formatting behind one seam.\n */\nexport interface ModelCatalog {\n /**\n * Current generation. The snapshot is a copy the caller may keep; `items` is\n * shared, because readers only enumerate it and never mutate it.\n */\n generation(): CatalogGeneration;\n /**\n * Records one completed generation from parsed catalog or raw wire JSON payload:\n * automatically parses wire envelope, derives its snapshot, and bumps version.\n */\n record(catalogOrRaw: unknown): void;\n /**\n * Restores a persisted snapshot or raw store object into a pristine store.\n */\n restore(persistedOrSnapshot: unknown): void;\n /**\n * Encodes the current generation snapshot for Pi models-store.json persistence.\n */\n toPersisted(): PersistedSnapshot | undefined;\n /**\n * Pi SDK refreshModels entry point: restores stored snapshot, fetches wire\n * catalog when online, updates generation, and publishes to Pi store.\n */\n refresh(context: RefreshContext): Promise<Array<Model<any>>>;\n /**\n * Refreshes catalog via the provided hook and reports freshness verdict.\n */\n refreshGeneration(doRefresh: () => unknown): Promise<CatalogRefreshOutcome>;\n /**\n * Resolves one Model Plan for the requested model and effort against\n * the current snapshot generation.\n */\n resolvePlan(publicModelId: string, effort?: string): ModelPlan;\n /**\n * Formats the current catalog generation as a readable CLI table string.\n */\n formatList(): string;\n}\n\nexport type CatalogStore = ModelCatalog;\n\nexport function buildThinkingMap(models: AvailableModelItem[]): Record<string, CatalogThinking> {\n return Object.fromEntries(\n models.map((m) => [\n m.id,\n {\n ...(typeof m.thinkingBudget === \"number\" ? { budget: m.thinkingBudget } : {}),\n supportsThinking: m.supportsThinking ?? false,\n },\n ]),\n );\n}\n\nfunction snapshotFromCatalog(catalog: AvailableModelsCatalog): CatalogSnapshot {\n return {\n enums: { ...catalog.modelEnums },\n runtimeIds: [...new Set(catalog.models.map((m) => m.id))],\n thinking: buildThinkingMap(catalog.models),\n deprecated: { ...(catalog.deprecated ?? {}) },\n };\n}\n\nfunction copySnapshot(snapshot: CatalogSnapshot): CatalogSnapshot {\n return {\n enums: { ...snapshot.enums },\n runtimeIds: [...snapshot.runtimeIds],\n thinking: Object.fromEntries(\n Object.entries(snapshot.thinking).map(([id, info]) => [id, { ...info }]),\n ),\n deprecated: { ...snapshot.deprecated },\n };\n}\n\nconst EMPTY_SNAPSHOT = (): CatalogSnapshot => ({ enums: {}, runtimeIds: [], thinking: {}, deprecated: {} });\n\nexport function parseAvailableModels(data: any): AvailableModelsCatalog {\n if (!data || typeof data !== \"object\") {\n return { models: [], modelEnums: {} };\n }\n\n const models: AvailableModelItem[] = [];\n const modelEnums: Record<string, string> = {};\n\n const modelsObj = data.models || {};\n for (const [id, info] of Object.entries<any>(modelsObj)) {\n if (id.startsWith(\"tab_\") || id.startsWith(\"chat_\")) continue; // hide internal completions\n\n const modelEnum = typeof info.model === \"string\" ? info.model : undefined;\n if (modelEnum) {\n modelEnums[id] = modelEnum;\n }\n\n const quotaInfo = info.quotaInfo || {};\n models.push({\n id,\n displayName: info.displayName || info.label || id,\n modelEnum,\n remainingFraction: quotaInfo.remainingFraction,\n resetTime: quotaInfo.resetTime,\n supportsThinking: Boolean(info.supportsThinking),\n thinkingBudget: typeof info.thinkingBudget === \"number\" ? info.thinkingBudget : undefined,\n minThinkingBudget: typeof info.minThinkingBudget === \"number\" ? info.minThinkingBudget : undefined,\n supportsImages: Boolean(info.supportsImages),\n maxTokens: typeof info.maxTokens === \"number\" ? info.maxTokens : undefined,\n maxOutputTokens: typeof info.maxOutputTokens === \"number\" ? info.maxOutputTokens : undefined,\n });\n }\n\n const agentModelSorts: string[] = [];\n if (Array.isArray(data.agentModelSorts)) {\n for (const sortGroup of data.agentModelSorts) {\n if (Array.isArray(sortGroup.groups)) {\n for (const group of sortGroup.groups) {\n if (Array.isArray(group.modelIds)) {\n agentModelSorts.push(...group.modelIds);\n }\n }\n }\n }\n }\n\n models.sort((a, b) => a.id.localeCompare(b.id));\n\n // Server-directed renames (old Runtime Model ID \u2192 current one).\n const deprecated: Record<string, string> = {};\n const rawDeprecated = (data as any).deprecatedModelIds;\n if (rawDeprecated && typeof rawDeprecated === \"object\") {\n for (const [oldId, info] of Object.entries<any>(rawDeprecated)) {\n if (info && typeof info.newModelId === \"string\") {\n deprecated[oldId] = info.newModelId;\n }\n }\n }\n\n return {\n models,\n modelEnums,\n ...(agentModelSorts.length > 0 ? { agentModelSorts } : {}),\n ...(Object.keys(deprecated).length > 0 ? { deprecated } : {}),\n };\n}\n\nasync function fetchAvailableModelsCatalog(\n token: string | AntigravityCredentials,\n projectId: string,\n signal?: AbortSignal\n): Promise<AvailableModelsCatalog> {\n const json = await postAntigravityJson<any>({\n auth: token,\n path: \"v1internal:fetchAvailableModels\",\n body: { project: projectId },\n signal,\n });\n return parseAvailableModels(json);\n}\n\nfunction toPersistedSnapshot(snapshot: CatalogSnapshot): PersistedSnapshot {\n return {\n modelEnums: { ...snapshot.enums },\n runtimeIds: [...snapshot.runtimeIds],\n thinking: { ...snapshot.thinking },\n deprecated: { ...snapshot.deprecated },\n };\n}\n\nfunction isStringRecord(value: unknown): value is Record<string, string> {\n return (\n !!value &&\n typeof value === \"object\" &&\n !Array.isArray(value) &&\n Object.values(value).every((entry) => typeof entry === \"string\")\n );\n}\n\nfunction isThinkingRecord(value: unknown): value is Record<string, CatalogThinking> {\n return (\n !!value &&\n typeof value === \"object\" &&\n !Array.isArray(value) &&\n Object.values(value).every((entry) => !!entry && typeof entry === \"object\" && !Array.isArray(entry))\n );\n}\n\nfunction fromPersistedSnapshot(raw: unknown): CatalogSnapshot | undefined {\n if (!raw || typeof raw !== \"object\" || Array.isArray(raw)) return undefined;\n const entry = raw as Partial<PersistedSnapshot>;\n const enums = isStringRecord(entry.modelEnums) ? entry.modelEnums : undefined;\n const runtimeIds = Array.isArray(entry.runtimeIds)\n ? entry.runtimeIds.filter((id): id is string => typeof id === \"string\")\n : undefined;\n const thinking = isThinkingRecord(entry.thinking) ? entry.thinking : undefined;\n const deprecated = isStringRecord(entry.deprecated) ? entry.deprecated : undefined;\n if (!enums && !runtimeIds && !thinking && !deprecated) return undefined;\n return { enums: enums ?? {}, runtimeIds: runtimeIds ?? [], thinking: thinking ?? {}, deprecated: deprecated ?? {} };\n}\n\nfunction resolveRuntimeModelId(\n modelId: string,\n effort: string | undefined,\n availableRuntimeIds: string[]\n): string {\n if (ALL_TIER_SUFFIXES.some((suffix) => modelId.endsWith(suffix))) {\n return modelId;\n }\n\n if (availableRuntimeIds.length > 0) {\n const variants = new Set(availableRuntimeIds.filter((id) => extractBaseModelId(id) === modelId));\n const order = tierCandidateOrder(effort);\n\n for (const suffix of order) {\n if (variants.has(`${modelId}${suffix}`)) {\n return `${modelId}${suffix}`;\n }\n }\n\n if (variants.size === 1) {\n return [...variants][0];\n }\n }\n\n return modelId;\n}\n\nfunction followRenames(runtimeModelId: string, snapshot: CatalogSnapshot): string {\n const renamed = snapshot.deprecated;\n if (!renamed) return runtimeModelId;\n let current = runtimeModelId;\n const seen = new Set<string>([current]);\n while (renamed[current] && !seen.has(renamed[current])) {\n current = renamed[current];\n seen.add(current);\n }\n return current;\n}\n\nfunction resolveThinkingConfig(\n runtimeModelId: string,\n snapshot: CatalogSnapshot\n): { includeThoughts: boolean; thinkingBudget: number } {\n const budget = snapshot.thinking[runtimeModelId]?.budget;\n return typeof budget === \"number\"\n ? { includeThoughts: true, thinkingBudget: budget }\n : { includeThoughts: false, thinkingBudget: 0 };\n}\n\nexport function resolveModelPlan(\n publicModelId: string,\n effort: string | undefined,\n snapshot: CatalogSnapshot\n): ModelPlan {\n const runtimeModelId = followRenames(\n resolveRuntimeModelId(publicModelId, effort, snapshot.runtimeIds),\n snapshot\n );\n const modelEnum = snapshot.enums[runtimeModelId];\n if (!modelEnum) {\n throw new Error(\n `Unknown model \"${runtimeModelId}\". ` +\n `Run /antigravity refresh, then pick a current model.`\n );\n }\n const family = classifyModelFamily(runtimeModelId);\n return {\n runtimeModelId,\n modelEnum,\n thinkingConfig: resolveThinkingConfig(runtimeModelId, snapshot),\n isNonGemini: family !== \"gemini\",\n isClaude: family === \"claude\",\n };\n}\n\nfunction estimateModelCost(_baseId: string): Model<any>[\"cost\"] {\n return { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };\n}\n\nfunction formatModelDisplayName(baseId: string, rawDisplayName?: string): string {\n if (rawDisplayName) {\n const cleaned = rawDisplayName.replace(/\\s*\\([^)]*\\)/g, \"\").trim();\n if (cleaned.length > 0) {\n return cleaned;\n }\n }\n const words = baseId.split(\"-\").map((w) => {\n if (/^\\d+(\\.\\d+)?$/.test(w)) return w;\n return w.charAt(0).toUpperCase() + w.slice(1);\n });\n return words.join(\" \");\n}\n\nfunction synthesizeDynamicModel(baseId: string, items: AvailableModelItem[]): Model<any> {\n const repItem = items.find((it) => it.id === `${baseId}-high` || it.id === baseId) || items[0];\n\n const hasVariant = (suffixes: readonly string[]) =>\n items.some((it) => suffixes.some((suffix) => it.id.endsWith(suffix)));\n const thinkingLevelMap = {\n off: null,\n minimal: null,\n ...(hasVariant(tierSpellings(\"low\")) ? {} : { low: null }),\n ...(hasVariant(tierSpellings(\"medium\")) ? {} : { medium: null }),\n ...(hasVariant(tierSpellings(\"high\")) || items.some((it) => it.id === baseId)\n ? {}\n : { high: null }),\n };\n\n const family = classifyModelFamily(baseId);\n const isFlash = baseId.includes(\"flash\");\n const isClaude = family === \"claude\";\n const isGpt = family === \"gpt\";\n\n const defaultContext = isFlash ? 1048576 : isClaude ? 250000 : isGpt ? 128000 : 1048576;\n const defaultMaxOutput = isClaude ? 64000 : isGpt ? 32768 : 65536;\n\n return {\n id: baseId,\n name: formatModelDisplayName(baseId, repItem?.displayName),\n provider: PROVIDER_ID,\n api: \"antigravity-api\",\n baseUrl: DEFAULT_ENDPOINT,\n reasoning: repItem?.supportsThinking ?? true,\n thinkingLevelMap,\n input: repItem?.supportsImages ? [\"text\", \"image\"] : [\"text\"],\n cost: estimateModelCost(baseId),\n contextWindow: repItem?.maxTokens || defaultContext,\n maxTokens: repItem?.maxOutputTokens || defaultMaxOutput,\n };\n}\n\nfunction buildDynamicPublicModels(catalog?: AvailableModelsCatalog): Array<Model<any>> {\n if (!catalog || !Array.isArray(catalog.models) || catalog.models.length === 0) {\n return [];\n }\n\n const agentSortIds = catalog.agentModelSorts;\n const eligibleItems =\n Array.isArray(agentSortIds) && agentSortIds.length > 0\n ? catalog.models.filter((m) => agentSortIds.includes(m.id))\n : catalog.models;\n\n const runtimeGroups = new Map<string, AvailableModelItem[]>();\n for (const item of eligibleItems) {\n const baseId = extractBaseModelId(item.id);\n const list = runtimeGroups.get(baseId) || [];\n list.push(item);\n runtimeGroups.set(baseId, list);\n }\n\n const orderedBaseIds: string[] = [];\n if (Array.isArray(agentSortIds)) {\n for (const sortId of agentSortIds) {\n const baseId = extractBaseModelId(sortId);\n if (runtimeGroups.has(baseId) && !orderedBaseIds.includes(baseId)) {\n orderedBaseIds.push(baseId);\n }\n }\n }\n\n for (const baseId of runtimeGroups.keys()) {\n if (!orderedBaseIds.includes(baseId)) {\n orderedBaseIds.push(baseId);\n }\n }\n\n return orderedBaseIds.map((baseId) => synthesizeDynamicModel(baseId, runtimeGroups.get(baseId)!));\n}\n\nfunction formatTokenCount(n?: number): string {\n if (typeof n !== \"number\") return \"N/A\";\n if (n % 1048576 === 0) return `${n / 1048576}M`;\n if (n % 1024 === 0) return `${n / 1024}k`;\n if (n % 1000 === 0) return `${n / 1000}k`;\n return `${Math.round(n / 1024)}k`;\n}\n\nfunction formatModelsList(catalog: AvailableModelsCatalog): string {\n const sorts = catalog.agentModelSorts;\n const recommendedOnly = Array.isArray(sorts) && sorts.length > 0;\n const rank = new Map((sorts || []).map((id, i) => [id, i]));\n\n const models = (recommendedOnly ? catalog.models.filter((m) => rank.has(m.id)) : catalog.models.slice()).sort(\n (a, b) => (rank.get(a.id) ?? Number.MAX_SAFE_INTEGER) - (rank.get(b.id) ?? Number.MAX_SAFE_INTEGER) ||\n a.id.localeCompare(b.id)\n );\n\n const rows = models.map((m) => {\n const flags: string[] = [];\n if (m.supportsThinking) flags.push(\"thinking\");\n if (m.supportsImages) flags.push(\"images\");\n return {\n id: m.id,\n name: formatModelDisplayName(m.id, m.displayName || m.id),\n ctx: `${formatTokenCount(m.maxTokens)}/${formatTokenCount(m.maxOutputTokens)}`,\n feat: flags.length > 0 ? flags.join(\", \") : \"-\",\n rem: typeof m.remainingFraction === \"number\" ? `${Math.round(m.remainingFraction * 100)}%` : \"N/A\",\n };\n });\n\n const headers = { id: \"Model\", name: \"Name\", ctx: \"Context\", feat: \"Features\", rem: \"Rem\" };\n const w = {\n id: Math.max(headers.id.length, ...rows.map((r) => r.id.length)),\n name: Math.max(headers.name.length, ...rows.map((r) => r.name.length)),\n ctx: Math.max(headers.ctx.length, ...rows.map((r) => r.ctx.length)),\n feat: Math.max(headers.feat.length, ...rows.map((r) => r.feat.length)),\n };\n\n const lines: string[] = [\n `Available Antigravity Models (${models.length}${recommendedOnly ? \" recommended\" : \"\"}):`,\n ` ${headers.id.padEnd(w.id)} ${headers.name.padEnd(w.name)} ${headers.ctx.padEnd(w.ctx)} ${headers.feat.padEnd(w.feat)} ${headers.rem}`,\n ];\n for (const r of rows) {\n lines.push(\n ` ${r.id.padEnd(w.id)} ${r.name.padEnd(w.name)} ${r.ctx.padEnd(w.ctx)} ${r.feat.padEnd(w.feat)} ${r.rem.padStart(4)}`\n );\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Creates the authoritative deep Model Catalog interface.\n */\nexport function createModelCatalog(): ModelCatalog {\n let generation: CatalogGeneration = { snapshot: EMPTY_SNAPSHOT(), version: 0 };\n\n const record = (catalogOrRaw: unknown) => {\n let catalog: AvailableModelsCatalog;\n if (\n catalogOrRaw &&\n typeof catalogOrRaw === \"object\" &&\n \"models\" in catalogOrRaw &&\n Array.isArray((catalogOrRaw as any).models) &&\n \"modelEnums\" in catalogOrRaw &&\n typeof (catalogOrRaw as any).modelEnums === \"object\"\n ) {\n catalog = catalogOrRaw as AvailableModelsCatalog;\n } else {\n catalog = parseAvailableModels(catalogOrRaw);\n }\n generation = {\n snapshot: snapshotFromCatalog(catalog),\n items: catalog,\n version: generation.version + 1,\n };\n };\n\n const restore = (persistedOrSnapshot: unknown) => {\n if (generation.version > 0) return;\n if (!persistedOrSnapshot || typeof persistedOrSnapshot !== \"object\") return;\n\n if (\n \"enums\" in persistedOrSnapshot &&\n \"runtimeIds\" in persistedOrSnapshot &&\n Array.isArray((persistedOrSnapshot as any).runtimeIds)\n ) {\n generation = { snapshot: copySnapshot(persistedOrSnapshot as CatalogSnapshot), version: 0 };\n return;\n }\n\n const snapshot = fromPersistedSnapshot(persistedOrSnapshot);\n if (snapshot) {\n generation = { snapshot: copySnapshot(snapshot), version: 0 };\n }\n };\n\n const toPersisted = (): PersistedSnapshot | undefined => {\n if (generation.version === 0 && generation.snapshot.runtimeIds.length === 0) {\n return undefined;\n }\n return toPersistedSnapshot(generation.snapshot);\n };\n\n const refresh = async (context: RefreshContext): Promise<Array<Model<any>>> => {\n const persisted = context.stored?.[PRIVATE_SNAPSHOT_KEY];\n if (persisted) restore(persisted);\n\n const storedModels = () => [...(context.stored?.models ?? [])];\n if (!context.allowNetwork) return storedModels();\n\n try {\n const creds = await resolveCredentials(context);\n if (!creds) return storedModels();\n\n const catalog = await fetchAvailableModelsCatalog(creds, creds.projectId, context.signal);\n record(catalog);\n\n const dynamicModels = buildDynamicPublicModels(catalog);\n\n if (context.publish) {\n await context.publish({\n persist: {\n models: dynamicModels,\n checkedAt: Date.now(),\n [PRIVATE_SNAPSHOT_KEY]: toPersisted(),\n },\n });\n }\n\n return dynamicModels;\n } catch {\n return storedModels();\n }\n };\n\n const refreshGen = async (doRefresh: () => unknown): Promise<CatalogRefreshOutcome> => {\n const versionBefore = generation.version;\n await doRefresh();\n const { items, version } = generation;\n if (!items) return { status: \"failed\" };\n return { status: version === versionBefore ? \"stale\" : \"fresh\", catalog: items };\n };\n\n return {\n generation: () => ({ ...generation, snapshot: copySnapshot(generation.snapshot) }),\n record,\n restore,\n toPersisted,\n refresh,\n refreshGeneration: refreshGen,\n resolvePlan: (publicModelId, effort) => resolveModelPlan(publicModelId, effort, generation.snapshot),\n formatList: () => (generation.items ? formatModelsList(generation.items) : \"No models available.\"),\n };\n}\n\nexport const createCatalogStore = createModelCatalog;\n\nexport async function refreshCatalog(context: RefreshContext, store: ModelCatalog): Promise<Array<Model<any>>> {\n return store.refresh(context);\n}\n", "import * as fs from \"node:fs\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport type { ExtensionCommandContext, Theme } from \"@earendil-works/pi-coding-agent\";\nimport { SettingsList, type SettingItem, type SettingsListTheme } from \"@earendil-works/pi-tui\";\n\nexport const ANSI_FG_RESET = \"\\x1b[39m\";\n\nexport const PROVIDER_CONFIG_FILE = \"pi-provider-antigravity.json\";\n\nexport interface ProviderFileConfig {\n settings?: { [key: string]: unknown };\n // Runtime state namespaced per subsystem (e.g. states.quota); unknown\n // entries pass through untouched.\n states?: { [name: string]: { [key: string]: unknown } | undefined };\n}\n\n// Single opt-in file next to Pi's settings.json (NOT settings.json itself \u2014\n// Pi manages that file and may drop unknown keys). Pi resolves its dir via\n// PI_CODING_AGENT_DIR else ~/.pi/agent:\n// { \"settings\": { \"quotaFooter\": \"smart\" } } // off (default) | smart | all\n// A \"states\" section holds runtime data namespaced per subsystem\n// (e.g. states.quota); unknown keys and sections pass through untouched. Read per call: tiny file, and edits apply\n// on the next refresh without a restart.\nexport function defaultConfigFile(env: NodeJS.ProcessEnv = process.env): string {\n const dir = (env.PI_CODING_AGENT_DIR || \"\").trim() || path.join(os.homedir(), \".pi\", \"agent\");\n return path.join(dir, PROVIDER_CONFIG_FILE);\n}\n\nexport function loadProviderConfig(file = defaultConfigFile()): ProviderFileConfig | undefined {\n try {\n const raw = JSON.parse(fs.readFileSync(file, \"utf-8\"));\n if (raw && typeof raw === \"object\" && !Array.isArray(raw)) return raw as ProviderFileConfig;\n } catch {\n // Missing/unreadable/invalid file means \"not configured\".\n }\n return undefined;\n}\n\n// Temp file in the same directory so the rename stays on one filesystem, and\n// fsync before it so a crash cannot leave the new name pointing at empty data.\n// An existing file's mode is carried over: rename replaces the inode, so\n// without it a user's tightened permissions would silently reset.\nexport function writeProviderConfigAtomically(file: string, data: ProviderFileConfig): boolean {\n const tmp = `${file}.tmp-${process.pid}`;\n try {\n fs.mkdirSync(path.dirname(file), { recursive: true });\n const mode = fs.existsSync(file) ? fs.statSync(file).mode & 0o777 : undefined;\n const fd = fs.openSync(tmp, \"w\", mode);\n try {\n fs.writeFileSync(fd, JSON.stringify(data, null, 2) + \"\\n\", \"utf-8\");\n fs.fsyncSync(fd);\n } finally {\n fs.closeSync(fd);\n }\n fs.renameSync(tmp, file);\n return true;\n } catch {\n try {\n fs.rmSync(tmp, { force: true });\n } catch {\n // Nothing left to clean up.\n }\n return false;\n }\n}\n\n// The file's single writer: parse once, let the caller mutate the keys it owns,\n// write atomically. A file we cannot read is never overwritten \u2014 this is the\n// file the CLI tells users to hand-edit, so one syntax error must not cost them\n// the rest of the document (settings and every subsystem's states entry).\n// Callers keep their own merge rule; leaving other keys untouched is what\n// preserves them.\nexport function updateProviderConfig(\n file: string,\n mutate: (config: ProviderFileConfig) => void,\n): boolean {\n try {\n let data: ProviderFileConfig = {};\n try {\n const raw = JSON.parse(fs.readFileSync(file, \"utf-8\"));\n if (!raw || typeof raw !== \"object\" || Array.isArray(raw)) return false;\n data = raw as ProviderFileConfig;\n } catch (err: any) {\n // A missing file is a fresh install; anything else is unreadable.\n if (err?.code !== \"ENOENT\") return false;\n }\n mutate(data);\n return writeProviderConfigAtomically(file, data);\n } catch {\n // Best-effort: a caller that loses its write keeps working from memory.\n return false;\n }\n}\n\n/**\n * Loads subsystem state from states[subsystem], e.g. states.quota.\n */\nexport function loadSubsystemState<T>(\n subsystem: string,\n file = defaultConfigFile(),\n): T | undefined {\n const state = loadProviderConfig(file)?.states?.[subsystem];\n return state && typeof state === \"object\" && !Array.isArray(state) ? (state as T) : undefined;\n}\n\n/**\n * Atomically merges state into states[subsystem] while preserving settings and other subsystems.\n */\nexport function saveSubsystemState<T extends object>(\n subsystem: string,\n state: T,\n file = defaultConfigFile(),\n): boolean {\n return updateProviderConfig(file, (config) => {\n const states =\n config.states && typeof config.states === \"object\" && !Array.isArray(config.states)\n ? config.states\n : {};\n const current =\n states[subsystem] && typeof states[subsystem] === \"object\" && !Array.isArray(states[subsystem])\n ? states[subsystem]\n : {};\n states[subsystem] = { ...current, ...state };\n config.states = states;\n });\n}\n\nexport interface SettingsFieldDef {\n key: string;\n label: string;\n description?: string;\n options: readonly string[];\n defaultValue?: string;\n optionNotes?: Record<string, string>;\n /** Optional preview hook returning formatted preview text for a chosen value. */\n renderPreview?: (value: string, ctx: ExtensionCommandContext, theme?: Theme) => string | undefined;\n /** Optional async hook invoked after a value is saved. */\n onChange?: (ctx: ExtensionCommandContext, value: string) => Promise<void>;\n /** Optional async prepare hook called before opening the settings dialog. */\n prepare?: (ctx: ExtensionCommandContext) => Promise<void>;\n}\n\nexport class SettingsRegistry {\n private fields: SettingsFieldDef[] = [];\n\n register(field: SettingsFieldDef): void {\n const existingIndex = this.fields.findIndex((f) => f.key === field.key);\n if (existingIndex >= 0) {\n this.fields[existingIndex] = field;\n } else {\n this.fields.push(field);\n }\n }\n\n unregister(key: string): void {\n this.fields = this.fields.filter((f) => f.key !== key);\n }\n\n getFields(): readonly SettingsFieldDef[] {\n return [...this.fields];\n }\n\n clear(): void {\n this.fields = [];\n }\n}\n\nexport const defaultSettingsRegistry = new SettingsRegistry();\n\nexport function registerSettingField(field: SettingsFieldDef): void {\n defaultSettingsRegistry.register(field);\n}\n\nexport function getRegisteredSettingFields(): readonly SettingsFieldDef[] {\n return defaultSettingsRegistry.getFields();\n}\n\nexport function fieldDisplayValue(\n config: ProviderFileConfig | undefined,\n field: SettingsFieldDef,\n): string {\n const raw = config?.settings?.[field.key];\n if (typeof raw === \"string\" && raw.trim()) return raw.trim();\n return field.defaultValue ?? \"unset\";\n}\n\nexport function saveSettingValue(field: SettingsFieldDef, value: string, file: string): boolean {\n return updateProviderConfig(file, (config) => {\n const settings =\n config.settings && typeof config.settings === \"object\" && !Array.isArray(config.settings)\n ? config.settings\n : {};\n settings[field.key] = value;\n config.settings = settings;\n });\n}\n\nexport async function applySettingValue(\n field: SettingsFieldDef,\n value: string,\n file: string,\n ctx: ExtensionCommandContext,\n): Promise<boolean> {\n if (!saveSettingValue(field, value, file)) {\n return false;\n }\n await field.onChange?.(ctx, value);\n return true;\n}\n\n// A refused write is either \"unreadable file\" or \"the write itself failed\", and\n// applySettingValue reports both the same way. So the message stays conditional\n// instead of naming a cause, and still hands over the recovery for the case a\n// hand-editor actually hits.\nfunction writeFailedMessage(file: string): string {\n return `Failed to write ${file}. If the file is not valid JSON, fix or delete it.`;\n}\n\nexport function buildSettingsItems(\n config: ProviderFileConfig | undefined,\n fields: readonly SettingsFieldDef[] = getRegisteredSettingFields(),\n): SettingItem[] {\n return fields.map((f) => ({\n id: f.key,\n label: f.label,\n description: f.description,\n currentValue: fieldDisplayValue(config, f),\n values: [...f.options],\n }));\n}\n\nasync function settingsListTheme(theme: Theme): Promise<SettingsListTheme> {\n try {\n const pi = await import(\"@earendil-works/pi-coding-agent\");\n return pi.getSettingsListTheme();\n } catch {\n return {\n label: (text, selected) => (selected ? theme.fg(\"accent\", text) : text),\n value: (text, selected) => (selected ? theme.fg(\"accent\", text) : theme.fg(\"muted\", text)),\n description: (text) => theme.fg(\"dim\", text),\n cursor: theme.fg(\"accent\", \"\u2192 \"),\n hint: (text) => theme.fg(\"dim\", text),\n };\n }\n}\n\nfunction resolveFields(\n registryOrFields?: SettingsRegistry | readonly SettingsFieldDef[],\n): readonly SettingsFieldDef[] {\n if (!registryOrFields) return getRegisteredSettingFields();\n if (\"getFields\" in registryOrFields && typeof (registryOrFields as any).getFields === \"function\") {\n return (registryOrFields as SettingsRegistry).getFields();\n }\n return registryOrFields as readonly SettingsFieldDef[];\n}\n\nexport async function openSettings(\n ctx: ExtensionCommandContext,\n registryOrFields?: SettingsRegistry | readonly SettingsFieldDef[],\n): Promise<void> {\n const fields = resolveFields(registryOrFields);\n const file = defaultConfigFile();\n if (ctx.mode === \"tui\" && ctx.hasUI) {\n await openSettingsDialog(ctx, fields, file);\n return;\n }\n const config = loadProviderConfig(file);\n if (!ctx.hasUI) {\n const text =\n fields.map((f) => `${f.label}: ${fieldDisplayValue(config, f)}`).join(\"\\n\") +\n `\\nEdit ${file} to change.`;\n if (ctx.hasUI) ctx.ui.notify(text, \"info\");\n else console.log(text);\n return;\n }\n let field = fields[0];\n if (!field) return;\n if (fields.length > 1) {\n const labels = fields.map(\n (f) => `${f.label} (current: ${fieldDisplayValue(config, f)})`,\n );\n const choice = await ctx.ui.select(\"Antigravity settings\", labels);\n if (!choice) return;\n const found = fields[labels.indexOf(choice)];\n if (!found) return;\n field = found;\n }\n const picked = await ctx.ui.select(\n `${field.label} (current: ${fieldDisplayValue(config, field)})`,\n [...field.options],\n );\n if (!picked || !field.options.includes(picked)) return;\n if (await applySettingValue(field, picked, file, ctx)) {\n ctx.ui.notify(`${field.label} set to ${picked}.`, \"info\");\n } else {\n ctx.ui.notify(writeFailedMessage(file), \"error\");\n }\n}\n\nasync function openSettingsDialog(\n ctx: ExtensionCommandContext,\n fields: readonly SettingsFieldDef[],\n file: string,\n): Promise<void> {\n for (const field of fields) {\n if (field.prepare) await field.prepare(ctx);\n }\n await ctx.ui.custom<void>(async (tui, theme, _kb, done) => {\n const config = loadProviderConfig(file);\n const items = buildSettingsItems(config, fields);\n const paintPreview = (field: SettingsFieldDef, value: string) => {\n const item = items.find((i) => i.id === field.key);\n if (!item) return;\n const base = field.description ?? \"\";\n const sample = field.renderPreview?.(value, ctx, theme);\n const head = sample && base ? `${base}: ${sample}` : (sample ?? base);\n const note = field.optionNotes?.[value];\n item.description = note ? `${head}\\n${note}` : head;\n };\n for (const field of fields) {\n const current = fieldDisplayValue(config, field);\n paintPreview(field, current);\n }\n const list = new SettingsList(\n items,\n Math.min(items.length, 10),\n await settingsListTheme(theme),\n (id, newValue) => {\n const field = fields.find((f) => f.key === id);\n if (!field) return;\n list.invalidate();\n tui.requestRender();\n void applySettingValue(field, newValue, file, ctx).then((saved) => {\n // A refused write (unreadable file) must not look like a success: the\n // list has already moved to the value it asked for, so put the row back\n // on what the file actually holds before reporting the failure.\n if (!saved) {\n list.updateValue(field.key, fieldDisplayValue(loadProviderConfig(file), field));\n ctx.ui.notify(writeFailedMessage(file), \"error\");\n list.invalidate();\n tui.requestRender();\n return;\n }\n paintPreview(field, newValue);\n list.invalidate();\n tui.requestRender();\n });\n },\n () => done(),\n );\n const border = {\n render: (width: number) => [theme.fg(\"border\", \"\u2500\".repeat(Math.max(1, width)))],\n };\n return {\n render: (width: number) => [\n ...border.render(width),\n ...list.render(width),\n ...border.render(width),\n ],\n handleInput: (data: string) => list.handleInput(data),\n invalidate: () => list.invalidate(),\n };\n });\n}\n", "import type { ExtensionCommandContext, ExtensionContext, Theme } from \"@earendil-works/pi-coding-agent\";\nimport { resolveCredentials } from \"./auth.ts\";\nimport { classifyModelFamily } from \"./model-identity.ts\";\nimport { postAntigravityJson, PROVIDER_ID } from \"./protocol.ts\";\nimport {\n defaultConfigFile,\n loadProviderConfig,\n loadSubsystemState,\n saveSubsystemState,\n registerSettingField,\n type ProviderFileConfig,\n type SettingsFieldDef,\n} from \"./config.ts\";\n\n/**\n * Quota Status module (deep, ports & adapters): Quota Pool wire parsing, urgent-window\n * math, ratio self-calibration, throttle, cache, and status footer slot painting.\n * Persists calibration state through the Provider Config Seam (states.quota).\n */\n\nexport type QuotaFooterMode = \"off\" | \"smart\" | \"all\";\n\nexport const FOOTER_MODE_NOTES: Readonly<Record<string, string>> = Object.freeze({\n smart:\n \"Picks whichever window runs out first (5h or weekly), weighting the weekly pool by a ratio learned from your usage\",\n all: \"Lists every window of the pool backing the current model (5h or weekly)\",\n});\n\nexport const FOOTER_MODE_OPTIONS: readonly QuotaFooterMode[] = Object.freeze([\n \"off\",\n \"smart\",\n \"all\",\n]);\n\nexport function normalizeFooterMode(value: unknown): QuotaFooterMode | undefined {\n const v = typeof value === \"string\" ? value.trim().toLowerCase() : \"\";\n return FOOTER_MODE_OPTIONS.includes(v as QuotaFooterMode) ? (v as QuotaFooterMode) : undefined;\n}\n\nexport function resolveFooterMode(config?: ProviderFileConfig): QuotaFooterMode {\n return normalizeFooterMode(config?.settings?.quotaFooter) ?? \"off\";\n}\n\nexport interface QuotaBucket {\n bucketId: string;\n displayName: string;\n window?: string;\n resetTime?: string;\n description?: string;\n remainingFraction: number;\n}\n\nexport interface QuotaGroup {\n displayName: string;\n description?: string;\n buckets: QuotaBucket[];\n}\n\nexport interface QuotaSummary {\n groups: QuotaGroup[];\n description?: string;\n}\n\nexport function renderProgressBar(fraction: number, width = 10): string {\n const clamped = Math.max(0, Math.min(1, fraction));\n const filled = Math.round(clamped * width);\n return `[${\"#\".repeat(filled)}${\"-\".repeat(width - filled)}]`;\n}\n\ntype QuotaWindowKind = \"5h\" | \"weekly\" | \"other\";\n\nconst QUOTA_WINDOW_RANK: Record<QuotaWindowKind, number> = {\n \"5h\": 0,\n weekly: 1,\n other: 2,\n};\n\nfunction classifyQuotaWindow(bucket: QuotaBucket): QuotaWindowKind {\n // The wire reports a machine `window` (\"5h\"/\"weekly\" in every capture). Trust\n // it \u2014 no display-prose guessing. Unknown or missing windows are \"other\".\n const w = (bucket.window || \"\").trim().toLowerCase();\n if (w === \"5h\") return \"5h\";\n if (w === \"weekly\") return \"weekly\";\n return \"other\";\n}\n\nfunction shortWindowLabel(bucket: QuotaBucket, kind: QuotaWindowKind): string {\n if (kind === \"5h\") return \"5h\";\n if (kind === \"weekly\") return \"Wk\";\n return bucket.displayName || bucket.bucketId || \"Quota\";\n}\n\nfunction sortQuotaBuckets(buckets: QuotaBucket[]): QuotaBucket[] {\n return buckets\n .slice()\n .sort(\n (a, b) =>\n QUOTA_WINDOW_RANK[classifyQuotaWindow(a)] - QUOTA_WINDOW_RANK[classifyQuotaWindow(b)],\n );\n}\n\nexport function formatResetRemaining(resetTime?: string): string | null {\n if (!resetTime) return null;\n const ts = Date.parse(resetTime);\n if (!Number.isFinite(ts)) return null;\n const delta = ts - Date.now();\n if (delta <= 0) return \"ready\";\n const totalMin = Math.ceil(delta / 60000);\n const days = Math.floor(totalMin / (60 * 24));\n const hours = Math.floor((totalMin % (60 * 24)) / 60);\n const mins = totalMin % 60;\n if (days > 0) return `in ${days}d ${hours}h`;\n if (hours > 0) return `in ${hours}h ${mins}m`;\n return `in ${mins}m`;\n}\n\nexport function parseQuotaSummary(data: any): QuotaSummary {\n const groups: QuotaGroup[] = [];\n\n for (const g of data.groups || []) {\n const buckets: QuotaBucket[] = [];\n for (const b of g.buckets || []) {\n buckets.push({\n bucketId: b.bucketId || \"unknown\",\n displayName: b.displayName || b.bucketId || \"Limit\",\n window: b.window,\n resetTime: b.resetTime,\n description: b.description,\n remainingFraction: typeof b.remainingFraction === \"number\" ? b.remainingFraction : 1,\n });\n }\n groups.push({\n displayName: g.displayName || \"Quota Group\",\n description: g.description,\n buckets,\n });\n }\n\n return {\n groups,\n description: data.description,\n };\n}\n\nexport function formatQuotaSummary(summary: QuotaSummary): string {\n const lines: string[] = [];\n\n for (const group of summary.groups) {\n if (lines.length > 0) lines.push(\"\");\n lines.push(`${group.displayName}`);\n for (const b of sortQuotaBuckets(group.buckets)) {\n const pct = Math.round(b.remainingFraction * 100);\n const label = shortWindowLabel(b, classifyQuotaWindow(b)).padEnd(3);\n const reset = formatResetRemaining(b.resetTime);\n const suffix = reset && pct < 100 ? ` (${reset})` : \"\";\n lines.push(\n ` ${label} ${renderProgressBar(b.remainingFraction)} ${String(pct).padStart(3)}% left${suffix}`,\n );\n }\n }\n\n return lines.join(\"\\n\");\n}\n\nexport function isGeminiQuotaGroup(group: QuotaGroup): boolean {\n // Bucket ids (\"gemini-5h\" vs \"3p-5h\") \u2014 not display prose (\"Gemini Models\").\n return (group.buckets || []).some((b) => (b.bucketId || \"\").toLowerCase().includes(\"gemini\"));\n}\n\nexport function selectQuotaGroup(groups: QuotaGroup[], modelId?: string): QuotaGroup | undefined {\n if (groups.length === 0) return undefined;\n const family = classifyModelFamily(modelId);\n if (family === \"claude\" || family === \"gpt\") {\n const found = groups.find((g) => !isGeminiQuotaGroup(g));\n if (found) return found;\n }\n return groups.find((g) => isGeminiQuotaGroup(g)) || groups[0];\n}\n\n// Compact one-line footer text (e.g. \"Wk 6% (2d 15h)\") showing the most\n// urgent window of the group backing the current model: 5h and weekly pools\n// differ in volume, so the wall you hit first is min(r5h, rWk \u00D7 R) \u2014 not min\n// fraction. R self-calibrates from observed deltas (see calibrateWeeklyTo5hRatio).\nexport const DEFAULT_WEEKLY_TO_5H_RATIO = 6.0;\n\nexport interface WindowFractionPair {\n \"5h\": number;\n weekly: number;\n}\n\nfunction windowBucket(buckets: QuotaBucket[], kind: QuotaWindowKind): QuotaBucket | undefined {\n return buckets.find((b) => classifyQuotaWindow(b) === kind);\n}\n\n// Pool-group key for persisted pairs: the 5h bucket's wire id minus its window\n// suffix (\"gemini-5h\" \u2192 \"gemini\"). Display names are upstream prose, and the raw\n// id would echo the window inside every record (\"gemini-5h\": { \"5h\", weekly }).\n// Unrecognized shapes keep the full id \u2014 matching only needs determinism.\nfunction poolKey(bucket: QuotaBucket): string {\n const id = bucket.bucketId || \"unknown\";\n return id.replace(/[-_](5h|five-?hour|weekly)$/i, \"\") || id;\n}\n\n// Plain-object form for JSON persistence (see coordinator state).\nexport function extractWindowFractionPairs(\n summary?: QuotaSummary,\n): Record<string, WindowFractionPair> {\n const pairs: Record<string, WindowFractionPair> = {};\n for (const g of summary?.groups || []) {\n const bucket5h = windowBucket(g.buckets, \"5h\");\n const bucketWeekly = windowBucket(g.buckets, \"weekly\");\n if (bucket5h && bucketWeekly)\n pairs[poolKey(bucket5h)] = {\n \"5h\": bucket5h.remainingFraction,\n weekly: bucketWeekly.remainingFraction,\n };\n }\n return pairs;\n}\n\n// Self-calibrates the 5h vs weekly volume ratio R from delta consumption:\n// the same absolute spend drops the 5h fraction R\u00D7 faster than weekly.\n// First valid pool wins; resets and noise fall outside the guards below.\nexport function calibrateWeeklyTo5hRatio(\n previous: Record<string, WindowFractionPair> | undefined,\n current: Record<string, WindowFractionPair> | undefined,\n currentRatio = DEFAULT_WEEKLY_TO_5H_RATIO,\n): number {\n if (!previous || !current) return currentRatio;\n for (const key of Object.keys(current)) {\n const prev = previous[key];\n const curr = current[key];\n if (!prev || !curr) continue;\n\n const dFiveHour = prev[\"5h\"] - curr[\"5h\"];\n const dWeekly = prev.weekly - curr.weekly;\n\n if (dFiveHour > 0.0001 && dWeekly > 0.00001) {\n const observedRatio = dFiveHour / dWeekly;\n if (observedRatio >= 1.0 && observedRatio <= 20.0) {\n return Math.round(observedRatio * 100) / 100;\n }\n }\n }\n return currentRatio;\n}\n\nfunction selectUrgentBucket(group: QuotaGroup, weeklyTo5hRatio: number): QuotaBucket | undefined {\n const buckets = group.buckets;\n if (buckets.length === 0) return undefined;\n const bucket5h = windowBucket(buckets, \"5h\");\n const bucketWeekly = windowBucket(buckets, \"weekly\");\n if (bucket5h && bucketWeekly) {\n return bucketWeekly.remainingFraction * weeklyTo5hRatio < bucket5h.remainingFraction\n ? bucketWeekly\n : bucket5h;\n }\n let worst = buckets[0];\n for (const b of buckets) {\n if (b.remainingFraction < worst.remainingFraction) worst = b;\n }\n return worst;\n}\n\nexport function buildQuotaFooter(\n summary: QuotaSummary,\n modelId?: string,\n weeklyTo5hRatio = DEFAULT_WEEKLY_TO_5H_RATIO,\n): string | undefined {\n const group = selectQuotaGroup(summary.groups, modelId);\n if (!group) return undefined;\n const urgent = selectUrgentBucket(group, weeklyTo5hRatio);\n return urgent ? formatQuotaWindowPart(urgent) : undefined;\n}\n\n// Both windows of the backing group, 5h first (e.g. \"5h 35% (26m) \u00B7 Wk 75% (6d 14h)\").\nexport function buildQuotaFooterBoth(summary: QuotaSummary, modelId?: string): string | undefined {\n const group = selectQuotaGroup(summary.groups, modelId);\n if (!group || group.buckets.length === 0) return undefined;\n return sortQuotaBuckets(group.buckets).map(formatQuotaWindowPart).join(\" \u00B7 \");\n}\n\n// Window prefix names the bucket (\"5h\"/\"Wk\"); unknown windows fall back to\n// the bucket's own display name.\nexport function formatQuotaWindowPart(bucket: QuotaBucket): string {\n const kind = classifyQuotaWindow(bucket);\n const prefix =\n kind === \"5h\" ? \"5h\" : kind === \"weekly\" ? \"Wk\" : bucket.displayName || bucket.bucketId;\n const pct = Math.round(bucket.remainingFraction * 100);\n const short = formatResetRemaining(bucket.resetTime)?.replace(/^in /, \"\");\n if (short && pct < 100) return `${prefix} ${pct}% (${short})`;\n return `${prefix} ${pct}%`;\n}\n\n// Threshold coloring for footer slots. Prefers Theme.fg when available so\n// coloring adapts to the active theme (light/dark/custom); falls back to basic\n// ANSI on dark (mirroring Theme.fg with foreground-only resets) when invoked\n// without a theme (e.g. tests, headless, or mock contexts).\nconst ANSI_RED = \"\\x1b[31m\";\nconst ANSI_YELLOW = \"\\x1b[33m\";\nconst ANSI_DIM = \"\\x1b[90m\";\nexport const ANSI_FG_RESET = \"\\x1b[39m\";\n\nexport const QUOTA_WARN_PCT = 30;\nexport const QUOTA_ALERT_PCT = 10;\n\nexport type QuotaColorTone = \"error\" | \"warning\" | \"dim\";\nexport type QuotaColorizer = (tone: QuotaColorTone, text: string) => string;\nexport type QuotaColorStyle =\n | { fg: (tone: QuotaColorTone, text: string) => string }\n | QuotaColorizer;\n\nfunction resolveColorizer(style?: QuotaColorStyle): QuotaColorizer {\n if (typeof style === \"function\") return style;\n if (style && typeof style.fg === \"function\") return (tone, text) => style.fg(tone, text);\n return (tone, text) => {\n const code = tone === \"error\" ? ANSI_RED : tone === \"warning\" ? ANSI_YELLOW : ANSI_DIM;\n return `${code}${text}${ANSI_FG_RESET}`;\n };\n}\n\nexport function colorizeQuotaFooter(\n footer: string | undefined,\n style?: QuotaColorStyle,\n): string | undefined {\n if (!footer) return undefined;\n const color = resolveColorizer(style);\n const match = footer.match(/(\\d+)%/);\n if (!match) return color(\"dim\", footer);\n const pct = parseInt(match[1], 10);\n if (pct <= QUOTA_ALERT_PCT) return color(\"error\", footer);\n if (pct <= QUOTA_WARN_PCT) return color(\"warning\", footer);\n return color(\"dim\", footer);\n}\n\n// Colors each \" \u00B7 \"-separated window part by its own percentage.\nexport function colorizeQuotaFooterBoth(\n footer: string | undefined,\n style?: QuotaColorStyle,\n): string | undefined {\n if (!footer) return undefined;\n const color = resolveColorizer(style);\n const sep = color(\"dim\", \" \u00B7 \");\n return footer\n .split(\" \u00B7 \")\n .map((part) => colorizeQuotaFooter(part, style) ?? part)\n .join(sep);\n}\n\nexport function previewQuotaFooterText(\n coord: QuotaStatusCoordinator | undefined,\n modelId: string | undefined,\n mode: string,\n style?: QuotaColorStyle,\n): string | undefined {\n if (!coord) return undefined;\n const normalized = normalizeFooterMode(mode);\n if (!normalized || normalized === \"off\") return undefined;\n const { colored } = coord.renderFooter(modelId, normalized, style);\n if (!colored) return undefined;\n return ANSI_FG_RESET + colored;\n}\n\n// Namespaced by repo so no other extension (e.g. a personal-config \"quota\"\n// slot) can overwrite this footer slot, and vice versa.\nexport const QUOTA_STATUS_KEY = \"pi-provider-antigravity-footer-usage\";\nexport const QUOTA_REFRESH_INTERVAL_MS = 5 * 60 * 1000;\n// Baselines older than this may straddle a quota reset (negative or\n// meaningless deltas), so cross-session calibration ignores them. An hour\n// caps the straddle risk at ~1/5 of the 5h window while an hour of active\n// use still dwarfs the noise guards below thousands-fold.\nexport const MAX_OBSERVATION_AGE_MS = 60 * 60 * 1000;\n\n// Persisted Quota Pool calibration state (states.quota in the provider file).\n// The file shape is owned by the settings subsystem; the coordinator only sees\n// this narrow view through its store.\nexport interface QuotaState {\n [key: string]: unknown;\n}\n\n// The seam behind the coordinator: production uses the file-backed store\n// from local config file, tests use an in-memory adapter or custom file.\nexport interface QuotaStatusStore {\n loadMode: () => QuotaFooterMode;\n loadQuotaState: () => QuotaState | undefined;\n saveQuotaState: (state: {\n weeklyTo5hRatio: number;\n previousObservation: Record<string, WindowFractionPair>;\n updatedAt: number;\n }) => boolean;\n}\n\n// Production QuotaStatusStore backed by the provider file. Reads per call:\n// tiny file, and edits apply on the next refresh without a restart.\nexport function fileQuotaStatusStore(file = defaultConfigFile()): QuotaStatusStore {\n return {\n loadMode: () => resolveFooterMode(loadProviderConfig(file)),\n loadQuotaState: () => loadSubsystemState<QuotaState>(\"quota\", file),\n saveQuotaState: (state) => saveSubsystemState(\"quota\", state, file),\n };\n}\n\nexport function createQuotaFooterField(\n quotaStatus: QuotaStatusCoordinator,\n): SettingsFieldDef {\n return {\n key: \"quotaFooter\",\n label: \"Quota footer\",\n description: \"Show remaining quota in Pi's status footer\",\n options: FOOTER_MODE_OPTIONS,\n defaultValue: \"off\",\n optionNotes: FOOTER_MODE_NOTES,\n renderPreview: (mode, ctx, theme) => {\n if (mode === \"off\") return \"hidden\";\n const activeTheme = theme || (ctx.ui as { theme?: Theme })?.theme;\n return previewQuotaFooterText(quotaStatus, ctx.model?.id, mode, activeTheme);\n },\n prepare: async (ctx) => {\n await quotaStatus.ensurePreview(ctx);\n },\n onChange: async (ctx, _value) => {\n if (quotaStatus.mode() !== \"off\") {\n await quotaStatus.refresh(ctx, { ignoreMode: true });\n }\n quotaStatus.paint(ctx);\n },\n };\n}\n\nexport function registerQuotaSettings(quotaStatus: QuotaStatusCoordinator): void {\n registerSettingField(createQuotaFooterField(quotaStatus));\n}\n\nexport interface RefreshOptions {\n force?: boolean;\n // Explicit looks at quota (/antigravity usage) bypass the mode and model\n // gates but still calibrate, persist, and share the throttle window.\n ignoreMode?: boolean;\n signal?: AbortSignal;\n}\n\nfunction isFiniteNumber(value: unknown): value is number {\n return typeof value === \"number\" && Number.isFinite(value);\n}\n\n// Lenient shape check for persisted observations; garbage restores as absent.\nfunction validPairs(raw: unknown): Record<string, WindowFractionPair> | undefined {\n if (!raw || typeof raw !== \"object\" || Array.isArray(raw)) return undefined;\n const pairs: Record<string, WindowFractionPair> = {};\n for (const [key, value] of Object.entries(raw)) {\n const rec = value as { \"5h\"?: unknown; weekly?: unknown };\n const fiveHour = rec?.[\"5h\"];\n const weekly = rec?.weekly;\n if (isFiniteNumber(fiveHour) && isFiniteNumber(weekly)) pairs[key] = { \"5h\": fiveHour, weekly };\n }\n return Object.keys(pairs).length > 0 ? pairs : undefined;\n}\n\nexport type QuotaStatusCtx = Pick<ExtensionContext, \"ui\" | \"modelRegistry\" | \"model\">;\n\n// Pi binds every ExtensionContext property read to a liveness assertion, so a\n// ctx captured before a session replacement or reload throws on any read once\n// the runtime is invalidated. A turn aborted by teardown still emits\n// agent_settled from that invalidated runtime, so handlers receive a dead ctx.\n// Probe once before touching it \u2014 painting a dead session's footer is meaningless.\nfunction isLiveCtx(ctx: QuotaStatusCtx): boolean {\n try {\n void ctx.ui;\n return true;\n } catch {\n return false;\n }\n}\n\nexport interface FooterModeDef {\n key: QuotaFooterMode;\n note?: string;\n render: (\n summary: QuotaSummary | undefined,\n modelId?: string,\n ratio?: number,\n style?: QuotaColorStyle,\n ) => { plain?: string; colored?: string };\n}\n\nexport const FOOTER_MODES: Record<QuotaFooterMode, FooterModeDef> = Object.freeze({\n off: {\n key: \"off\",\n render: () => ({}),\n },\n smart: {\n key: \"smart\",\n note: FOOTER_MODE_NOTES.smart,\n render: (summary, modelId, ratio = DEFAULT_WEEKLY_TO_5H_RATIO, style) => {\n if (!summary) return {};\n const plain = buildQuotaFooter(summary, modelId, ratio);\n return { plain, colored: colorizeQuotaFooter(plain, style) };\n },\n },\n all: {\n key: \"all\",\n note: FOOTER_MODE_NOTES.all,\n render: (summary, modelId, _ratio, style) => {\n if (!summary) return {};\n const plain = buildQuotaFooterBoth(summary, modelId);\n return { plain, colored: colorizeQuotaFooterBoth(plain, style) };\n },\n },\n});\n\nexport function isAntigravityModel(model?: { provider?: string }): boolean {\n return model?.provider === PROVIDER_ID;\n}\n\nexport function paintQuotaStatus(coord: QuotaStatusCoordinator, ctx: QuotaStatusCtx): void {\n coord.paint(ctx);\n}\n\n// In-memory throttle around the quota fetch: at most one network call per\n// QUOTA_REFRESH_INTERVAL_MS, with inflight dedup. Failures keep the stale\n// footer instead of flashing errors in the status bar.\nexport class QuotaStatusCoordinator {\n private summary: QuotaSummary | undefined;\n private fetchedAt = 0;\n private inflight: Promise<QuotaSummary | undefined> | null = null;\n private weeklyTo5hRatio: number;\n private lastPairs: Record<string, WindowFractionPair> | undefined;\n private readonly store: QuotaStatusStore;\n\n constructor(storeOrFile?: string | QuotaStatusStore) {\n if (typeof storeOrFile === \"string\" || !storeOrFile) {\n this.store = fileQuotaStatusStore(storeOrFile || defaultConfigFile());\n } else {\n this.store = storeOrFile;\n }\n this.weeklyTo5hRatio = DEFAULT_WEEKLY_TO_5H_RATIO;\n this.loadPersisted();\n }\n\n get ratio(): number {\n return this.weeklyTo5hRatio;\n }\n\n // Single source of truth for the mode: the injected store.\n mode(): QuotaFooterMode {\n return this.store.loadMode();\n }\n\n footerFor(modelId?: string, mode: QuotaFooterMode = \"smart\"): string | undefined {\n return FOOTER_MODES[mode]?.render(this.summary, modelId, this.weeklyTo5hRatio).plain;\n }\n\n renderFooter(\n modelId?: string,\n mode: QuotaFooterMode = \"smart\",\n style?: QuotaColorStyle,\n ): { plain?: string; colored?: string } {\n return FOOTER_MODES[mode]?.render(this.summary, modelId, this.weeklyTo5hRatio, style) ?? {};\n }\n\n get isFresh(): boolean {\n return !!this.summary && Date.now() - this.fetchedAt < QUOTA_REFRESH_INTERVAL_MS;\n }\n\n refresh(ctx: QuotaStatusCtx, opts: RefreshOptions = {}): Promise<QuotaSummary | undefined> {\n if (!isLiveCtx(ctx)) return Promise.resolve(undefined);\n if (!opts.ignoreMode && (this.mode() === \"off\" || !isAntigravityModel(ctx.model))) {\n return Promise.resolve(undefined);\n }\n if (this.inflight) return this.inflight;\n if (!opts.force && this.isFresh) return Promise.resolve(this.summary);\n return this.fetchOnce(ctx, opts.signal);\n }\n\n // The single ordering behind the footer slot: paint cached text instantly,\n // refresh when the throttle window expired, repaint with fresh text.\n // Event handlers delegate here instead of replicating the sequence.\n async refreshAndPaint(ctx: QuotaStatusCtx): Promise<void> {\n this.paint(ctx);\n await this.refresh(ctx);\n this.paint(ctx);\n }\n\n // Paints current cached quota status to the footer slot.\n paint(ctx: QuotaStatusCtx): void {\n if (!isLiveCtx(ctx)) return;\n const mode = this.mode();\n if (mode === \"off\" || !isAntigravityModel(ctx.model)) {\n ctx.ui.setStatus(QUOTA_STATUS_KEY, undefined);\n return;\n }\n const theme = (ctx.ui as { theme?: Theme })?.theme;\n const { colored } = this.renderFooter(ctx.model?.id, mode, theme);\n ctx.ui.setStatus(QUOTA_STATUS_KEY, colored);\n }\n\n // Atomic inspect for /antigravity usage: forces fresh quota fetch, repaints\n // the footer slot, and formats the full summary. Callers need no flag knowledge.\n async inspectUsage(ctx: QuotaStatusCtx & { signal?: AbortSignal }): Promise<string> {\n const summary = await this.refresh(ctx, { force: true, ignoreMode: true, signal: ctx.signal });\n if (!summary) {\n throw new Error(\"Failed to fetch usage.\");\n }\n this.paint(ctx);\n return formatQuotaSummary(summary);\n }\n\n // One fetch for preview purposes even when the footer slot is off or the\n // current model belongs to another provider: opening quota settings is an\n // explicit look at quota (like /antigravity usage), and the preview is the\n // only place that quota is visible while a foreign model is selected.\n ensurePreview(ctx: QuotaStatusCtx): Promise<QuotaSummary | undefined> {\n if (this.summary) return Promise.resolve(this.summary);\n if (this.inflight) return this.inflight;\n return this.fetchOnce(ctx);\n }\n\n private fetchOnce(ctx: QuotaStatusCtx, signal?: AbortSignal): Promise<QuotaSummary | undefined> {\n this.inflight = this.fetch(ctx, signal).finally(() => {\n this.inflight = null;\n });\n return this.inflight;\n }\n\n private async fetch(\n ctx: QuotaStatusCtx,\n signal?: AbortSignal,\n ): Promise<QuotaSummary | undefined> {\n try {\n const creds = await resolveCredentials(ctx);\n if (!creds) return undefined;\n const rawSummary = await postAntigravityJson<any>({\n auth: creds,\n path: \"v1internal:retrieveUserQuotaSummary\",\n body: { project: creds.projectId },\n signal,\n });\n const summary = parseQuotaSummary(rawSummary);\n this.ingest(summary);\n return summary;\n } catch {\n return undefined;\n }\n }\n\n // Accepts an externally fetched summary into the shared cache: same\n // calibration, persistence, and freshness as fetch().\n ingest(summary: QuotaSummary): void {\n const calibrated = calibrateWeeklyTo5hRatio(\n this.lastPairs,\n extractWindowFractionPairs(summary),\n this.weeklyTo5hRatio,\n );\n this.weeklyTo5hRatio = calibrated;\n this.lastPairs = extractWindowFractionPairs(summary);\n this.summary = summary;\n this.fetchedAt = Date.now();\n this.saveState();\n }\n\n private loadPersisted(): void {\n const entry = this.store.loadQuotaState();\n const ratio = entry?.weeklyTo5hRatio;\n if (typeof ratio === \"number\" && Number.isFinite(ratio) && ratio > 0) {\n this.weeklyTo5hRatio = ratio;\n }\n const at = entry?.updatedAt;\n this.lastPairs =\n typeof at === \"number\" && Date.now() - at <= MAX_OBSERVATION_AGE_MS\n ? validPairs(entry?.previousObservation)\n : undefined;\n }\n\n // Persists calibration state through the injected store. Best-effort: a\n // stale ratio is still usable.\n private saveState(): void {\n try {\n this.store.saveQuotaState({\n weeklyTo5hRatio: this.weeklyTo5hRatio,\n previousObservation: this.lastPairs ?? {},\n updatedAt: Date.now(),\n });\n } catch {\n // Cache is best-effort; a stale ratio is still usable.\n }\n }\n}\n", "import {\n type AssistantMessage,\n type AssistantMessageEventStream,\n type Context,\n type Model,\n type SimpleStreamOptions,\n type TextContent,\n type ThinkingContent,\n type ToolCall,\n createAssistantMessageEventStream,\n} from \"@earendil-works/pi-ai\";\nimport { requireCredentials } from \"./auth.ts\";\nimport { buildAntigravityRequestBody } from \"./builder.ts\";\nimport { postAntigravityStream } from \"./protocol.ts\";\nimport type { ModelCatalog } from \"./model-catalog.ts\";\n\n/**\n * One assembled content block, Pi-spelled (TextContent | ThinkingContent |\n * ToolCall): thinking blocks carry thinkingSignature, text blocks carry\n * textSignature, toolCalls carry the wire-spelled thoughtSignature.\n */\nexport type ParsedBlock = TextContent | ThinkingContent | ToolCall;\n\nexport interface ParsedStreamResult {\n content: ParsedBlock[];\n usage: {\n input: number;\n output: number;\n cacheRead: number;\n /**\n * Reasoning tokens, a subset of `output` (pi-ai Usage.reasoning). Captured\n * turns without a `thoughtsTokenCount` report 0, like pi-ai's own Google\n * adapter does for a missing count.\n */\n reasoning: number;\n total: number;\n };\n stopReason: \"stop\" | \"toolUse\" | \"length\" | \"error\";\n}\n\nexport type StreamDeliveryEvent =\n | { type: \"text_start\" | \"thinking_start\"; contentIndex: number }\n | { type: \"text_delta\" | \"thinking_delta\"; contentIndex: number; delta: string }\n | { type: \"text_end\" | \"thinking_end\"; contentIndex: number; content: string }\n | { type: \"toolcall_start\"; contentIndex: number }\n | { type: \"toolcall_delta\"; contentIndex: number; delta: string }\n | { type: \"toolcall_end\"; contentIndex: number; toolCall: ToolCall };\n\ninterface StreamParserState {\n content: ParsedBlock[];\n usage: ParsedStreamResult[\"usage\"];\n stopReason: ParsedStreamResult[\"stopReason\"];\n openType: \"text\" | \"thinking\" | null;\n lastThoughtSignature?: string;\n buffer: string;\n}\n\nfunction attachLoneSignature(content: ParsedBlock[], lastThoughtSignature?: string): void {\n if (!lastThoughtSignature) return;\n // Not lone: a block already carries it. The wire sends\n // `{thoughtSignature, functionCall}`, whose signature the toolCall branch\n // attaches itself \u2014 pushing a carrier on top of that put an empty text\n // block on a turn that never had one.\n const attached = content.some((b) =>\n b.type === \"thinking\"\n ? Boolean(b.thinkingSignature)\n : b.type === \"toolCall\"\n ? Boolean(b.thoughtSignature)\n : b.type === \"text\"\n ? Boolean(b.textSignature)\n : false,\n );\n if (attached) return;\n\n const thinking = content.find((b): b is ThinkingContent => b.type === \"thinking\");\n if (thinking) {\n if (!thinking.thinkingSignature) thinking.thinkingSignature = lastThoughtSignature;\n return;\n }\n\n for (let i = content.length - 1; i >= 0; i--) {\n const block = content[i];\n if (block?.type === \"text\" && !block.textSignature) {\n block.textSignature = lastThoughtSignature;\n return;\n }\n }\n\n // The turn carried no block to hold it: keep the signature rather than\n // dropping it silently. The builder drops the empty part and replays the\n // signature on the next one, so this never puts an empty text on the wire.\n content.push({ type: \"text\", text: \"\", textSignature: lastThoughtSignature });\n}\n\nfunction closeOpenBlock(\n state: StreamParserState,\n onEvent?: (ev: StreamDeliveryEvent) => void,\n): void {\n if (state.openType === null) return;\n const contentIndex = state.content.length - 1;\n const block = state.content[contentIndex];\n if (block?.type === \"thinking\") {\n onEvent?.({ type: \"thinking_end\", contentIndex, content: block.thinking });\n } else if (block?.type === \"text\") {\n onEvent?.({ type: \"text_end\", contentIndex, content: block.text });\n }\n state.openType = null;\n}\n\nfunction processLine(\n rawLine: string,\n state: StreamParserState,\n onEvent?: (ev: StreamDeliveryEvent) => void,\n): void {\n const line = rawLine.trim();\n if (!line.startsWith(\"data:\")) return;\n\n const dataStr = line.slice(5).trim();\n if (!dataStr || dataStr === \"[DONE]\") return;\n\n let payload: any;\n try {\n payload = JSON.parse(dataStr);\n } catch {\n return;\n }\n\n const response = payload.response || payload;\n\n // Usage metadata (promptTokenCount includes cached tokens per Google spec).\n // output counts thinking tokens too, mirroring the pi-ai Google adapter:\n // usageMetadata reports candidates and thoughts separately.\n if (response.usageMetadata) {\n const um = response.usageMetadata;\n const promptTokens = typeof um.promptTokenCount === \"number\" ? um.promptTokenCount : 0;\n const cacheRead = typeof um.cachedContentTokenCount === \"number\" ? um.cachedContentTokenCount : 0;\n state.usage.input = Math.max(0, promptTokens - cacheRead);\n state.usage.cacheRead = cacheRead;\n const candidates = typeof um.candidatesTokenCount === \"number\" ? um.candidatesTokenCount : 0;\n const thoughts = typeof um.thoughtsTokenCount === \"number\" ? um.thoughtsTokenCount : 0;\n state.usage.output = candidates + thoughts;\n state.usage.reasoning = thoughts;\n if (typeof um.totalTokenCount === \"number\") state.usage.total = um.totalTokenCount;\n }\n\n const candidate = response.candidates?.[0];\n if (!candidate) return;\n\n // Sticky: length/error/toolUse are never downgraded by a later STOP.\n // Mirrors pi-ai mapStopReasonString: only STOP is benign, MAX_TOKENS is\n // length, every other reason (SAFETY, RECITATION, BLOCKLIST, ...) is error.\n if (candidate.finishReason === \"MAX_TOKENS\") {\n state.stopReason = \"length\";\n } else if (typeof candidate.finishReason === \"string\" && candidate.finishReason !== \"STOP\") {\n state.stopReason = \"error\";\n }\n\n const parts = candidate.content?.parts || [];\n for (const part of parts) {\n if (part.thoughtSignature) {\n state.lastThoughtSignature = part.thoughtSignature;\n }\n\n if (part.thought) {\n const delta = part.text || \"\";\n // A part carrying no thinking text opens no block: the wire uses empty\n // thought parts as Thought Signature carriers, and an eager block would\n // outlive the turn as an empty thinking block, which the builder replays\n // as `{thought:true,text:\"\"}` \u2014 a part the wire never sends. The signature is\n // already recorded above; close() keeps a carrier for it.\n if (delta === \"\" && state.openType !== \"thinking\") continue;\n if (state.openType !== \"thinking\") {\n closeOpenBlock(state, onEvent);\n state.content.push({ type: \"thinking\", thinking: \"\" });\n onEvent?.({ type: \"thinking_start\", contentIndex: state.content.length - 1 });\n state.openType = \"thinking\";\n }\n const block = state.content[state.content.length - 1];\n if (block?.type !== \"thinking\") continue;\n block.thinking += delta;\n if (part.thoughtSignature) {\n block.thinkingSignature = part.thoughtSignature;\n }\n onEvent?.({\n type: \"thinking_delta\",\n contentIndex: state.content.length - 1,\n delta,\n });\n } else if (part.functionCall) {\n closeOpenBlock(state, onEvent);\n state.stopReason = \"toolUse\";\n const block: ToolCall = {\n type: \"toolCall\",\n id: part.functionCall.id || `call_${state.content.length}`,\n name: part.functionCall.name || \"\",\n arguments: part.functionCall.args || {},\n thoughtSignature: part.thoughtSignature || state.lastThoughtSignature,\n };\n state.content.push(block);\n const contentIndex = state.content.length - 1;\n onEvent?.({ type: \"toolcall_start\", contentIndex });\n onEvent?.({\n type: \"toolcall_delta\",\n contentIndex,\n delta: JSON.stringify(block.arguments),\n });\n onEvent?.({ type: \"toolcall_end\", contentIndex, toolCall: block });\n } else if (part.text !== undefined) {\n // Same rule as the thinking branch: an empty text part is a Thought\n // Signature carrier (or a streamed artifact), not content, so it opens no\n // block. 7 of the 26 frozen responses and 91% of live antigravity turns\n // carried the empty block this used to create.\n if (part.text === \"\" && state.openType !== \"text\") continue;\n if (state.openType !== \"text\") {\n closeOpenBlock(state, onEvent);\n state.content.push({ type: \"text\", text: \"\" });\n onEvent?.({ type: \"text_start\", contentIndex: state.content.length - 1 });\n state.openType = \"text\";\n }\n const block = state.content[state.content.length - 1];\n if (block?.type !== \"text\") continue;\n block.text += part.text;\n onEvent?.({ type: \"text_delta\", contentIndex: state.content.length - 1, delta: part.text });\n }\n }\n}\n\nfunction feedChunk(\n chunk: string,\n state: StreamParserState,\n onEvent?: (ev: StreamDeliveryEvent) => void,\n): void {\n state.buffer += chunk;\n const lines = state.buffer.split(\"\\n\");\n state.buffer = lines.pop() || \"\";\n for (const line of lines) {\n processLine(line, state, onEvent);\n }\n}\n\nfunction finishStream(\n state: StreamParserState,\n onEvent?: (ev: StreamDeliveryEvent) => void,\n): void {\n if (state.buffer.trim() !== \"\") {\n processLine(state.buffer, state, onEvent);\n }\n state.buffer = \"\";\n closeOpenBlock(state, onEvent);\n attachLoneSignature(state.content, state.lastThoughtSignature);\n}\n\n/**\n * Pure parsing seam for whole or chunked SSE wire responses (fixtures, replay, tests).\n * Replaces the shallow createSseFeed adapter with direct response decoding.\n */\nexport function parseAntigravitySseResponse(\n rawSse: string | Iterable<string>,\n onEvent?: (ev: StreamDeliveryEvent) => void,\n): ParsedStreamResult {\n const state: StreamParserState = {\n content: [],\n usage: { input: 0, output: 0, cacheRead: 0, reasoning: 0, total: 0 },\n stopReason: \"stop\",\n openType: null,\n buffer: \"\",\n };\n\n if (typeof rawSse === \"string\") {\n feedChunk(rawSse, state, onEvent);\n } else {\n for (const chunk of rawSse) {\n feedChunk(chunk, state, onEvent);\n }\n }\n finishStream(state, onEvent);\n\n return {\n content: state.content,\n usage: state.usage,\n stopReason: state.stopReason,\n };\n}\n\nasync function consumeAntigravityStream(\n streamBody: ReadableStream<Uint8Array>,\n output: AssistantMessage,\n stream: AssistantMessageEventStream,\n modelCost?: Model<any>[\"cost\"],\n): Promise<void> {\n const state: StreamParserState = {\n content: output.content,\n usage: { input: 0, output: 0, cacheRead: 0, reasoning: 0, total: 0 },\n stopReason: \"stop\",\n openType: null,\n buffer: \"\",\n };\n\n const updateUsageAndCost = () => {\n output.usage.input = state.usage.input;\n output.usage.cacheRead = state.usage.cacheRead;\n output.usage.output = state.usage.output;\n output.usage.reasoning = state.usage.reasoning;\n output.usage.totalTokens = state.usage.total;\n\n if (modelCost) {\n const inputCost = (output.usage.input * (modelCost.input || 0)) / 1_000_000;\n const outputCost = (output.usage.output * (modelCost.output || 0)) / 1_000_000;\n const cacheCost = (output.usage.cacheRead * (modelCost.cacheRead || 0)) / 1_000_000;\n output.usage.cost = {\n input: inputCost,\n output: outputCost,\n cacheRead: cacheCost,\n cacheWrite: 0,\n total: inputCost + outputCost + cacheCost,\n };\n }\n output.stopReason = state.stopReason;\n };\n\n const dispatchEvent = (ev: StreamDeliveryEvent) => {\n updateUsageAndCost();\n stream.push({ ...ev, partial: output });\n };\n\n const reader = streamBody.getReader();\n const decoder = new TextDecoder();\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n feedChunk(decoder.decode(value, { stream: true }), state, dispatchEvent);\n }\n\n finishStream(state, dispatchEvent);\n updateUsageAndCost();\n}\n\n/**\n * Stream Delivery Module: the deep module encapsulating wire byte streaming,\n * incremental SSE decoding, usage accounting, Thought Signature placement,\n * and direct Pi AssistantMessageEventStream dispatch.\n */\nexport function streamAntigravity(\n model: Model<any>,\n context: Context,\n options: SimpleStreamOptions | undefined,\n catalog: ModelCatalog,\n): AssistantMessageEventStream {\n const stream = createAssistantMessageEventStream();\n\n (async () => {\n const output: AssistantMessage = {\n role: \"assistant\",\n content: [],\n api: model.api,\n provider: model.provider,\n model: model.id,\n usage: {\n input: 0,\n output: 0,\n cacheRead: 0,\n cacheWrite: 0,\n totalTokens: 0,\n cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n },\n stopReason: \"pending\",\n timestamp: Date.now(),\n };\n\n try {\n stream.push({ type: \"start\", partial: output });\n\n const { token, projectId } = await requireCredentials(options);\n\n const effort = options?.reasoning;\n // trajectoryId is provider-specific (absent from the SDK options\n // type), so read it via runtime-checked `in` narrowing instead of a cast.\n const trajectoryId =\n options && \"trajectoryId\" in options && typeof options.trajectoryId === \"string\"\n ? options.trajectoryId\n : undefined;\n const plan = catalog.resolvePlan(model.id, effort);\n\n const requestBody = buildAntigravityRequestBody({\n projectId,\n plan,\n context,\n sessionId: options?.sessionId,\n trajectoryId,\n maxOutputTokens: model.maxTokens,\n toolChoice: options?.toolChoice,\n });\n\n const streamBody = await postAntigravityStream({\n auth: token,\n path: \"v1internal:streamGenerateContent?alt=sse\",\n body: requestBody,\n signal: options?.signal,\n });\n\n await consumeAntigravityStream(streamBody, output, stream, model.cost);\n\n const doneReason: \"stop\" | \"toolUse\" | \"length\" =\n output.stopReason === \"toolUse\" || output.stopReason === \"length\"\n ? output.stopReason\n : \"stop\";\n\n stream.push({\n type: \"done\",\n reason: doneReason,\n message: output,\n });\n stream.end();\n } catch (error) {\n output.stopReason = options?.signal?.aborted ? \"aborted\" : \"error\";\n output.errorMessage = error instanceof Error ? error.message : String(error);\n stream.push({ type: \"error\", reason: output.stopReason, error: output });\n stream.end();\n }\n })();\n\n return stream;\n}\n", "import { createHash, randomUUID } from \"node:crypto\";\nimport type { ModelPlan } from \"./model-catalog.ts\";\nimport { classifyModelFamily, isCompatibleFamily } from \"./model-identity.ts\";\nimport { PROVIDER_ID } from \"./protocol.ts\";\n\nexport interface BuildRequestBodyParams {\n projectId: string;\n plan: ModelPlan;\n context: {\n systemPrompt?: string;\n messages: Array<any>;\n tools?: Array<any>;\n };\n sessionId?: string;\n trajectoryId?: string;\n maxOutputTokens?: number;\n toolChoice?: string;\n}\n\nconst BASE64_SIGNATURE_PATTERN = /^[A-Za-z0-9+/_-]+={0,2}$/;\n\n/**\n * Gemini 3 rejects a `functionCall` part that carries no `thoughtSignature` while\n * it sits inside the current turn (validation covers \"all steps in the current\n * turn\"; a turn begins with the most recent user message that is not a\n * functionResponse) with 400 INVALID_ARGUMENT \"Function call is missing a\n * thought_signature in functionCall parts\". Dropping an unreplayable signature\n * (below) leaves exactly that state, and a cross-provider model switch mid-tool\n * turn is the everyday way to produce it: the other provider's tool call has no\n * signature to replay, and it is the pending step of the current turn.\n *\n * Google documents one escape hatch for `functionCall` parts \"that were not\n * generated by the API ... for example, when transferring history from a model\n * that does not include thought signatures\" \u2014 the literal sentinel below, which\n * trades that call's reasoning continuity (it is gone either way) for a request\n * the backend accepts.\n *\n * Live probe validation (gemini-3.8-flash-low): unsigned foreign functionCall as the pending step\n * of the current turn \u2192 400 with the message above; the identical body with this\n * sentinel on that single part \u2192 200.\n *\n * Applied to foreign calls only. A signature we *should* have had \u2014\n * same provider and family, yet missing or unreadable (pipeline regression, damaged\n * session) \u2014 keeps failing loudly with the 400 above instead of being papered over,\n * so a lost signature stays visible as a bug rather than silently degrading the\n * model's reasoning for that call.\n */\nexport const SKIP_THOUGHT_SIGNATURE_VALIDATOR = \"skip_thought_signature_validator\";\n\n/**\n * Verifies that a thought signature candidate is a valid base64 string suitable\n * for Google Protobuf TYPE_BYTES fields in JSON mapping.\n */\nfunction isValidThoughtSignature(sig: unknown): sig is string {\n if (typeof sig !== \"string\" || sig.length === 0) return false;\n if (sig.includes(\"=\") && sig.length % 4 !== 0) return false;\n return BASE64_SIGNATURE_PATTERN.test(sig);\n}\n\n/**\n * Resolves a thoughtSignature candidate only when coming from the same provider and\n * compatible model family, and only when formatted as valid base64.\n */\nfunction resolveThoughtSignature(\n isSameProviderAndModel: boolean,\n sig: unknown\n): string | undefined {\n if (!isSameProviderAndModel) return undefined;\n return isValidThoughtSignature(sig) ? sig : undefined;\n}\n\n/**\n * Deterministically derives a persistent session ID from the initial conversation turn.\n */\nfunction deriveSessionId(\n context: { messages?: Array<any>; systemPrompt?: string },\n explicitSessionId?: string\n): string {\n if (explicitSessionId && typeof explicitSessionId === \"string\" && explicitSessionId.trim().length > 0) {\n return explicitSessionId.trim();\n }\n\n const firstMsg = context.messages?.[0];\n if (!firstMsg) {\n return randomUUID();\n }\n\n const seedContent =\n typeof firstMsg.content === \"string\"\n ? firstMsg.content\n : JSON.stringify(firstMsg.content || \"\");\n\n const hash = createHash(\"sha256\")\n .update(`antigravity:conversation:${seedContent}`)\n .digest()\n .subarray(0, 16);\n\n hash[6] = (hash[6] & 0x0f) | 0x40; // v4 UUID\n hash[8] = (hash[8] & 0x3f) | 0x80;\n const hex = [...hash].map((b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;\n}\n\n/**\n * Computes deterministic v5 UUID trajectory ID from the session ID.\n */\nfunction resolveSessionTrajectory(sessionId: string): string {\n const bytes = createHash(\"sha1\").update(`antigravity:${sessionId}`).digest().subarray(0, 16);\n bytes[6] = (bytes[6] & 0x0f) | 0x50; // v5 UUID\n bytes[8] = (bytes[8] & 0x3f) | 0x80;\n const hex = [...bytes].map((b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;\n}\n\n/**\n * Signed 64-bit `request.sessionId`. Constant in the wire protocol specification \u2014 no\n * conversation/account input.\n */\nconst DEFAULT_SESSION_ID = \"-3750763034362895579\";\n\n/**\n * Pure-numeric session IDs (`stream.ts` override) pass through verbatim.\n */\nfunction resolveNumericSessionId(sessionId: string): string {\n if (/^-?\\d+$/.test(sessionId)) {\n return sessionId;\n }\n return DEFAULT_SESSION_ID;\n}\n\n/**\n * Normalizes tool call IDs for cross-provider compatibility.\n */\nfunction normalizeToolCallId(id: string | undefined): string | undefined {\n if (!id || typeof id !== \"string\") return id;\n return id.replace(/[^a-zA-Z0-9_-]/g, \"_\").slice(0, 64);\n}\n\nconst CUSTOM_TOOL_SCHEMA_ALLOW = new Set([\n \"type\",\n \"description\",\n \"properties\",\n \"required\",\n \"items\",\n \"enum\",\n]);\n\nfunction stripMetaSchema(schema: unknown): unknown {\n if (!schema || typeof schema !== \"object\" || Array.isArray(schema)) return schema;\n const omit = new Set([\"$schema\", \"$id\", \"$defs\", \"definitions\"]);\n const out: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(schema)) {\n if (!omit.has(key)) out[key] = stripMetaSchema(value);\n }\n return out;\n}\n\nfunction normalizeCustomToolSchema(schema: unknown): unknown {\n if (!schema || typeof schema !== \"object\") return schema;\n if (Array.isArray(schema)) return schema.map(normalizeCustomToolSchema);\n\n const s = schema as Record<string, unknown>;\n const out: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(s)) {\n if (!CUSTOM_TOOL_SCHEMA_ALLOW.has(key)) {\n // Map string const to single-item enum for Claude bridge compatibility\n if (key === \"const\" && s.enum === undefined && typeof value === \"string\") {\n out.enum = [value];\n }\n continue;\n }\n if (key === \"type\" && Array.isArray(value)) {\n const scalar = value.find((e) => typeof e === \"string\" && e !== \"null\");\n if (scalar) out.type = scalar;\n continue;\n }\n if (key === \"properties\" && value && typeof value === \"object\" && !Array.isArray(value)) {\n const props: Record<string, unknown> = {};\n for (const [propName, propSchema] of Object.entries(value as Record<string, unknown>)) {\n props[propName] = normalizeCustomToolSchema(propSchema);\n }\n out.properties = props;\n continue;\n }\n if (key === \"enum\" && Array.isArray(value) && !value.every((e) => typeof e === \"string\")) {\n continue;\n }\n out[key] = normalizeCustomToolSchema(value);\n }\n return out;\n}\n\n/**\n * Strict wire compatibility: declarations use legacy\n * `parameters`, never `parametersJsonSchema` \u2014 for Gemini\n * and non-Gemini models alike. Declarations also carry no\n * anyOf/patternProperties/const keys, hence the normalization below.\n */\nfunction convertTools(\n tools: Array<any> | undefined\n): Array<{ functionDeclarations: Array<any> }> | undefined {\n if (!tools?.length) return undefined;\n return [\n {\n functionDeclarations: tools.map((tool) => {\n const schema = stripMetaSchema(tool.parameters) || { type: \"object\", properties: {} };\n return {\n name: tool.name,\n description: tool.description,\n parameters: normalizeCustomToolSchema(schema),\n };\n }),\n },\n ];\n}\n\n/**\n * Translates a conversation turn trace into Antigravity wire contents.\n */\nfunction translateTurnTrace(\n context: { messages?: Array<any>; systemPrompt?: string },\n runtimeModelId: string\n): Array<any> {\n const contents: Array<any> = [];\n const messages = context.messages || [];\n\n // The sentinel is Gemini-specific evidence: the probe shows a Claude runtime model\n // accepts the same unsigned foreign functionCall with no sentinel at all (and merely\n // tolerates the sentinel), so Claude/GPT requests keep today's shape.\n const isGeminiRequest = classifyModelFamily(runtimeModelId) === \"gemini\";\n // GPT requests carry no reasoning history on the wire: a replay sends\n // the response as plain text only, no thought part and no signature.\n // Gemini and Claude both replay reasoning, so a gpt request drops the\n // block instead of serializing it.\n const isGptRequest = classifyModelFamily(runtimeModelId) === \"gpt\";\n\n for (const msg of messages) {\n if (msg.role === \"user\") {\n const parts: Array<any> = [];\n if (typeof msg.content === \"string\") {\n parts.push({ text: msg.content });\n } else if (Array.isArray(msg.content)) {\n for (const item of msg.content) {\n if (item.type === \"text\") {\n parts.push({ text: item.text });\n } else if (item.type === \"image\") {\n parts.push({\n inlineData: {\n mimeType: item.mimeType || \"image/png\",\n data: item.data,\n },\n });\n }\n }\n }\n if (parts.length > 0) {\n contents.push({ role: \"user\", parts });\n }\n } else if (msg.role === \"assistant\") {\n if (msg.stopReason === \"error\" || msg.stopReason === \"aborted\") {\n continue;\n }\n\n const isSameProvider = !msg.provider || msg.provider === PROVIDER_ID;\n const isSameModel = isCompatibleFamily(msg.model, runtimeModelId);\n const isSameProviderAndModel = isSameProvider && isSameModel;\n\n const parts: Array<any> = [];\n // Canonical wire shape: a thinking replay never carries its\n // own signature \u2014 it stays pending and rides on the NEXT text/functionCall\n // part. Only when the turn ends with no carrying part does it fall back\n // onto the last part (uncovered edge, same as the message-level fallback).\n // Signature fields are canonical SDK spellings only (textSignature /\n // thinkingSignature on blocks, thoughtSignature on toolCalls). No\n // legacy-spelling reads: pre-#26 sessions are abandoned (see #26).\n let pendingThinkingSig: string | undefined;\n if (typeof msg.content === \"string\") {\n parts.push({ text: msg.content });\n } else if (Array.isArray(msg.content)) {\n for (const item of msg.content) {\n if (item.type === \"text\") {\n if (typeof item.text !== \"string\" || item.text === \"\") {\n // Vacuous text block (e.g. a leading empty part the live feed\n // opened): drop the part but keep a valid signature pending\n // for the next part carrying one, mirroring the precedence\n // below. The Claude backend rejects {\"text\": \"\"} with 400\n // (text.text: Field required, observed live on multi-turn\n // replay); Gemini accepts the same payload (probed 200), but\n // an empty part carries nothing either way, and the wire never\n // emits one, so this stays regardless of model family.\n pendingThinkingSig =\n resolveThoughtSignature(isSameProviderAndModel, item.textSignature) ||\n pendingThinkingSig;\n continue;\n }\n const part: any = { text: item.text };\n const sig =\n resolveThoughtSignature(\n isSameProviderAndModel,\n item.textSignature\n ) || pendingThinkingSig;\n if (sig) {\n part.thoughtSignature = sig;\n pendingThinkingSig = undefined;\n }\n parts.push(part);\n } else if (item.type === \"thinking\") {\n const candidateSig = item.thinkingSignature;\n const isForeignReasoning =\n !isSameProviderAndModel ||\n (typeof candidateSig === \"string\" && candidateSig.trim().startsWith(\"{\"));\n\n // Same-family gpt reasoning is dropped, not serialized: the wire has no\n // shape for it. Foreign reasoning keeps the\n // context-preserving text fallback below, which has no single-provider counterpart.\n if (isGptRequest && !isForeignReasoning) continue;\n\n if (!isForeignReasoning) {\n // No thoughtSignature here by design: it stays pending for the\n // next text/functionCall part (canonical wire part-split shape).\n const part: any = {\n thought: true,\n text: item.thinking || \"\",\n };\n const sig = resolveThoughtSignature(true, candidateSig);\n if (sig) {\n pendingThinkingSig = sig;\n }\n parts.push(part);\n } else {\n // Cross-provider/model or foreign reasoning item: drop foreign signature and\n // serialize reasoning text (or summary) as plain text so the model retains\n // conversation context without failing Google's TYPE_BYTES base64 validation.\n let text = item.thinking || \"\";\n if (!text && typeof candidateSig === \"string\" && candidateSig.trim().startsWith(\"{\")) {\n try {\n const parsed = JSON.parse(candidateSig);\n if (Array.isArray(parsed.summary)) {\n text = parsed.summary\n .filter((s: any) => s && typeof s.text === \"string\")\n .map((s: any) => s.text)\n .join(\"\\n\");\n }\n } catch {\n // Ignore JSON parse errors\n }\n }\n if (text && text.trim() !== \"\") {\n parts.push({ text });\n }\n }\n } else if (item.type === \"tool_use\" || item.type === \"toolCall\") {\n const part: any = {\n functionCall: {\n id: normalizeToolCallId(item.id),\n name: item.name,\n args: item.input || item.arguments || {},\n },\n };\n const sig =\n resolveThoughtSignature(\n isSameProviderAndModel,\n item.thoughtSignature\n ) || pendingThinkingSig;\n if (sig) {\n part.thoughtSignature = sig;\n pendingThinkingSig = undefined;\n } else if (isGeminiRequest && !isSameProviderAndModel) {\n part.thoughtSignature = SKIP_THOUGHT_SIGNATURE_VALIDATOR;\n }\n parts.push(part);\n }\n }\n }\n if (parts.length > 0) {\n if (pendingThinkingSig && !parts.some((p) => p.thoughtSignature)) {\n parts[parts.length - 1].thoughtSignature = pendingThinkingSig;\n }\n contents.push({ role: \"model\", parts });\n }\n } else if (msg.role === \"toolResult\") {\n let toolName = msg.toolName || msg.name;\n if (!toolName && (msg.toolCallId || msg.id)) {\n const rawTargetId = msg.toolCallId || msg.id;\n const normTargetId = normalizeToolCallId(rawTargetId);\n for (const prev of messages) {\n if (prev.role === \"assistant\" && Array.isArray(prev.content)) {\n const found = prev.content.find(\n (c: any) =>\n (c.type === \"tool_use\" || c.type === \"toolCall\") &&\n (c.id === rawTargetId || normalizeToolCallId(c.id) === normTargetId)\n );\n if (found) {\n toolName = found.name;\n break;\n }\n }\n }\n }\n\n let toolText = \"\";\n const imageParts: Array<any> = [];\n\n if (Array.isArray(msg.content)) {\n const textParts: string[] = [];\n for (const c of msg.content) {\n if (typeof c === \"string\") {\n textParts.push(c);\n } else if (c.type === \"text\") {\n textParts.push(c.text);\n } else if (c.type === \"image\") {\n imageParts.push({\n inlineData: {\n mimeType: c.mimeType || \"image/png\",\n data: c.data,\n },\n });\n } else {\n textParts.push(JSON.stringify(c));\n }\n }\n toolText = textParts.join(\"\\n\");\n } else if (typeof msg.content === \"string\") {\n toolText = msg.content;\n } else if (msg.content) {\n toolText = JSON.stringify(msg.content);\n }\n\n // Strict wire parity:\n // - response is always { output: string }, never a top-level list.\n // - error tool results also use the \"output\" key.\n const responseObj = { output: toolText };\n\n const functionResponse: any = {\n name: toolName || \"tool\",\n response: responseObj,\n };\n\n const rawCallId = msg.toolCallId || msg.id;\n const callId = normalizeToolCallId(rawCallId);\n if (callId) {\n functionResponse.id = callId;\n }\n\n if (imageParts.length > 0) {\n functionResponse.parts = imageParts;\n }\n\n contents.push({\n role: \"model\",\n parts: [{ functionResponse }],\n });\n }\n }\n\n // Antigravity rejects requests ending with an incomplete model turn.\n if (contents.length > 0) {\n const lastContent = contents[contents.length - 1];\n if (\n lastContent.role === \"model\" &&\n !lastContent.parts?.some((p: any) => p.functionResponse)\n ) {\n contents.push({\n role: \"user\",\n parts: [{ text: \"continue\" }],\n });\n }\n }\n\n return contents;\n}\n\n/**\n * Builds the complete Antigravity Wire Fingerprint request envelope.\n * Encapsulates session identity derivation, Thought Signature replay,\n * Turn Trace translation, and tool schema normalization.\n */\nexport function buildAntigravityRequestBody(params: BuildRequestBodyParams): Record<string, any> {\n const {\n projectId,\n plan,\n context,\n maxOutputTokens = 65536,\n } = params;\n const runtimeModelId = plan.runtimeModelId;\n\n const sessionId = deriveSessionId(context, params.sessionId);\n const trajectoryId =\n params.trajectoryId && typeof params.trajectoryId === \"string\" && params.trajectoryId.trim().length > 0\n ? params.trajectoryId.trim()\n : resolveSessionTrajectory(sessionId);\n const contents = translateTurnTrace(context, runtimeModelId);\n\n // Request ID sequence increments by completed assistant turns **as carried by\n // this request**: derive it from the payload, so a turn the translation drops\n // (stopReason error/aborted, empty content, all-empty parts) can never desync\n // the label from `contents` \u2014 matches the wire protocol specification.\n const requestIndex = contents.filter(\n (c) => c.role === \"model\" && !c.parts?.some((p: any) => p.functionResponse)\n ).length;\n const requestId = `agent/${sessionId}/${Date.now()}/${trajectoryId}/${contents.length}`;\n\n const modelEnum = plan.modelEnum;\n\n const labels: Record<string, string> = {\n last_step_index: String(Math.max(0, contents.length - 1)),\n model_enum: modelEnum,\n request_id: `${trajectoryId}-${requestIndex}`,\n trajectory_id: trajectoryId,\n used_claude: String(plan.isClaude),\n used_claude_conservative: String(plan.isClaude),\n used_non_gemini_model: String(plan.isNonGemini),\n };\n\n const generationConfig: Record<string, any> = {\n maxOutputTokens,\n thinkingConfig: plan.thinkingConfig,\n };\n\n const request: Record<string, any> = {\n contents,\n };\n\n if (context.systemPrompt) {\n request.systemInstruction = {\n role: \"user\",\n parts: [{ text: context.systemPrompt }],\n };\n }\n\n const tools = convertTools(context.tools);\n if (tools) {\n request.tools = tools;\n }\n\n if (params.toolChoice && params.toolChoice !== \"auto\" && params.toolChoice !== \"Auto\") {\n let mode = \"AUTO\";\n const tc = String(params.toolChoice).toLowerCase();\n if (tc === \"none\") mode = \"NONE\";\n else if (tc === \"any\" || tc === \"required\") mode = \"ANY\";\n request.toolConfig = {\n functionCallingConfig: {\n mode,\n },\n };\n }\n\n request.labels = labels;\n request.generationConfig = generationConfig;\n request.sessionId = resolveNumericSessionId(sessionId);\n\n return {\n project: projectId,\n requestId,\n request,\n model: runtimeModelId,\n userAgent: \"antigravity\",\n requestType: \"agent\",\n };\n}\n", "import { postAntigravityJson } from \"./protocol.ts\";\nimport { FALLBACK_PROJECT_ID, type AntigravityCredentials } from \"./auth.ts\";\n\nexport interface WebSearchOptions {\n query: string;\n domain?: string;\n signal?: AbortSignal;\n}\n\nexport interface GroundingChunk {\n web?: {\n uri: string;\n title: string;\n };\n}\n\nexport interface GroundingSupport {\n segment?: {\n startIndex?: number;\n endIndex?: number;\n text?: string;\n };\n groundingChunkIndices?: number[];\n}\n\nexport interface GroundingMetadata {\n webSearchQueries?: string[];\n searchEntryPoint?: {\n renderedContent?: string;\n };\n groundingChunks?: GroundingChunk[];\n groundingSupports?: GroundingSupport[];\n}\n\nexport interface SearchCandidate {\n content?: {\n role: string;\n parts?: Array<{\n text?: string;\n thoughtSignature?: string;\n }>;\n };\n finishReason?: string;\n groundingMetadata?: GroundingMetadata;\n}\n\nexport interface SearchApiResponse {\n response?: {\n candidates?: SearchCandidate[];\n usageMetadata?: {\n promptTokenCount?: number;\n candidatesTokenCount?: number;\n totalTokenCount?: number;\n };\n modelVersion?: string;\n responseId?: string;\n };\n traceId?: string;\n metadata?: unknown;\n}\n\nexport interface SearchSource {\n index: number;\n title: string;\n url: string;\n}\n\nexport interface SearchResult {\n query: string;\n rawText: string;\n formattedOutput: string;\n sources: SearchSource[];\n queries: string[];\n createdAt: string;\n completedAt: string;\n}\n\nexport const SEARCH_SYSTEM_INSTRUCTION =\n \"You are a search engine bot. You will be given a query from a user. \" +\n \"Your task is to search the web for relevant information that will help the user. \" +\n \"You MUST perform a web search. Do not respond or interact with the user, \" +\n \"please respond as if they typed the query into a search bar.\";\n\nexport const SEARCH_MODEL = \"gemini-3.1-flash-lite\";\n\n/**\n * Annotates the raw text with inline citations [1][2] and appends Sources list,\n * matching agy CLI's exact Wire output shape.\n */\nexport function formatSearchResults(\n rawText: string,\n metadata: GroundingMetadata | undefined,\n query: string,\n createdAt: string,\n completedAt: string\n): SearchResult {\n const sources: SearchSource[] = (metadata?.groundingChunks || [])\n .map((chunk, i) => ({\n index: i + 1,\n title: chunk.web?.title || \"Web Source\",\n url: chunk.web?.uri || \"\",\n }))\n .filter((s) => Boolean(s.url));\n\n const queries = metadata?.webSearchQueries || [];\n\n let annotatedText = rawText;\n const supports = (metadata?.groundingSupports || [])\n .filter(\n (s): s is GroundingSupport & { segment: { endIndex: number } } =>\n typeof s.segment?.endIndex === \"number\" &&\n Array.isArray(s.groundingChunkIndices) &&\n s.groundingChunkIndices.length > 0\n )\n .slice()\n .sort((a, b) => (b.segment.endIndex ?? 0) - (a.segment.endIndex ?? 0));\n\n // Insert footnote citations from end to start so indices stay stable\n for (const sup of supports) {\n const end = sup.segment.endIndex;\n if (end >= 0 && end <= annotatedText.length) {\n const citations = (sup.groundingChunkIndices || [])\n .map((idx) => `[${idx + 1}]`)\n .join(\"\");\n annotatedText = annotatedText.slice(0, end) + citations + annotatedText.slice(end);\n }\n }\n\n const sourceLines = sources.map((s) => `[${s.index}] [${s.title}](${s.url})`);\n\n let formattedOutput =\n `Created At: ${createdAt}\\n` +\n `Completed At: ${completedAt}\\n` +\n `The search for \"${query}\" returned the following summary:\\n` +\n `${annotatedText.trim() || \"No content returned.\"}`;\n\n if (sourceLines.length > 0) {\n formattedOutput += `\\n\\nSources:\\n${sourceLines.join(\"\\n\")}`;\n }\n\n return {\n query,\n rawText,\n formattedOutput,\n sources,\n queries,\n createdAt,\n completedAt,\n };\n}\n\n/**\n * Executes a live Google Web Search with Search Grounding via Antigravity backend,\n * replicating agy CLI's native search_web tool call.\n */\nexport async function performWebSearch(\n creds: AntigravityCredentials,\n options: WebSearchOptions\n): Promise<SearchResult> {\n const createdAt = new Date().toISOString();\n let effectiveQuery = options.query.trim();\n if (options.domain && options.domain.trim()) {\n const d = options.domain.trim();\n if (!effectiveQuery.toLowerCase().includes(`site:${d.toLowerCase()}`)) {\n effectiveQuery = `${effectiveQuery} site:${d}`;\n }\n }\n\n const reqBody = {\n project: creds.projectId || FALLBACK_PROJECT_ID,\n request: {\n contents: [\n {\n role: \"user\",\n parts: [{ text: effectiveQuery }],\n },\n ],\n systemInstruction: {\n role: \"user\",\n parts: [{ text: SEARCH_SYSTEM_INSTRUCTION }],\n },\n tools: [\n {\n googleSearch: {\n enhancedContent: {\n imageSearch: {\n maxResultCount: 5,\n },\n },\n },\n },\n ],\n generationConfig: {\n candidateCount: 1,\n },\n },\n model: SEARCH_MODEL,\n userAgent: \"antigravity\",\n requestType: \"web_search\",\n };\n\n const resp = await postAntigravityJson<SearchApiResponse>({\n auth: creds.token,\n path: \"v1internal:generateContent\",\n body: reqBody,\n signal: options.signal,\n });\n\n const completedAt = new Date().toISOString();\n const candidate = resp.response?.candidates?.[0];\n const rawText =\n candidate?.content?.parts\n ?.filter((p) => typeof p.text === \"string\")\n .map((p) => p.text)\n .join(\"\") || \"\";\n const metadata = candidate?.groundingMetadata;\n\n return formatSearchResults(rawText, metadata, effectiveQuery, createdAt, completedAt);\n}\n", "import type { ExtensionCommandContext } from \"@earendil-works/pi-coding-agent\";\nimport { resolveCredentials, NOT_LOGGED_IN, type AntigravityCredentials } from \"./auth.ts\";\nimport { PROVIDER_ID } from \"./protocol.ts\";\nimport { openSettings } from \"./config.ts\";\nimport { type QuotaStatusCoordinator, registerQuotaSettings } from \"./quota-status.ts\";\nimport type { ModelCatalog } from \"./model-catalog.ts\";\nimport { performWebSearch } from \"./search.ts\";\n\nexport function emitOutput(\n ctx: ExtensionCommandContext,\n text: string,\n type: \"info\" | \"warning\" | \"error\" = \"info\",\n): void {\n if (ctx.hasUI) {\n ctx.ui.notify(text, type);\n } else {\n if (type === \"error\" || type === \"warning\") console.error(text);\n else console.log(text);\n }\n}\n\nexport interface SubcommandContext {\n ctx: ExtensionCommandContext;\n quotaStatus?: QuotaStatusCoordinator;\n catalog: ModelCatalog;\n subArgs?: string;\n}\n\nexport interface SubcommandDef {\n name: string;\n description: string;\n aliases?: readonly string[];\n run: (deps: SubcommandContext) => Promise<void> | void;\n}\n\nexport interface SubcommandCompletion {\n value: string;\n label: string;\n description: string;\n}\n\nexport const SUBCOMMANDS: readonly SubcommandDef[] = Object.freeze([\n {\n name: \"usage\",\n description: \"Show remaining 5h and weekly quota\",\n run: async ({ ctx, quotaStatus }) => runUsageSubcommand(ctx, quotaStatus),\n },\n {\n name: \"models\",\n description: \"List recommended models with context window and remaining quota\",\n aliases: Object.freeze([\"model\"]),\n run: async ({ ctx, catalog }) => runModelsSubcommand(ctx, catalog),\n },\n {\n name: \"refresh\",\n description: \"Fetch the latest model list\",\n run: async ({ ctx, catalog }) => runRefreshSubcommand(ctx, catalog),\n },\n {\n name: \"settings\",\n description: \"Configure provider settings\",\n aliases: Object.freeze([\"setting\"]),\n run: async ({ ctx, quotaStatus }) => {\n if (quotaStatus) registerQuotaSettings(quotaStatus);\n await openSettings(ctx);\n },\n },\n {\n name: \"websearch\",\n description: \"Search the web using Google Search Grounding\",\n run: async ({ ctx, subArgs }) => runSearchSubcommand(ctx, subArgs),\n },\n {\n name: \"login\",\n description: \"Run /login antigravity\",\n run: ({ ctx }) => runLoginSubcommand(ctx),\n },\n]);\n\nexport function buildUsageText(commands: readonly SubcommandDef[] = SUBCOMMANDS): string {\n const maxNameLen = Math.max(...commands.map((c) => c.name.length));\n const lines = commands.map((c) => {\n const aliasPart = c.aliases?.length ? ` (alias: ${c.aliases.join(\", \")})` : \"\";\n return ` ${c.name.padEnd(maxNameLen)} ${c.description}${aliasPart}`;\n });\n return `Usage: /antigravity <command>\\n\\nCommands:\\n${lines.join(\"\\n\")}`;\n}\n\nexport const USAGE_TEXT = buildUsageText();\n\nexport function completeSubcommands(\n prefix: string,\n commands: readonly SubcommandDef[] = SUBCOMMANDS,\n): SubcommandCompletion[] | null {\n const trimmed = prefix.trim();\n if (trimmed === \"\") {\n return commands.map((s) => ({ value: s.name, label: s.name, description: s.description }));\n }\n if (/\\s/.test(trimmed)) return null;\n const lower = trimmed.toLowerCase();\n return commands\n .filter((s) => s.name.startsWith(lower))\n .map((s) => ({\n value: s.name,\n label: s.name,\n description: s.description,\n }));\n}\n\nexport function parseAntigravitySubcommand(\n args: string,\n commands: readonly SubcommandDef[] = SUBCOMMANDS,\n): string {\n const sub = (args || \"\").trim().toLowerCase();\n for (const cmd of commands) {\n if (cmd.name === sub || cmd.aliases?.includes(sub)) {\n return cmd.name;\n }\n }\n return sub;\n}\n\nexport async function resolveToken(\n ctx: ExtensionCommandContext\n): Promise<AntigravityCredentials | null> {\n return resolveCredentials(ctx);\n}\n\nasync function runModelsSubcommand(ctx: ExtensionCommandContext, catalog: ModelCatalog): Promise<void> {\n if ((await resolveCredentials(ctx)) === null) {\n emitOutput(ctx, NOT_LOGGED_IN, \"warning\");\n return;\n }\n try {\n if (ctx.hasUI) ctx.ui.notify(\"Fetching available models\u2026\", \"info\");\n // Single Model Catalog path: freshness lives behind the catalog seam \u2014\n // this module only branches on the verdict and prints.\n const { status, catalog: items } = await catalog.refreshGeneration(() =>\n ctx.modelRegistry?.refresh?.({ force: true, providers: [PROVIDER_ID], signal: ctx.signal }),\n );\n if (status === \"failed\" || !items) {\n throw new Error(\"no models were returned\");\n }\n if (status === \"stale\") {\n // Refresh failed: say so, but still show the retained generation \u2014\n // a stale list beats no list, as long as it is labeled.\n emitOutput(ctx, \"Failed to refresh models; showing last known list.\", \"warning\");\n emitOutput(ctx, catalog.formatList());\n return;\n }\n emitOutput(ctx, catalog.formatList());\n } catch (err: any) {\n emitOutput(ctx, `Failed to fetch models: ${err.message}`, \"error\");\n }\n}\n\nasync function runUsageSubcommand(\n ctx: ExtensionCommandContext,\n quotaStatus?: QuotaStatusCoordinator,\n): Promise<void> {\n if ((await resolveCredentials(ctx)) === null) {\n emitOutput(ctx, NOT_LOGGED_IN, \"warning\");\n return;\n }\n if (!quotaStatus) {\n emitOutput(ctx, \"Quota status is unavailable.\", \"error\");\n return;\n }\n try {\n if (ctx.hasUI) ctx.ui.notify(\"Fetching quota summary\u2026\", \"info\");\n const text = await quotaStatus.inspectUsage(ctx);\n emitOutput(ctx, text);\n } catch (err: any) {\n emitOutput(ctx, `Failed to fetch usage: ${err.message}`, \"error\");\n }\n}\n\nasync function runRefreshSubcommand(ctx: ExtensionCommandContext, catalog: ModelCatalog): Promise<void> {\n try {\n if (ctx.hasUI) ctx.ui.notify(\"Refreshing models\u2026\", \"info\");\n const { status } = await catalog.refreshGeneration(() =>\n ctx.modelRegistry?.refresh?.({ force: true, providers: [PROVIDER_ID], signal: ctx.signal }),\n );\n if (status === \"fresh\") {\n emitOutput(ctx, \"Antigravity models refreshed successfully.\");\n } else if (status === \"stale\") {\n emitOutput(ctx, \"Failed to refresh models; keeping last known list.\", \"warning\");\n } else {\n emitOutput(ctx, \"Failed to refresh models: no models were returned.\", \"error\");\n }\n } catch (err: any) {\n emitOutput(ctx, `Failed to refresh: ${err.message}`, \"error\");\n }\n}\n\nfunction runLoginSubcommand(ctx: ExtensionCommandContext): void {\n if (ctx.hasUI) {\n ctx.ui.setEditorText(\"/login antigravity\");\n ctx.ui.notify(\"Press Enter to log in to Antigravity.\", \"info\");\n } else {\n emitOutput(ctx, \"Please run /login antigravity to authenticate.\");\n }\n}\n\nasync function runSearchSubcommand(\n ctx: ExtensionCommandContext,\n query?: string,\n): Promise<void> {\n const creds = await resolveCredentials(ctx);\n if (!creds) {\n emitOutput(ctx, NOT_LOGGED_IN, \"warning\");\n return;\n }\n\n const trimmedQuery = (query || \"\").trim();\n if (!trimmedQuery) {\n emitOutput(ctx, \"Usage: /antigravity websearch <query>\", \"warning\");\n return;\n }\n\n try {\n if (ctx.hasUI) ctx.ui.notify(`Searching: \"${trimmedQuery}\"\u2026`, \"info\");\n const result = await performWebSearch(creds, {\n query: trimmedQuery,\n signal: ctx.signal,\n });\n emitOutput(ctx, result.formattedOutput);\n } catch (err: any) {\n emitOutput(ctx, `Search failed: ${err.message}`, \"error\");\n }\n}\n\nexport async function runAntigravitySubcommand(\n args: string,\n ctx: ExtensionCommandContext,\n quotaStatus: QuotaStatusCoordinator | undefined,\n catalog: ModelCatalog,\n): Promise<void> {\n const raw = (args || \"\").trim();\n const parts = raw.split(/\\s+/).filter(Boolean);\n const sub = parseAntigravitySubcommand(parts[0] || \"\");\n const subArgs = raw.slice(parts[0]?.length || 0).trim();\n const cmd = SUBCOMMANDS.find((c) => c.name === sub);\n if (cmd) {\n await cmd.run({ ctx, quotaStatus, catalog, subArgs });\n return;\n }\n\n emitOutput(ctx, USAGE_TEXT);\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { ExtensionAPI, ExtensionCommandContext } from \"@earendil-works/pi-coding-agent\";\nimport { Type } from \"@earendil-works/pi-ai\";\nimport { loginAntigravity, refreshAntigravityToken, getApiKey, resolveCredentials } from \"./auth.ts\";\nimport { DEFAULT_ENDPOINT, PROVIDER_ID } from \"./protocol.ts\";\nimport { createModelCatalog } from \"./model-catalog.ts\";\nimport { QuotaStatusCoordinator, registerQuotaSettings } from \"./quota-status.ts\";\nimport { streamAntigravity } from \"./stream.ts\";\nimport { completeSubcommands, runAntigravitySubcommand } from \"./commands.ts\";\nimport { performWebSearch } from \"./search.ts\";\n\nexport { PROVIDER_ID };\nexport const PROVIDER_NAME = \"Antigravity\";\n\nexport default function (pi: ExtensionAPI): void {\n const quotaStatus = new QuotaStatusCoordinator();\n registerQuotaSettings(quotaStatus);\n // The one deep Model Catalog seam for this extension: handles Pi refreshModels,\n // Model Plan resolution for streaming, and CLI formatting for subcommands.\n const catalog = createModelCatalog();\n\n pi.registerProvider(PROVIDER_ID, {\n name: PROVIDER_NAME,\n baseUrl: DEFAULT_ENDPOINT,\n api: \"antigravity-api\",\n models: [], // Purely dynamic provider per Pi SDK architecture\n oauth: {\n name: PROVIDER_NAME,\n login: loginAntigravity,\n refreshToken: refreshAntigravityToken,\n getApiKey,\n },\n streamSimple: (model, context, options) => streamAntigravity(model, context, options, catalog),\n refreshModels: async (context) => catalog.refresh(context),\n });\n\n pi.registerCommand(\"antigravity\", {\n description: \"Antigravity quota, models and settings\",\n getArgumentCompletions: (prefix) => completeSubcommands(prefix),\n handler: async (args: string, ctx: ExtensionCommandContext) => {\n await runAntigravitySubcommand(args, ctx, quotaStatus, catalog);\n },\n });\n\n if (typeof pi.registerTool === \"function\") {\n pi.registerTool({\n name: \"antigravity_websearch\",\n label: \"Antigravity Web Search\",\n description:\n \"Performs a web search for a given query. Returns a summary of relevant information along with URL citations.\",\n promptSnippet: \"Search the web using Google Search Grounding with source citations\",\n promptGuidelines: [\n \"Use antigravity_websearch when you need real-time web search, latest documentation, or up-to-date facts with verified citations.\",\n ],\n parameters: Type.Object({\n query: Type.String({ description: \"The search query string to look up on the web.\" }),\n domain: Type.Optional(\n Type.String({\n description: \"Optional domain to recommend the search prioritize (e.g. 'github.com', 'developer.mozilla.org').\",\n }),\n ),\n }),\n async execute(_toolCallId, params, signal, _onUpdate, ctx) {\n const creds = await resolveCredentials(ctx);\n if (!creds) {\n return {\n content: [{ type: \"text\", text: \"Error: Not logged in. Run /login antigravity first.\" }],\n details: { error: \"not_logged_in\" },\n };\n }\n try {\n const result = await performWebSearch(creds, {\n query: params.query,\n domain: params.domain,\n signal,\n });\n return {\n content: [{ type: \"text\", text: result.formattedOutput }],\n details: {\n sources: result.sources,\n queries: result.queries,\n },\n };\n } catch (err: any) {\n return {\n content: [{ type: \"text\", text: `Search failed: ${err.message}` }],\n details: { error: err.message },\n };\n }\n },\n });\n }\n\n // Footer quota slot: paint cached text instantly, refresh in background.\n pi.on(\"session_start\", async (_event, ctx) => {\n await quotaStatus.refreshAndPaint(ctx);\n });\n\n // Model switch changes which Quota Pool backs the footer \u2014 repaint instantly,\n // then fill in fresh text when switching (back) to an Antigravity model.\n pi.on(\"model_select\", async (event, ctx) => {\n const modelCtx = {\n ui: ctx.ui,\n modelRegistry: ctx.modelRegistry,\n model: event.model || ctx.model,\n };\n await quotaStatus.refreshAndPaint(modelCtx);\n });\n\n // Turn settled: refresh only when the throttle window expired.\n pi.on(\"agent_settled\", async (_event, ctx) => {\n await quotaStatus.refreshAndPaint(ctx);\n });\n}\n", "import { createHash, randomBytes } from \"node:crypto\";\nimport type { OAuthCredentials, OAuthLoginCallbacks } from \"@earendil-works/pi-ai\";\nimport { postAntigravityJson, PROVIDER_ID } from \"./protocol.ts\";\n\nexport interface AntigravityCredentials {\n token: string;\n projectId: string;\n}\n\nexport type CredentialSource =\n | { modelRegistry?: { getApiKeyForProvider?: (provider: string) => Promise<string | undefined> } }\n | { apiKey?: string }\n | { credential?: { access?: string; type?: string } }\n | string\n | null\n | undefined;\n\nexport const REDIRECT_URI = \"https://antigravity.google/oauth-callback\";\nexport const AUTH_URL = \"https://accounts.google.com/o/oauth2/auth\";\nexport const TOKEN_URL = \"https://oauth2.googleapis.com/token\";\nexport const OAUTH_CALLBACK_TIMEOUT_MS = 5 * 60 * 1000;\nexport const FALLBACK_PROJECT_ID = \"aicode-consumers\";\n\nexport const SCOPES = [\n \"https://www.googleapis.com/auth/cloud-platform\",\n \"https://www.googleapis.com/auth/userinfo.email\",\n \"https://www.googleapis.com/auth/userinfo.profile\",\n \"https://www.googleapis.com/auth/cclog\",\n \"https://www.googleapis.com/auth/experimentsandconfigs\",\n \"https://www.googleapis.com/auth/aicode\",\n \"openid\",\n];\n\nexport const CLIENT_ID =\n process.env.ANTIGRAVITY_CLIENT_ID ||\n Buffer.from(\n \"MTA3MTAwNjA2MDU5MS10bWhzc2luMmgyMWxjcmUyMzV2dG9sb2poNGc0MDNlcC5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbQ==\",\n \"base64\"\n ).toString(\"utf-8\");\n\nexport const CLIENT_SECRET =\n process.env.ANTIGRAVITY_CLIENT_SECRET ||\n Buffer.from(\"R09DU1BYLUs1OEZXUjQ4NkxkTEoxbUxCOHNYQzR6NnFEQWY=\", \"base64\").toString(\"utf-8\");\n\nfunction base64Url(buf: Buffer): string {\n return buf.toString(\"base64url\");\n}\n\nexport function extractCodeFromInput(rawInput: string): string {\n let code = rawInput.trim();\n if (!code) {\n throw new Error(\"No authorization code provided\");\n }\n\n if (code.startsWith(\"code=\")) {\n code = code.slice(5).trim();\n if (!code) {\n throw new Error(\"No authorization code provided\");\n }\n }\n\n // Reject callback URLs and other non-code input here instead of passing\n // garbage downstream (Google rejects those with a bare invalid_grant).\n // Note: real codes contain \"/\" (e.g. \"4/0ATs\u2026\"), so only reject\n // characters a code can never contain.\n if (/[\\s:?#&=%+]/.test(code)) {\n throw new Error(\"Invalid authorization code: paste the code value itself, not the callback URL\");\n }\n\n return code;\n}\n\nfunction generatePKCE(): { verifier: string; challenge: string } {\n const verifier = base64Url(randomBytes(32));\n const challenge = base64Url(createHash(\"sha256\").update(verifier).digest());\n return { verifier, challenge };\n}\n\nexport async function fetchProjectId(token: string, signal?: AbortSignal): Promise<string> {\n try {\n const data = await postAntigravityJson<{ cloudaicompanionProject?: string }>({\n auth: token,\n path: \"v1internal:loadCodeAssist\",\n body: { metadata: { ideType: \"ANTIGRAVITY\" } },\n signal,\n });\n if (data.cloudaicompanionProject) {\n return data.cloudaicompanionProject;\n }\n } catch {\n // Fall back to standard project\n }\n return FALLBACK_PROJECT_ID;\n}\n\nexport async function loginAntigravity(callbacks: OAuthLoginCallbacks): Promise<OAuthCredentials> {\n const { verifier, challenge } = generatePKCE();\n // state is sent for OAuth wire parity, but never validated back:\n // with code-only paste the callback URL (and its state) never reaches us.\n const state = randomBytes(16).toString(\"hex\");\n\n const authParams = new URLSearchParams({\n client_id: CLIENT_ID,\n response_type: \"code\",\n redirect_uri: REDIRECT_URI,\n scope: SCOPES.join(\" \"),\n code_challenge: challenge,\n code_challenge_method: \"S256\",\n state,\n access_type: \"offline\",\n prompt: \"consent\",\n });\n\n const authUrl = `${AUTH_URL}?${authParams.toString()}`;\n callbacks.onAuth({ url: authUrl });\n\n const manualPromptPromise = (async () => {\n const input = await callbacks.onPrompt({\n message: \"Paste authorization code from browser:\",\n });\n return extractCodeFromInput(input);\n })();\n\n const timeout = new Promise<never>((_, rej) =>\n setTimeout(() => rej(new Error(\"Timed out waiting for authorization code (5 minutes)\")), OAUTH_CALLBACK_TIMEOUT_MS)\n );\n\n const code = await Promise.race([manualPromptPromise, timeout]);\n\n const tokenParams = new URLSearchParams({\n client_id: CLIENT_ID,\n client_secret: CLIENT_SECRET,\n code,\n grant_type: \"authorization_code\",\n redirect_uri: REDIRECT_URI,\n code_verifier: verifier,\n });\n\n const tokenRes = await fetch(TOKEN_URL, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: tokenParams.toString(),\n });\n\n if (!tokenRes.ok) {\n const errText = await tokenRes.text();\n throw new Error(`Failed to exchange token (${tokenRes.status}): ${errText}`);\n }\n\n const tokens = (await tokenRes.json()) as {\n access_token: string;\n refresh_token?: string;\n expires_in?: number;\n };\n const projectId = await fetchProjectId(tokens.access_token);\n\n return {\n refresh: tokens.refresh_token || \"\",\n access: JSON.stringify({ token: tokens.access_token, projectId }),\n expires: Date.now() + (tokens.expires_in || 3600) * 1000,\n };\n}\n\nexport async function refreshAntigravityToken(\n credentials: OAuthCredentials,\n signal?: AbortSignal\n): Promise<OAuthCredentials> {\n const params = new URLSearchParams({\n client_id: CLIENT_ID,\n client_secret: CLIENT_SECRET,\n refresh_token: credentials.refresh,\n grant_type: \"refresh_token\",\n });\n\n const res = await fetch(TOKEN_URL, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: params.toString(),\n signal,\n });\n\n if (!res.ok) {\n const errText = await res.text();\n throw new Error(`Failed to refresh token (${res.status}): ${errText}`);\n }\n\n const tokens = (await res.json()) as {\n access_token: string;\n refresh_token?: string;\n expires_in?: number;\n };\n\n let existingProjectId = FALLBACK_PROJECT_ID;\n try {\n const parsed = JSON.parse(credentials.access);\n if (parsed.projectId) existingProjectId = parsed.projectId;\n } catch {\n // ignore\n }\n\n // Re-resolve: a login-time lookup failure pins the \"aicode-consumers\"\n // default forever unless refresh retries it. A failed lookup yields that\n // same default, which must never clobber a known value.\n const freshProjectId = await fetchProjectId(tokens.access_token, signal);\n const projectId = freshProjectId !== FALLBACK_PROJECT_ID ? freshProjectId : existingProjectId;\n\n return {\n refresh: tokens.refresh_token || credentials.refresh,\n access: JSON.stringify({ token: tokens.access_token, projectId }),\n expires: Date.now() + (tokens.expires_in || 3600) * 1000,\n };\n}\n\nexport function getApiKey(credentials: OAuthCredentials): string {\n return credentials.access;\n}\n\n/**\n * Deep credential resolution seam: extracts and normalizes Antigravity credentials\n * ({ token, projectId }) from any Pi context (command context, model registry,\n * stream options, refresh context, or raw API key strings).\n * Returns null when credentials are not found.\n */\nexport async function resolveCredentials(\n source: CredentialSource\n): Promise<AntigravityCredentials | null> {\n if (!source) return null;\n\n let raw: string | undefined;\n\n if (typeof source === \"string\") {\n raw = source.trim();\n } else if (typeof source === \"object\") {\n if (\"modelRegistry\" in source && source.modelRegistry?.getApiKeyForProvider) {\n raw = await source.modelRegistry.getApiKeyForProvider(PROVIDER_ID);\n } else if (\"apiKey\" in source && typeof source.apiKey === \"string\") {\n raw = source.apiKey;\n } else if (\"credential\" in source && source.credential) {\n raw = source.credential.type === \"oauth\" || !source.credential.type\n ? source.credential.access\n : undefined;\n }\n }\n\n if (!raw || typeof raw !== \"string\" || !raw.trim()) {\n return null;\n }\n\n const parsed = parseStoredCredentials(raw);\n if (!parsed.token || !parsed.token.trim()) {\n return null;\n }\n return parsed;\n}\n\n/**\n * One wording for the one state: the request path (\"I am not signed in\") and the\n * subcommands say the same thing, so a user learns it once.\n */\nexport const NOT_LOGGED_IN = \"Not logged in. Run /login antigravity first.\";\n\n/**\n * Ensures credentials exist or throws a clear error message.\n */\nexport async function requireCredentials(\n source: CredentialSource,\n errorMessage = NOT_LOGGED_IN\n): Promise<AntigravityCredentials> {\n const creds = await resolveCredentials(source);\n if (!creds) {\n throw new Error(errorMessage);\n }\n return creds;\n}\n\nexport function parseStoredCredentials(rawApiKey: string): AntigravityCredentials {\n try {\n const parsed = JSON.parse(rawApiKey);\n if (parsed.token) {\n return { token: parsed.token, projectId: parsed.projectId || FALLBACK_PROJECT_ID };\n }\n } catch {\n // If plain token\n }\n return { token: rawApiKey, projectId: FALLBACK_PROJECT_ID };\n}\n", "export const DEFAULT_ENDPOINT = \"https://daily-cloudcode-pa.googleapis.com\";\nexport const DEFAULT_USER_AGENT =\n \"antigravity/cli/1.2.5 (aidev_client; os_type=linux; arch=amd64; cl=982839923; auth_method=consumer)\";\n\nexport const PROVIDER_ID = \"antigravity\";\n\n/**\n * Structured error thrown when an Antigravity HTTP endpoint responds with a non-2xx status code.\n * Preserves status, endpoint path, and raw error body for error inspection without string parsing.\n */\nexport class AntigravityHttpError extends Error {\n readonly status: number;\n readonly path: string;\n readonly errorBody: string;\n\n constructor(status: number, path: string, errorBody: string) {\n super(`Antigravity request to ${path} failed (${status}): ${errorBody}`);\n this.name = \"AntigravityHttpError\";\n this.status = status;\n this.path = path;\n this.errorBody = errorBody;\n }\n}\n\nexport interface AntigravityPostParams {\n auth: string | { token: string };\n /** Path below the endpoint, e.g. \"v1internal:retrieveUserQuotaSummary\". */\n path: string;\n body: unknown;\n signal?: AbortSignal;\n}\n\nfunction resolveToken(auth: string | { token: string }): string {\n if (typeof auth === \"string\") return auth;\n if (auth && typeof auth.token === \"string\") return auth.token;\n throw new Error(\"Invalid auth parameter: missing token string\");\n}\n\nasync function postAntigravityRaw({\n auth,\n path,\n body,\n signal,\n}: AntigravityPostParams): Promise<Response> {\n const token = resolveToken(auth);\n return fetch(`${DEFAULT_ENDPOINT}/${path}`, {\n method: \"POST\",\n headers: buildAntigravityHeaders(token),\n body: JSON.stringify(body),\n signal,\n });\n}\n\n/**\n * Deep protocol JSON client: validates HTTP status, decodes JSON payloads,\n * and throws structured AntigravityHttpError on failures.\n */\nexport async function postAntigravityJson<T>(params: AntigravityPostParams): Promise<T> {\n const res = await postAntigravityRaw(params);\n if (!res.ok) {\n const errText = await res.text();\n throw new AntigravityHttpError(res.status, params.path, errText);\n }\n return (await res.json()) as T;\n}\n\n/**\n * Deep protocol stream client: validates HTTP status, checks stream presence,\n * and returns the validated ReadableStream.\n */\nexport async function postAntigravityStream(\n params: AntigravityPostParams\n): Promise<ReadableStream<Uint8Array>> {\n const res = await postAntigravityRaw(params);\n if (!res.ok) {\n const errText = await res.text();\n throw new AntigravityHttpError(res.status, params.path, errText);\n }\n if (!res.body) {\n throw new Error(`No response stream received from Antigravity for ${params.path}.`);\n }\n return res.body;\n}\n\n/**\n * Builds the canonical HTTP request headers for the Antigravity Wire Fingerprint.\n */\nexport function buildAntigravityHeaders(token: string, userAgent = DEFAULT_USER_AGENT): Record<string, string> {\n return {\n Host: \"daily-cloudcode-pa.googleapis.com\",\n \"User-Agent\": userAgent,\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${token}`,\n };\n}\n\n", "/**\n * Pure domain module encapsulating Model Family classification across\n * Turn Trace request construction, Quota Pool grouping, and Model Catalog resolution.\n */\n\nexport type ModelFamily = \"gemini\" | \"claude\" | \"gpt\" | \"unknown\";\n\n/**\n * The single model-identity predicate: which\n * family a model ID belongs to. Accepts any ID space \u2014 Public or Runtime\n * Model ID, with or without a `provider/` prefix \u2014 by stripping the prefix\n * before the prefix match, so every caller classifies identically. Unknown\n * (including missing) IDs report \"unknown\"; mapping that onto a Quota Pool\n * or plan flags stays with the consumer, preserving each caller's default.\n */\nexport function classifyModelFamily(modelId?: string): ModelFamily {\n const bare = ((modelId || \"\").split(\"/\").pop() || \"\").toLowerCase();\n if (bare.startsWith(\"gemini-\")) return \"gemini\";\n if (bare.startsWith(\"claude-\")) return \"claude\";\n if (bare.startsWith(\"gpt-\")) return \"gpt\";\n return \"unknown\";\n}\n\n/**\n * Checks Model Family compatibility for thoughtSignature replay.\n * Protocol specifications demonstrate that:\n * - Gemini models (gemini-3.7, gemini-3.8, etc.) share thoughtSignatures seamlessly.\n * - Claude models replay thoughtSignatures within the Claude family, part-split like Gemini.\n * - Non-Gemini models (Claude, GPT-OSS) do NOT share signatures with Gemini models.\n */\nexport function isCompatibleFamily(msgModel?: string, targetModelId?: string): boolean {\n if (!msgModel || !targetModelId) return true;\n if (msgModel === targetModelId) return true;\n\n const msgFamily = classifyModelFamily(msgModel);\n if (msgFamily !== \"unknown\" && msgFamily === classifyModelFamily(targetModelId)) return true;\n\n return false;\n}\n", "import type { Model, RefreshModelsContext } from \"@earendil-works/pi-ai\";\nimport { resolveCredentials, type AntigravityCredentials } from \"./auth.ts\";\nimport { DEFAULT_ENDPOINT, postAntigravityJson, PROVIDER_ID } from \"./protocol.ts\";\nimport { classifyModelFamily } from \"./model-identity.ts\";\n\nexport const PRIVATE_SNAPSHOT_KEY = \"pi-provider-antigravity\";\n\ntype CanonicalTier = \"low\" | \"medium\" | \"high\";\n\n/**\n * Canonical Tier Suffix: The wire suffix that mirrors the user-requested thinking\n * effort by name (-low, -medium, -high), attempted first when resolving a Runtime Model ID.\n */\nconst CANONICAL_TIER_SUFFIXES: Record<CanonicalTier, string> = Object.freeze({\n low: \"-low\",\n medium: \"-medium\",\n high: \"-high\",\n});\n\n/**\n * Tier Alias: Alternative wire spellings representing the same thinking effort tier\n * (-thinking or -agent for high, -extra-low for low, or an unsuffixed base identifier\n * for the default tier), resolved when the canonical suffix is absent.\n */\nconst TIER_ALIASES: Record<CanonicalTier, readonly string[]> = Object.freeze({\n low: Object.freeze([\"-extra-low\"]),\n medium: Object.freeze([]),\n high: Object.freeze([\"-thinking\", \"-agent\"]),\n});\n\n/**\n * Special suffixes in the catalog that designate non-effort variant types (e.g. server-directed\n * dynamic thinking selection). Stripped for base model grouping and recognized as runtime IDs,\n * but not selectable as a user thinking effort tier.\n */\nconst SPECIAL_TIER_SUFFIXES: readonly string[] = Object.freeze([\"-tiered\"]);\n\n/**\n * Union of all known model ID tier suffixes (canonical, aliases, and special tokens).\n */\nconst ALL_TIER_SUFFIXES: readonly string[] = Object.freeze([\n ...new Set([\n ...Object.values(CANONICAL_TIER_SUFFIXES),\n ...Object.values(TIER_ALIASES).flat(),\n ...SPECIAL_TIER_SUFFIXES,\n ]),\n]);\n\n/**\n * Strips any known tier suffix from a model ID for grouping.\n */\nconst TIER_SUFFIX_PATTERN = new RegExp(\n `-(?:${ALL_TIER_SUFFIXES.map((s) => s.replace(/^-/, \"\")).join(\"|\")})$`,\n);\n\nfunction tierSpellings(tier: CanonicalTier): readonly string[] {\n return [CANONICAL_TIER_SUFFIXES[tier], ...TIER_ALIASES[tier]];\n}\n\nfunction extractBaseModelId(runtimeId: string): string {\n if (runtimeId === \"gemini-pro-agent\") return \"gemini-3.1-pro\";\n if (runtimeId.startsWith(\"gemini-3.1-pro-\")) return \"gemini-3.1-pro\";\n\n return runtimeId.replace(TIER_SUFFIX_PATTERN, \"\");\n}\n\n/**\n * Ordered candidate suffixes attempted when resolving a Runtime Model ID for an effort.\n * Canonical suffix comes first, followed by fallbacks.\n */\nconst TIER_FALLBACKS: Record<string, readonly string[]> = Object.freeze({\n minimal: Object.freeze([\"-low\", \"-extra-low\", \"\"]),\n low: Object.freeze([\"-extra-low\", \"\"]),\n medium: Object.freeze([\"\", \"-high\"]), // Gemini 3.1 Pro lists no -medium: up to high, never down\n high: Object.freeze([\"-thinking\", \"-agent\", \"\"]), // Claude's high tier is -thinking\n xhigh: Object.freeze([\"-high\", \"-thinking\", \"-agent\", \"\"]),\n max: Object.freeze([\"-high\", \"-thinking\", \"-agent\", \"\"]),\n});\n\nconst DEFAULT_TIER_ORDER: readonly string[] = Object.freeze([\n CANONICAL_TIER_SUFFIXES.high,\n ...TIER_ALIASES.high,\n \"\",\n]);\n\nfunction tierCandidateOrder(effort?: string): readonly string[] {\n if (!effort) return DEFAULT_TIER_ORDER;\n const canonical = effort in CANONICAL_TIER_SUFFIXES\n ? [CANONICAL_TIER_SUFFIXES[effort as CanonicalTier]]\n : [`-${effort}`];\n const fallbacks = TIER_FALLBACKS[effort] ?? DEFAULT_TIER_ORDER;\n return [...new Set([...canonical, ...fallbacks])];\n}\n\ntype StoreEntry = NonNullable<RefreshModelsContext[\"stored\"]>;\n\n/**\n * Context passed to refreshModels by Pi Core, minus internal fields the\n * extension does not touch.\n */\nexport type RefreshContext = Omit<RefreshModelsContext, \"stored\" | \"publish\"> & {\n stored?: Readonly<StoreEntry> & { [PRIVATE_SNAPSHOT_KEY]?: PersistedSnapshot };\n publish?(publication: {\n persist?: (StoreEntry & { [PRIVATE_SNAPSHOT_KEY]?: PersistedSnapshot }) | null;\n update?: () => void;\n }): Promise<boolean>;\n};\n\nexport interface CatalogRefreshOutcome {\n status: \"fresh\" | \"stale\" | \"failed\";\n catalog?: AvailableModelsCatalog;\n}\n\nexport interface AvailableModelItem {\n id: string;\n displayName?: string;\n modelEnum?: string;\n remainingFraction?: number;\n resetTime?: string;\n supportsThinking?: boolean;\n thinkingBudget?: number;\n minThinkingBudget?: number;\n supportsImages?: boolean;\n maxTokens?: number;\n maxOutputTokens?: number;\n}\n\nexport interface AvailableModelsCatalog {\n models: AvailableModelItem[];\n modelEnums: Record<string, string>;\n agentModelSorts?: string[];\n /** Server-directed renames: old Runtime Model ID \u2192 current Runtime Model ID. */\n deprecated?: Record<string, string>;\n}\n\nexport interface CatalogThinking {\n budget?: number;\n supportsThinking: boolean;\n}\n\nexport interface CatalogSnapshot {\n enums: Record<string, string>;\n runtimeIds: string[];\n thinking: Record<string, CatalogThinking>;\n deprecated: Record<string, string>;\n}\n\nexport interface CatalogGeneration {\n snapshot: CatalogSnapshot;\n /** Full item list of the recorded refresh; absent after an offline restore. */\n items?: AvailableModelsCatalog;\n /** Fetch successes recorded in this process; 0 until one is recorded. */\n version: number;\n}\n\n// Catalog Persistence codec: the private entry this provider keeps inside its\n// own Pi store entry (PRIVATE_SNAPSHOT_KEY). The key spells a snapshot's `enums`\n// as `modelEnums` and must keep doing so \u2014 Pi persists unknown keys verbatim.\nexport interface PersistedSnapshot {\n modelEnums: Record<string, string>;\n runtimeIds: string[];\n thinking: Record<string, CatalogThinking>;\n deprecated: Record<string, string>;\n}\n\nexport interface ModelPlan {\n runtimeModelId: string;\n modelEnum: string;\n thinkingConfig: { includeThoughts: boolean; thinkingBudget: number };\n isNonGemini: boolean;\n isClaude: boolean;\n}\n\n/**\n * The single deep Model Catalog interface. Encapsulates wire decoding, snapshot generations,\n * persistence codecs, network refresh, plan resolution, and CLI formatting behind one seam.\n */\nexport interface ModelCatalog {\n /**\n * Current generation. The snapshot is a copy the caller may keep; `items` is\n * shared, because readers only enumerate it and never mutate it.\n */\n generation(): CatalogGeneration;\n /**\n * Records one completed generation from parsed catalog or raw wire JSON payload:\n * automatically parses wire envelope, derives its snapshot, and bumps version.\n */\n record(catalogOrRaw: unknown): void;\n /**\n * Restores a persisted snapshot or raw store object into a pristine store.\n */\n restore(persistedOrSnapshot: unknown): void;\n /**\n * Encodes the current generation snapshot for Pi models-store.json persistence.\n */\n toPersisted(): PersistedSnapshot | undefined;\n /**\n * Pi SDK refreshModels entry point: restores stored snapshot, fetches wire\n * catalog when online, updates generation, and publishes to Pi store.\n */\n refresh(context: RefreshContext): Promise<Array<Model<any>>>;\n /**\n * Refreshes catalog via the provided hook and reports freshness verdict.\n */\n refreshGeneration(doRefresh: () => unknown): Promise<CatalogRefreshOutcome>;\n /**\n * Resolves one Model Plan for the requested model and effort against\n * the current snapshot generation.\n */\n resolvePlan(publicModelId: string, effort?: string): ModelPlan;\n /**\n * Formats the current catalog generation as a readable CLI table string.\n */\n formatList(): string;\n}\n\nexport type CatalogStore = ModelCatalog;\n\nexport function buildThinkingMap(models: AvailableModelItem[]): Record<string, CatalogThinking> {\n return Object.fromEntries(\n models.map((m) => [\n m.id,\n {\n ...(typeof m.thinkingBudget === \"number\" ? { budget: m.thinkingBudget } : {}),\n supportsThinking: m.supportsThinking ?? false,\n },\n ]),\n );\n}\n\nfunction snapshotFromCatalog(catalog: AvailableModelsCatalog): CatalogSnapshot {\n return {\n enums: { ...catalog.modelEnums },\n runtimeIds: [...new Set(catalog.models.map((m) => m.id))],\n thinking: buildThinkingMap(catalog.models),\n deprecated: { ...(catalog.deprecated ?? {}) },\n };\n}\n\nfunction copySnapshot(snapshot: CatalogSnapshot): CatalogSnapshot {\n return {\n enums: { ...snapshot.enums },\n runtimeIds: [...snapshot.runtimeIds],\n thinking: Object.fromEntries(\n Object.entries(snapshot.thinking).map(([id, info]) => [id, { ...info }]),\n ),\n deprecated: { ...snapshot.deprecated },\n };\n}\n\nconst EMPTY_SNAPSHOT = (): CatalogSnapshot => ({ enums: {}, runtimeIds: [], thinking: {}, deprecated: {} });\n\nexport function parseAvailableModels(data: any): AvailableModelsCatalog {\n if (!data || typeof data !== \"object\") {\n return { models: [], modelEnums: {} };\n }\n\n const models: AvailableModelItem[] = [];\n const modelEnums: Record<string, string> = {};\n\n const modelsObj = data.models || {};\n for (const [id, info] of Object.entries<any>(modelsObj)) {\n if (id.startsWith(\"tab_\") || id.startsWith(\"chat_\")) continue; // hide internal completions\n\n const modelEnum = typeof info.model === \"string\" ? info.model : undefined;\n if (modelEnum) {\n modelEnums[id] = modelEnum;\n }\n\n const quotaInfo = info.quotaInfo || {};\n models.push({\n id,\n displayName: info.displayName || info.label || id,\n modelEnum,\n remainingFraction: quotaInfo.remainingFraction,\n resetTime: quotaInfo.resetTime,\n supportsThinking: Boolean(info.supportsThinking),\n thinkingBudget: typeof info.thinkingBudget === \"number\" ? info.thinkingBudget : undefined,\n minThinkingBudget: typeof info.minThinkingBudget === \"number\" ? info.minThinkingBudget : undefined,\n supportsImages: Boolean(info.supportsImages),\n maxTokens: typeof info.maxTokens === \"number\" ? info.maxTokens : undefined,\n maxOutputTokens: typeof info.maxOutputTokens === \"number\" ? info.maxOutputTokens : undefined,\n });\n }\n\n const agentModelSorts: string[] = [];\n if (Array.isArray(data.agentModelSorts)) {\n for (const sortGroup of data.agentModelSorts) {\n if (Array.isArray(sortGroup.groups)) {\n for (const group of sortGroup.groups) {\n if (Array.isArray(group.modelIds)) {\n agentModelSorts.push(...group.modelIds);\n }\n }\n }\n }\n }\n\n models.sort((a, b) => a.id.localeCompare(b.id));\n\n // Server-directed renames (old Runtime Model ID \u2192 current one).\n const deprecated: Record<string, string> = {};\n const rawDeprecated = (data as any).deprecatedModelIds;\n if (rawDeprecated && typeof rawDeprecated === \"object\") {\n for (const [oldId, info] of Object.entries<any>(rawDeprecated)) {\n if (info && typeof info.newModelId === \"string\") {\n deprecated[oldId] = info.newModelId;\n }\n }\n }\n\n return {\n models,\n modelEnums,\n ...(agentModelSorts.length > 0 ? { agentModelSorts } : {}),\n ...(Object.keys(deprecated).length > 0 ? { deprecated } : {}),\n };\n}\n\nasync function fetchAvailableModelsCatalog(\n token: string | AntigravityCredentials,\n projectId: string,\n signal?: AbortSignal\n): Promise<AvailableModelsCatalog> {\n const json = await postAntigravityJson<any>({\n auth: token,\n path: \"v1internal:fetchAvailableModels\",\n body: { project: projectId },\n signal,\n });\n return parseAvailableModels(json);\n}\n\nfunction toPersistedSnapshot(snapshot: CatalogSnapshot): PersistedSnapshot {\n return {\n modelEnums: { ...snapshot.enums },\n runtimeIds: [...snapshot.runtimeIds],\n thinking: { ...snapshot.thinking },\n deprecated: { ...snapshot.deprecated },\n };\n}\n\nfunction isStringRecord(value: unknown): value is Record<string, string> {\n return (\n !!value &&\n typeof value === \"object\" &&\n !Array.isArray(value) &&\n Object.values(value).every((entry) => typeof entry === \"string\")\n );\n}\n\nfunction isThinkingRecord(value: unknown): value is Record<string, CatalogThinking> {\n return (\n !!value &&\n typeof value === \"object\" &&\n !Array.isArray(value) &&\n Object.values(value).every((entry) => !!entry && typeof entry === \"object\" && !Array.isArray(entry))\n );\n}\n\nfunction fromPersistedSnapshot(raw: unknown): CatalogSnapshot | undefined {\n if (!raw || typeof raw !== \"object\" || Array.isArray(raw)) return undefined;\n const entry = raw as Partial<PersistedSnapshot>;\n const enums = isStringRecord(entry.modelEnums) ? entry.modelEnums : undefined;\n const runtimeIds = Array.isArray(entry.runtimeIds)\n ? entry.runtimeIds.filter((id): id is string => typeof id === \"string\")\n : undefined;\n const thinking = isThinkingRecord(entry.thinking) ? entry.thinking : undefined;\n const deprecated = isStringRecord(entry.deprecated) ? entry.deprecated : undefined;\n if (!enums && !runtimeIds && !thinking && !deprecated) return undefined;\n return { enums: enums ?? {}, runtimeIds: runtimeIds ?? [], thinking: thinking ?? {}, deprecated: deprecated ?? {} };\n}\n\nfunction resolveRuntimeModelId(\n modelId: string,\n effort: string | undefined,\n availableRuntimeIds: string[]\n): string {\n if (ALL_TIER_SUFFIXES.some((suffix) => modelId.endsWith(suffix))) {\n return modelId;\n }\n\n if (availableRuntimeIds.length > 0) {\n const variants = new Set(availableRuntimeIds.filter((id) => extractBaseModelId(id) === modelId));\n const order = tierCandidateOrder(effort);\n\n for (const suffix of order) {\n if (variants.has(`${modelId}${suffix}`)) {\n return `${modelId}${suffix}`;\n }\n }\n\n if (variants.size === 1) {\n return [...variants][0];\n }\n }\n\n return modelId;\n}\n\nfunction followRenames(runtimeModelId: string, snapshot: CatalogSnapshot): string {\n const renamed = snapshot.deprecated;\n if (!renamed) return runtimeModelId;\n let current = runtimeModelId;\n const seen = new Set<string>([current]);\n while (renamed[current] && !seen.has(renamed[current])) {\n current = renamed[current];\n seen.add(current);\n }\n return current;\n}\n\nfunction resolveThinkingConfig(\n runtimeModelId: string,\n snapshot: CatalogSnapshot\n): { includeThoughts: boolean; thinkingBudget: number } {\n const budget = snapshot.thinking[runtimeModelId]?.budget;\n return typeof budget === \"number\"\n ? { includeThoughts: true, thinkingBudget: budget }\n : { includeThoughts: false, thinkingBudget: 0 };\n}\n\nexport function resolveModelPlan(\n publicModelId: string,\n effort: string | undefined,\n snapshot: CatalogSnapshot\n): ModelPlan {\n const runtimeModelId = followRenames(\n resolveRuntimeModelId(publicModelId, effort, snapshot.runtimeIds),\n snapshot\n );\n const modelEnum = snapshot.enums[runtimeModelId];\n if (!modelEnum) {\n throw new Error(\n `Unknown model \"${runtimeModelId}\". ` +\n `Run /antigravity refresh, then pick a current model.`\n );\n }\n const family = classifyModelFamily(runtimeModelId);\n return {\n runtimeModelId,\n modelEnum,\n thinkingConfig: resolveThinkingConfig(runtimeModelId, snapshot),\n isNonGemini: family !== \"gemini\",\n isClaude: family === \"claude\",\n };\n}\n\nfunction estimateModelCost(_baseId: string): Model<any>[\"cost\"] {\n return { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };\n}\n\nfunction formatModelDisplayName(baseId: string, rawDisplayName?: string): string {\n if (rawDisplayName) {\n const cleaned = rawDisplayName.replace(/\\s*\\([^)]*\\)/g, \"\").trim();\n if (cleaned.length > 0) {\n return cleaned;\n }\n }\n const words = baseId.split(\"-\").map((w) => {\n if (/^\\d+(\\.\\d+)?$/.test(w)) return w;\n return w.charAt(0).toUpperCase() + w.slice(1);\n });\n return words.join(\" \");\n}\n\nfunction synthesizeDynamicModel(baseId: string, items: AvailableModelItem[]): Model<any> {\n const repItem = items.find((it) => it.id === `${baseId}-high` || it.id === baseId) || items[0];\n\n const hasVariant = (suffixes: readonly string[]) =>\n items.some((it) => suffixes.some((suffix) => it.id.endsWith(suffix)));\n const thinkingLevelMap = {\n off: null,\n minimal: null,\n ...(hasVariant(tierSpellings(\"low\")) ? {} : { low: null }),\n ...(hasVariant(tierSpellings(\"medium\")) ? {} : { medium: null }),\n ...(hasVariant(tierSpellings(\"high\")) || items.some((it) => it.id === baseId)\n ? {}\n : { high: null }),\n };\n\n const family = classifyModelFamily(baseId);\n const isFlash = baseId.includes(\"flash\");\n const isClaude = family === \"claude\";\n const isGpt = family === \"gpt\";\n\n const defaultContext = isFlash ? 1048576 : isClaude ? 250000 : isGpt ? 128000 : 1048576;\n const defaultMaxOutput = isClaude ? 64000 : isGpt ? 32768 : 65536;\n\n return {\n id: baseId,\n name: formatModelDisplayName(baseId, repItem?.displayName),\n provider: PROVIDER_ID,\n api: \"antigravity-api\",\n baseUrl: DEFAULT_ENDPOINT,\n reasoning: repItem?.supportsThinking ?? true,\n thinkingLevelMap,\n input: repItem?.supportsImages ? [\"text\", \"image\"] : [\"text\"],\n cost: estimateModelCost(baseId),\n contextWindow: repItem?.maxTokens || defaultContext,\n maxTokens: repItem?.maxOutputTokens || defaultMaxOutput,\n };\n}\n\nfunction buildDynamicPublicModels(catalog?: AvailableModelsCatalog): Array<Model<any>> {\n if (!catalog || !Array.isArray(catalog.models) || catalog.models.length === 0) {\n return [];\n }\n\n const agentSortIds = catalog.agentModelSorts;\n const eligibleItems =\n Array.isArray(agentSortIds) && agentSortIds.length > 0\n ? catalog.models.filter((m) => agentSortIds.includes(m.id))\n : catalog.models;\n\n const runtimeGroups = new Map<string, AvailableModelItem[]>();\n for (const item of eligibleItems) {\n const baseId = extractBaseModelId(item.id);\n const list = runtimeGroups.get(baseId) || [];\n list.push(item);\n runtimeGroups.set(baseId, list);\n }\n\n const orderedBaseIds: string[] = [];\n if (Array.isArray(agentSortIds)) {\n for (const sortId of agentSortIds) {\n const baseId = extractBaseModelId(sortId);\n if (runtimeGroups.has(baseId) && !orderedBaseIds.includes(baseId)) {\n orderedBaseIds.push(baseId);\n }\n }\n }\n\n for (const baseId of runtimeGroups.keys()) {\n if (!orderedBaseIds.includes(baseId)) {\n orderedBaseIds.push(baseId);\n }\n }\n\n return orderedBaseIds.map((baseId) => synthesizeDynamicModel(baseId, runtimeGroups.get(baseId)!));\n}\n\nfunction formatTokenCount(n?: number): string {\n if (typeof n !== \"number\") return \"N/A\";\n if (n % 1048576 === 0) return `${n / 1048576}M`;\n if (n % 1024 === 0) return `${n / 1024}k`;\n if (n % 1000 === 0) return `${n / 1000}k`;\n return `${Math.round(n / 1024)}k`;\n}\n\nfunction formatModelsList(catalog: AvailableModelsCatalog): string {\n const sorts = catalog.agentModelSorts;\n const recommendedOnly = Array.isArray(sorts) && sorts.length > 0;\n const rank = new Map((sorts || []).map((id, i) => [id, i]));\n\n const models = (recommendedOnly ? catalog.models.filter((m) => rank.has(m.id)) : catalog.models.slice()).sort(\n (a, b) => (rank.get(a.id) ?? Number.MAX_SAFE_INTEGER) - (rank.get(b.id) ?? Number.MAX_SAFE_INTEGER) ||\n a.id.localeCompare(b.id)\n );\n\n const rows = models.map((m) => {\n const flags: string[] = [];\n if (m.supportsThinking) flags.push(\"thinking\");\n if (m.supportsImages) flags.push(\"images\");\n return {\n id: m.id,\n name: formatModelDisplayName(m.id, m.displayName || m.id),\n ctx: `${formatTokenCount(m.maxTokens)}/${formatTokenCount(m.maxOutputTokens)}`,\n feat: flags.length > 0 ? flags.join(\", \") : \"-\",\n rem: typeof m.remainingFraction === \"number\" ? `${Math.round(m.remainingFraction * 100)}%` : \"N/A\",\n };\n });\n\n const headers = { id: \"Model\", name: \"Name\", ctx: \"Context\", feat: \"Features\", rem: \"Rem\" };\n const w = {\n id: Math.max(headers.id.length, ...rows.map((r) => r.id.length)),\n name: Math.max(headers.name.length, ...rows.map((r) => r.name.length)),\n ctx: Math.max(headers.ctx.length, ...rows.map((r) => r.ctx.length)),\n feat: Math.max(headers.feat.length, ...rows.map((r) => r.feat.length)),\n };\n\n const lines: string[] = [\n `Available Antigravity Models (${models.length}${recommendedOnly ? \" recommended\" : \"\"}):`,\n ` ${headers.id.padEnd(w.id)} ${headers.name.padEnd(w.name)} ${headers.ctx.padEnd(w.ctx)} ${headers.feat.padEnd(w.feat)} ${headers.rem}`,\n ];\n for (const r of rows) {\n lines.push(\n ` ${r.id.padEnd(w.id)} ${r.name.padEnd(w.name)} ${r.ctx.padEnd(w.ctx)} ${r.feat.padEnd(w.feat)} ${r.rem.padStart(4)}`\n );\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Creates the authoritative deep Model Catalog interface.\n */\nexport function createModelCatalog(): ModelCatalog {\n let generation: CatalogGeneration = { snapshot: EMPTY_SNAPSHOT(), version: 0 };\n\n const record = (catalogOrRaw: unknown) => {\n let catalog: AvailableModelsCatalog;\n if (\n catalogOrRaw &&\n typeof catalogOrRaw === \"object\" &&\n \"models\" in catalogOrRaw &&\n Array.isArray((catalogOrRaw as any).models) &&\n \"modelEnums\" in catalogOrRaw &&\n typeof (catalogOrRaw as any).modelEnums === \"object\"\n ) {\n catalog = catalogOrRaw as AvailableModelsCatalog;\n } else {\n catalog = parseAvailableModels(catalogOrRaw);\n }\n generation = {\n snapshot: snapshotFromCatalog(catalog),\n items: catalog,\n version: generation.version + 1,\n };\n };\n\n const restore = (persistedOrSnapshot: unknown) => {\n if (generation.version > 0) return;\n if (!persistedOrSnapshot || typeof persistedOrSnapshot !== \"object\") return;\n\n if (\n \"enums\" in persistedOrSnapshot &&\n \"runtimeIds\" in persistedOrSnapshot &&\n Array.isArray((persistedOrSnapshot as any).runtimeIds)\n ) {\n generation = { snapshot: copySnapshot(persistedOrSnapshot as CatalogSnapshot), version: 0 };\n return;\n }\n\n const snapshot = fromPersistedSnapshot(persistedOrSnapshot);\n if (snapshot) {\n generation = { snapshot: copySnapshot(snapshot), version: 0 };\n }\n };\n\n const toPersisted = (): PersistedSnapshot | undefined => {\n if (generation.version === 0 && generation.snapshot.runtimeIds.length === 0) {\n return undefined;\n }\n return toPersistedSnapshot(generation.snapshot);\n };\n\n const refresh = async (context: RefreshContext): Promise<Array<Model<any>>> => {\n const persisted = context.stored?.[PRIVATE_SNAPSHOT_KEY];\n if (persisted) restore(persisted);\n\n const storedModels = () => [...(context.stored?.models ?? [])];\n if (!context.allowNetwork) return storedModels();\n\n try {\n const creds = await resolveCredentials(context);\n if (!creds) return storedModels();\n\n const catalog = await fetchAvailableModelsCatalog(creds, creds.projectId, context.signal);\n record(catalog);\n\n const dynamicModels = buildDynamicPublicModels(catalog);\n\n if (context.publish) {\n await context.publish({\n persist: {\n models: dynamicModels,\n checkedAt: Date.now(),\n [PRIVATE_SNAPSHOT_KEY]: toPersisted(),\n },\n });\n }\n\n return dynamicModels;\n } catch {\n return storedModels();\n }\n };\n\n const refreshGen = async (doRefresh: () => unknown): Promise<CatalogRefreshOutcome> => {\n const versionBefore = generation.version;\n await doRefresh();\n const { items, version } = generation;\n if (!items) return { status: \"failed\" };\n return { status: version === versionBefore ? \"stale\" : \"fresh\", catalog: items };\n };\n\n return {\n generation: () => ({ ...generation, snapshot: copySnapshot(generation.snapshot) }),\n record,\n restore,\n toPersisted,\n refresh,\n refreshGeneration: refreshGen,\n resolvePlan: (publicModelId, effort) => resolveModelPlan(publicModelId, effort, generation.snapshot),\n formatList: () => (generation.items ? formatModelsList(generation.items) : \"No models available.\"),\n };\n}\n\nexport const createCatalogStore = createModelCatalog;\n\nexport async function refreshCatalog(context: RefreshContext, store: ModelCatalog): Promise<Array<Model<any>>> {\n return store.refresh(context);\n}\n", "import * as fs from \"node:fs\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport type { ExtensionCommandContext, Theme } from \"@earendil-works/pi-coding-agent\";\nimport { SettingsList, type SettingItem, type SettingsListTheme } from \"@earendil-works/pi-tui\";\n\nexport const ANSI_FG_RESET = \"\\x1b[39m\";\n\nexport const PROVIDER_CONFIG_FILE = \"pi-provider-antigravity.json\";\n\nexport interface ProviderFileConfig {\n settings?: { [key: string]: unknown };\n // Runtime state namespaced per subsystem (e.g. states.quota); unknown\n // entries pass through untouched.\n states?: { [name: string]: { [key: string]: unknown } | undefined };\n}\n\n// Single opt-in file next to Pi's settings.json (NOT settings.json itself \u2014\n// Pi manages that file and may drop unknown keys). Pi resolves its dir via\n// PI_CODING_AGENT_DIR else ~/.pi/agent:\n// { \"settings\": { \"quotaFooter\": \"smart\" } } // off (default) | smart | all\n// A \"states\" section holds runtime data namespaced per subsystem\n// (e.g. states.quota); unknown keys and sections pass through untouched. Read per call: tiny file, and edits apply\n// on the next refresh without a restart.\nexport function defaultConfigFile(env: NodeJS.ProcessEnv = process.env): string {\n const dir = (env.PI_CODING_AGENT_DIR || \"\").trim() || path.join(os.homedir(), \".pi\", \"agent\");\n return path.join(dir, PROVIDER_CONFIG_FILE);\n}\n\nexport function loadProviderConfig(file = defaultConfigFile()): ProviderFileConfig | undefined {\n try {\n const raw = JSON.parse(fs.readFileSync(file, \"utf-8\"));\n if (raw && typeof raw === \"object\" && !Array.isArray(raw)) return raw as ProviderFileConfig;\n } catch {\n // Missing/unreadable/invalid file means \"not configured\".\n }\n return undefined;\n}\n\n// Temp file in the same directory so the rename stays on one filesystem, and\n// fsync before it so a crash cannot leave the new name pointing at empty data.\n// An existing file's mode is carried over: rename replaces the inode, so\n// without it a user's tightened permissions would silently reset.\nexport function writeProviderConfigAtomically(file: string, data: ProviderFileConfig): boolean {\n const tmp = `${file}.tmp-${process.pid}`;\n try {\n fs.mkdirSync(path.dirname(file), { recursive: true });\n const mode = fs.existsSync(file) ? fs.statSync(file).mode & 0o777 : undefined;\n const fd = fs.openSync(tmp, \"w\", mode);\n try {\n fs.writeFileSync(fd, JSON.stringify(data, null, 2) + \"\\n\", \"utf-8\");\n fs.fsyncSync(fd);\n } finally {\n fs.closeSync(fd);\n }\n fs.renameSync(tmp, file);\n return true;\n } catch {\n try {\n fs.rmSync(tmp, { force: true });\n } catch {\n // Nothing left to clean up.\n }\n return false;\n }\n}\n\n// The file's single writer: parse once, let the caller mutate the keys it owns,\n// write atomically. A file we cannot read is never overwritten \u2014 this is the\n// file the CLI tells users to hand-edit, so one syntax error must not cost them\n// the rest of the document (settings and every subsystem's states entry).\n// Callers keep their own merge rule; leaving other keys untouched is what\n// preserves them.\nexport function updateProviderConfig(\n file: string,\n mutate: (config: ProviderFileConfig) => void,\n): boolean {\n try {\n let data: ProviderFileConfig = {};\n try {\n const raw = JSON.parse(fs.readFileSync(file, \"utf-8\"));\n if (!raw || typeof raw !== \"object\" || Array.isArray(raw)) return false;\n data = raw as ProviderFileConfig;\n } catch (err: any) {\n // A missing file is a fresh install; anything else is unreadable.\n if (err?.code !== \"ENOENT\") return false;\n }\n mutate(data);\n return writeProviderConfigAtomically(file, data);\n } catch {\n // Best-effort: a caller that loses its write keeps working from memory.\n return false;\n }\n}\n\n/**\n * Loads subsystem state from states[subsystem], e.g. states.quota.\n */\nexport function loadSubsystemState<T>(\n subsystem: string,\n file = defaultConfigFile(),\n): T | undefined {\n const state = loadProviderConfig(file)?.states?.[subsystem];\n return state && typeof state === \"object\" && !Array.isArray(state) ? (state as T) : undefined;\n}\n\n/**\n * Atomically merges state into states[subsystem] while preserving settings and other subsystems.\n */\nexport function saveSubsystemState<T extends object>(\n subsystem: string,\n state: T,\n file = defaultConfigFile(),\n): boolean {\n return updateProviderConfig(file, (config) => {\n const states =\n config.states && typeof config.states === \"object\" && !Array.isArray(config.states)\n ? config.states\n : {};\n const current =\n states[subsystem] && typeof states[subsystem] === \"object\" && !Array.isArray(states[subsystem])\n ? states[subsystem]\n : {};\n states[subsystem] = { ...current, ...state };\n config.states = states;\n });\n}\n\nexport interface SettingsFieldDef {\n key: string;\n label: string;\n description?: string;\n options: readonly string[];\n defaultValue?: string;\n optionNotes?: Record<string, string>;\n /** Optional preview hook returning formatted preview text for a chosen value. */\n renderPreview?: (value: string, ctx: ExtensionCommandContext, theme?: Theme) => string | undefined;\n /** Optional async hook invoked after a value is saved. */\n onChange?: (ctx: ExtensionCommandContext, value: string) => Promise<void>;\n /** Optional async prepare hook called before opening the settings dialog. */\n prepare?: (ctx: ExtensionCommandContext) => Promise<void>;\n}\n\nexport class SettingsRegistry {\n private fields: SettingsFieldDef[] = [];\n\n register(field: SettingsFieldDef): void {\n const existingIndex = this.fields.findIndex((f) => f.key === field.key);\n if (existingIndex >= 0) {\n this.fields[existingIndex] = field;\n } else {\n this.fields.push(field);\n }\n }\n\n unregister(key: string): void {\n this.fields = this.fields.filter((f) => f.key !== key);\n }\n\n getFields(): readonly SettingsFieldDef[] {\n return [...this.fields];\n }\n\n clear(): void {\n this.fields = [];\n }\n}\n\nexport const defaultSettingsRegistry = new SettingsRegistry();\n\nexport function registerSettingField(field: SettingsFieldDef): void {\n defaultSettingsRegistry.register(field);\n}\n\nexport function getRegisteredSettingFields(): readonly SettingsFieldDef[] {\n return defaultSettingsRegistry.getFields();\n}\n\nexport function fieldDisplayValue(\n config: ProviderFileConfig | undefined,\n field: SettingsFieldDef,\n): string {\n const raw = config?.settings?.[field.key];\n if (typeof raw === \"string\" && raw.trim()) return raw.trim();\n return field.defaultValue ?? \"unset\";\n}\n\nexport function saveSettingValue(field: SettingsFieldDef, value: string, file: string): boolean {\n return updateProviderConfig(file, (config) => {\n const settings =\n config.settings && typeof config.settings === \"object\" && !Array.isArray(config.settings)\n ? config.settings\n : {};\n settings[field.key] = value;\n config.settings = settings;\n });\n}\n\nexport async function applySettingValue(\n field: SettingsFieldDef,\n value: string,\n file: string,\n ctx: ExtensionCommandContext,\n): Promise<boolean> {\n if (!saveSettingValue(field, value, file)) {\n return false;\n }\n await field.onChange?.(ctx, value);\n return true;\n}\n\n// A refused write is either \"unreadable file\" or \"the write itself failed\", and\n// applySettingValue reports both the same way. So the message stays conditional\n// instead of naming a cause, and still hands over the recovery for the case a\n// hand-editor actually hits.\nfunction writeFailedMessage(file: string): string {\n return `Failed to write ${file}. If the file is not valid JSON, fix or delete it.`;\n}\n\nexport function buildSettingsItems(\n config: ProviderFileConfig | undefined,\n fields: readonly SettingsFieldDef[] = getRegisteredSettingFields(),\n): SettingItem[] {\n return fields.map((f) => ({\n id: f.key,\n label: f.label,\n description: f.description,\n currentValue: fieldDisplayValue(config, f),\n values: [...f.options],\n }));\n}\n\nasync function settingsListTheme(theme: Theme): Promise<SettingsListTheme> {\n try {\n const pi = await import(\"@earendil-works/pi-coding-agent\");\n return pi.getSettingsListTheme();\n } catch {\n return {\n label: (text, selected) => (selected ? theme.fg(\"accent\", text) : text),\n value: (text, selected) => (selected ? theme.fg(\"accent\", text) : theme.fg(\"muted\", text)),\n description: (text) => theme.fg(\"dim\", text),\n cursor: theme.fg(\"accent\", \"\u2192 \"),\n hint: (text) => theme.fg(\"dim\", text),\n };\n }\n}\n\nfunction resolveFields(\n registryOrFields?: SettingsRegistry | readonly SettingsFieldDef[],\n): readonly SettingsFieldDef[] {\n if (!registryOrFields) return getRegisteredSettingFields();\n if (\"getFields\" in registryOrFields && typeof (registryOrFields as any).getFields === \"function\") {\n return (registryOrFields as SettingsRegistry).getFields();\n }\n return registryOrFields as readonly SettingsFieldDef[];\n}\n\nexport async function openSettings(\n ctx: ExtensionCommandContext,\n registryOrFields?: SettingsRegistry | readonly SettingsFieldDef[],\n): Promise<void> {\n const fields = resolveFields(registryOrFields);\n const file = defaultConfigFile();\n if (ctx.mode === \"tui\" && ctx.hasUI) {\n await openSettingsDialog(ctx, fields, file);\n return;\n }\n const config = loadProviderConfig(file);\n if (!ctx.hasUI) {\n const text =\n fields.map((f) => `${f.label}: ${fieldDisplayValue(config, f)}`).join(\"\\n\") +\n `\\nEdit ${file} to change.`;\n if (ctx.hasUI) ctx.ui.notify(text, \"info\");\n else console.log(text);\n return;\n }\n let field = fields[0];\n if (!field) return;\n if (fields.length > 1) {\n const labels = fields.map(\n (f) => `${f.label} (current: ${fieldDisplayValue(config, f)})`,\n );\n const choice = await ctx.ui.select(\"Antigravity settings\", labels);\n if (!choice) return;\n const found = fields[labels.indexOf(choice)];\n if (!found) return;\n field = found;\n }\n const picked = await ctx.ui.select(\n `${field.label} (current: ${fieldDisplayValue(config, field)})`,\n [...field.options],\n );\n if (!picked || !field.options.includes(picked)) return;\n if (await applySettingValue(field, picked, file, ctx)) {\n ctx.ui.notify(`${field.label} set to ${picked}.`, \"info\");\n } else {\n ctx.ui.notify(writeFailedMessage(file), \"error\");\n }\n}\n\nasync function openSettingsDialog(\n ctx: ExtensionCommandContext,\n fields: readonly SettingsFieldDef[],\n file: string,\n): Promise<void> {\n for (const field of fields) {\n if (field.prepare) await field.prepare(ctx);\n }\n await ctx.ui.custom<void>(async (tui, theme, _kb, done) => {\n const config = loadProviderConfig(file);\n const items = buildSettingsItems(config, fields);\n const paintPreview = (field: SettingsFieldDef, value: string) => {\n const item = items.find((i) => i.id === field.key);\n if (!item) return;\n const base = field.description ?? \"\";\n const sample = field.renderPreview?.(value, ctx, theme);\n const head = sample && base ? `${base}: ${sample}` : (sample ?? base);\n const note = field.optionNotes?.[value];\n item.description = note ? `${head}\\n${note}` : head;\n };\n for (const field of fields) {\n const current = fieldDisplayValue(config, field);\n paintPreview(field, current);\n }\n const list = new SettingsList(\n items,\n Math.min(items.length, 10),\n await settingsListTheme(theme),\n (id, newValue) => {\n const field = fields.find((f) => f.key === id);\n if (!field) return;\n list.invalidate();\n tui.requestRender();\n void applySettingValue(field, newValue, file, ctx).then((saved) => {\n // A refused write (unreadable file) must not look like a success: the\n // list has already moved to the value it asked for, so put the row back\n // on what the file actually holds before reporting the failure.\n if (!saved) {\n list.updateValue(field.key, fieldDisplayValue(loadProviderConfig(file), field));\n ctx.ui.notify(writeFailedMessage(file), \"error\");\n list.invalidate();\n tui.requestRender();\n return;\n }\n paintPreview(field, newValue);\n list.invalidate();\n tui.requestRender();\n });\n },\n () => done(),\n );\n const border = {\n render: (width: number) => [theme.fg(\"border\", \"\u2500\".repeat(Math.max(1, width)))],\n };\n return {\n render: (width: number) => [\n ...border.render(width),\n ...list.render(width),\n ...border.render(width),\n ],\n handleInput: (data: string) => list.handleInput(data),\n invalidate: () => list.invalidate(),\n };\n });\n}\n", "import type { ExtensionCommandContext, ExtensionContext, Theme } from \"@earendil-works/pi-coding-agent\";\nimport { resolveCredentials } from \"./auth.ts\";\nimport { classifyModelFamily } from \"./model-identity.ts\";\nimport { postAntigravityJson, PROVIDER_ID } from \"./protocol.ts\";\nimport {\n defaultConfigFile,\n loadProviderConfig,\n loadSubsystemState,\n saveSubsystemState,\n registerSettingField,\n type ProviderFileConfig,\n type SettingsFieldDef,\n} from \"./config.ts\";\n\n/**\n * Quota Status module (deep, ports & adapters): Quota Pool wire parsing, urgent-window\n * math, ratio self-calibration, throttle, cache, and status footer slot painting.\n * Persists calibration state through the Provider Config Seam (states.quota).\n */\n\nexport type QuotaFooterMode = \"off\" | \"smart\" | \"all\";\n\nexport const FOOTER_MODE_NOTES: Readonly<Record<string, string>> = Object.freeze({\n smart:\n \"Picks whichever window runs out first (5h or weekly), weighting the weekly pool by a ratio learned from your usage\",\n all: \"Lists every window of the pool backing the current model (5h or weekly)\",\n});\n\nexport const FOOTER_MODE_OPTIONS: readonly QuotaFooterMode[] = Object.freeze([\n \"off\",\n \"smart\",\n \"all\",\n]);\n\nexport function normalizeFooterMode(value: unknown): QuotaFooterMode | undefined {\n const v = typeof value === \"string\" ? value.trim().toLowerCase() : \"\";\n return FOOTER_MODE_OPTIONS.includes(v as QuotaFooterMode) ? (v as QuotaFooterMode) : undefined;\n}\n\nexport function resolveFooterMode(config?: ProviderFileConfig): QuotaFooterMode {\n return normalizeFooterMode(config?.settings?.quotaFooter) ?? \"off\";\n}\n\nexport interface QuotaBucket {\n bucketId: string;\n displayName: string;\n window?: string;\n resetTime?: string;\n description?: string;\n remainingFraction: number;\n}\n\nexport interface QuotaGroup {\n displayName: string;\n description?: string;\n buckets: QuotaBucket[];\n}\n\nexport interface QuotaSummary {\n groups: QuotaGroup[];\n description?: string;\n}\n\nexport function renderProgressBar(fraction: number, width = 10): string {\n const clamped = Math.max(0, Math.min(1, fraction));\n const filled = Math.round(clamped * width);\n return `[${\"#\".repeat(filled)}${\"-\".repeat(width - filled)}]`;\n}\n\ntype QuotaWindowKind = \"5h\" | \"weekly\" | \"other\";\n\nconst QUOTA_WINDOW_RANK: Record<QuotaWindowKind, number> = {\n \"5h\": 0,\n weekly: 1,\n other: 2,\n};\n\nfunction classifyQuotaWindow(bucket: QuotaBucket): QuotaWindowKind {\n // The wire reports a machine `window` (\"5h\"/\"weekly\" in every capture). Trust\n // it \u2014 no display-prose guessing. Unknown or missing windows are \"other\".\n const w = (bucket.window || \"\").trim().toLowerCase();\n if (w === \"5h\") return \"5h\";\n if (w === \"weekly\") return \"weekly\";\n return \"other\";\n}\n\nfunction shortWindowLabel(bucket: QuotaBucket, kind: QuotaWindowKind): string {\n if (kind === \"5h\") return \"5h\";\n if (kind === \"weekly\") return \"Wk\";\n return bucket.displayName || bucket.bucketId || \"Quota\";\n}\n\nfunction sortQuotaBuckets(buckets: QuotaBucket[]): QuotaBucket[] {\n return buckets\n .slice()\n .sort(\n (a, b) =>\n QUOTA_WINDOW_RANK[classifyQuotaWindow(a)] - QUOTA_WINDOW_RANK[classifyQuotaWindow(b)],\n );\n}\n\nexport function formatResetRemaining(resetTime?: string): string | null {\n if (!resetTime) return null;\n const ts = Date.parse(resetTime);\n if (!Number.isFinite(ts)) return null;\n const delta = ts - Date.now();\n if (delta <= 0) return \"ready\";\n const totalMin = Math.ceil(delta / 60000);\n const days = Math.floor(totalMin / (60 * 24));\n const hours = Math.floor((totalMin % (60 * 24)) / 60);\n const mins = totalMin % 60;\n if (days > 0) return `in ${days}d ${hours}h`;\n if (hours > 0) return `in ${hours}h ${mins}m`;\n return `in ${mins}m`;\n}\n\nexport function parseQuotaSummary(data: any): QuotaSummary {\n const groups: QuotaGroup[] = [];\n\n for (const g of data.groups || []) {\n const buckets: QuotaBucket[] = [];\n for (const b of g.buckets || []) {\n buckets.push({\n bucketId: b.bucketId || \"unknown\",\n displayName: b.displayName || b.bucketId || \"Limit\",\n window: b.window,\n resetTime: b.resetTime,\n description: b.description,\n remainingFraction: typeof b.remainingFraction === \"number\" ? b.remainingFraction : 1,\n });\n }\n groups.push({\n displayName: g.displayName || \"Quota Group\",\n description: g.description,\n buckets,\n });\n }\n\n return {\n groups,\n description: data.description,\n };\n}\n\nexport function formatQuotaSummary(summary: QuotaSummary): string {\n const lines: string[] = [];\n\n for (const group of summary.groups) {\n if (lines.length > 0) lines.push(\"\");\n lines.push(`${group.displayName}`);\n for (const b of sortQuotaBuckets(group.buckets)) {\n const pct = Math.round(b.remainingFraction * 100);\n const label = shortWindowLabel(b, classifyQuotaWindow(b)).padEnd(3);\n const reset = formatResetRemaining(b.resetTime);\n const suffix = reset && pct < 100 ? ` (${reset})` : \"\";\n lines.push(\n ` ${label} ${renderProgressBar(b.remainingFraction)} ${String(pct).padStart(3)}% left${suffix}`,\n );\n }\n }\n\n return lines.join(\"\\n\");\n}\n\nexport function isGeminiQuotaGroup(group: QuotaGroup): boolean {\n // Bucket ids (\"gemini-5h\" vs \"3p-5h\") \u2014 not display prose (\"Gemini Models\").\n return (group.buckets || []).some((b) => (b.bucketId || \"\").toLowerCase().includes(\"gemini\"));\n}\n\nexport function selectQuotaGroup(groups: QuotaGroup[], modelId?: string): QuotaGroup | undefined {\n if (groups.length === 0) return undefined;\n const family = classifyModelFamily(modelId);\n if (family === \"claude\" || family === \"gpt\") {\n const found = groups.find((g) => !isGeminiQuotaGroup(g));\n if (found) return found;\n }\n return groups.find((g) => isGeminiQuotaGroup(g)) || groups[0];\n}\n\n// Compact one-line footer text (e.g. \"Wk 6% (2d 15h)\") showing the most\n// urgent window of the group backing the current model: 5h and weekly pools\n// differ in volume, so the wall you hit first is min(r5h, rWk \u00D7 R) \u2014 not min\n// fraction. R self-calibrates from observed deltas (see calibrateWeeklyTo5hRatio).\nexport const DEFAULT_WEEKLY_TO_5H_RATIO = 6.0;\n\nexport interface WindowFractionPair {\n \"5h\": number;\n weekly: number;\n}\n\nfunction windowBucket(buckets: QuotaBucket[], kind: QuotaWindowKind): QuotaBucket | undefined {\n return buckets.find((b) => classifyQuotaWindow(b) === kind);\n}\n\n// Pool-group key for persisted pairs: the 5h bucket's wire id minus its window\n// suffix (\"gemini-5h\" \u2192 \"gemini\"). Display names are upstream prose, and the raw\n// id would echo the window inside every record (\"gemini-5h\": { \"5h\", weekly }).\n// Unrecognized shapes keep the full id \u2014 matching only needs determinism.\nfunction poolKey(bucket: QuotaBucket): string {\n const id = bucket.bucketId || \"unknown\";\n return id.replace(/[-_](5h|five-?hour|weekly)$/i, \"\") || id;\n}\n\n// Plain-object form for JSON persistence (see coordinator state).\nexport function extractWindowFractionPairs(\n summary?: QuotaSummary,\n): Record<string, WindowFractionPair> {\n const pairs: Record<string, WindowFractionPair> = {};\n for (const g of summary?.groups || []) {\n const bucket5h = windowBucket(g.buckets, \"5h\");\n const bucketWeekly = windowBucket(g.buckets, \"weekly\");\n if (bucket5h && bucketWeekly)\n pairs[poolKey(bucket5h)] = {\n \"5h\": bucket5h.remainingFraction,\n weekly: bucketWeekly.remainingFraction,\n };\n }\n return pairs;\n}\n\n// Self-calibrates the 5h vs weekly volume ratio R from delta consumption:\n// the same absolute spend drops the 5h fraction R\u00D7 faster than weekly.\n// First valid pool wins; resets and noise fall outside the guards below.\nexport function calibrateWeeklyTo5hRatio(\n previous: Record<string, WindowFractionPair> | undefined,\n current: Record<string, WindowFractionPair> | undefined,\n currentRatio = DEFAULT_WEEKLY_TO_5H_RATIO,\n): number {\n if (!previous || !current) return currentRatio;\n for (const key of Object.keys(current)) {\n const prev = previous[key];\n const curr = current[key];\n if (!prev || !curr) continue;\n\n const dFiveHour = prev[\"5h\"] - curr[\"5h\"];\n const dWeekly = prev.weekly - curr.weekly;\n\n if (dFiveHour > 0.0001 && dWeekly > 0.00001) {\n const observedRatio = dFiveHour / dWeekly;\n if (observedRatio >= 1.0 && observedRatio <= 20.0) {\n return Math.round(observedRatio * 100) / 100;\n }\n }\n }\n return currentRatio;\n}\n\nfunction selectUrgentBucket(group: QuotaGroup, weeklyTo5hRatio: number): QuotaBucket | undefined {\n const buckets = group.buckets;\n if (buckets.length === 0) return undefined;\n const bucket5h = windowBucket(buckets, \"5h\");\n const bucketWeekly = windowBucket(buckets, \"weekly\");\n if (bucket5h && bucketWeekly) {\n return bucketWeekly.remainingFraction * weeklyTo5hRatio < bucket5h.remainingFraction\n ? bucketWeekly\n : bucket5h;\n }\n let worst = buckets[0];\n for (const b of buckets) {\n if (b.remainingFraction < worst.remainingFraction) worst = b;\n }\n return worst;\n}\n\nexport function buildQuotaFooter(\n summary: QuotaSummary,\n modelId?: string,\n weeklyTo5hRatio = DEFAULT_WEEKLY_TO_5H_RATIO,\n): string | undefined {\n const group = selectQuotaGroup(summary.groups, modelId);\n if (!group) return undefined;\n const urgent = selectUrgentBucket(group, weeklyTo5hRatio);\n return urgent ? formatQuotaWindowPart(urgent) : undefined;\n}\n\n// Both windows of the backing group, 5h first (e.g. \"5h 35% (26m) \u00B7 Wk 75% (6d 14h)\").\nexport function buildQuotaFooterBoth(summary: QuotaSummary, modelId?: string): string | undefined {\n const group = selectQuotaGroup(summary.groups, modelId);\n if (!group || group.buckets.length === 0) return undefined;\n return sortQuotaBuckets(group.buckets).map(formatQuotaWindowPart).join(\" \u00B7 \");\n}\n\n// Window prefix names the bucket (\"5h\"/\"Wk\"); unknown windows fall back to\n// the bucket's own display name.\nexport function formatQuotaWindowPart(bucket: QuotaBucket): string {\n const kind = classifyQuotaWindow(bucket);\n const prefix =\n kind === \"5h\" ? \"5h\" : kind === \"weekly\" ? \"Wk\" : bucket.displayName || bucket.bucketId;\n const pct = Math.round(bucket.remainingFraction * 100);\n const short = formatResetRemaining(bucket.resetTime)?.replace(/^in /, \"\");\n if (short && pct < 100) return `${prefix} ${pct}% (${short})`;\n return `${prefix} ${pct}%`;\n}\n\n// Threshold coloring for footer slots. Prefers Theme.fg when available so\n// coloring adapts to the active theme (light/dark/custom); falls back to basic\n// ANSI on dark (mirroring Theme.fg with foreground-only resets) when invoked\n// without a theme (e.g. tests, headless, or mock contexts).\nconst ANSI_RED = \"\\x1b[31m\";\nconst ANSI_YELLOW = \"\\x1b[33m\";\nconst ANSI_DIM = \"\\x1b[90m\";\nexport const ANSI_FG_RESET = \"\\x1b[39m\";\n\nexport const QUOTA_WARN_PCT = 30;\nexport const QUOTA_ALERT_PCT = 10;\n\nexport type QuotaColorTone = \"error\" | \"warning\" | \"dim\";\nexport type QuotaColorizer = (tone: QuotaColorTone, text: string) => string;\nexport type QuotaColorStyle =\n | { fg: (tone: QuotaColorTone, text: string) => string }\n | QuotaColorizer;\n\nfunction resolveColorizer(style?: QuotaColorStyle): QuotaColorizer {\n if (typeof style === \"function\") return style;\n if (style && typeof style.fg === \"function\") return (tone, text) => style.fg(tone, text);\n return (tone, text) => {\n const code = tone === \"error\" ? ANSI_RED : tone === \"warning\" ? ANSI_YELLOW : ANSI_DIM;\n return `${code}${text}${ANSI_FG_RESET}`;\n };\n}\n\nexport function colorizeQuotaFooter(\n footer: string | undefined,\n style?: QuotaColorStyle,\n): string | undefined {\n if (!footer) return undefined;\n const color = resolveColorizer(style);\n const match = footer.match(/(\\d+)%/);\n if (!match) return color(\"dim\", footer);\n const pct = parseInt(match[1], 10);\n if (pct <= QUOTA_ALERT_PCT) return color(\"error\", footer);\n if (pct <= QUOTA_WARN_PCT) return color(\"warning\", footer);\n return color(\"dim\", footer);\n}\n\n// Colors each \" \u00B7 \"-separated window part by its own percentage.\nexport function colorizeQuotaFooterBoth(\n footer: string | undefined,\n style?: QuotaColorStyle,\n): string | undefined {\n if (!footer) return undefined;\n const color = resolveColorizer(style);\n const sep = color(\"dim\", \" \u00B7 \");\n return footer\n .split(\" \u00B7 \")\n .map((part) => colorizeQuotaFooter(part, style) ?? part)\n .join(sep);\n}\n\nexport function previewQuotaFooterText(\n coord: QuotaStatusCoordinator | undefined,\n modelId: string | undefined,\n mode: string,\n style?: QuotaColorStyle,\n): string | undefined {\n if (!coord) return undefined;\n const normalized = normalizeFooterMode(mode);\n if (!normalized || normalized === \"off\") return undefined;\n const { colored } = coord.renderFooter(modelId, normalized, style);\n if (!colored) return undefined;\n return ANSI_FG_RESET + colored;\n}\n\n// Namespaced by repo so no other extension (e.g. a personal-config \"quota\"\n// slot) can overwrite this footer slot, and vice versa.\nexport const QUOTA_STATUS_KEY = \"pi-provider-antigravity-footer-usage\";\nexport const QUOTA_REFRESH_INTERVAL_MS = 5 * 60 * 1000;\n// Baselines older than this may straddle a quota reset (negative or\n// meaningless deltas), so cross-session calibration ignores them. An hour\n// caps the straddle risk at ~1/5 of the 5h window while an hour of active\n// use still dwarfs the noise guards below thousands-fold.\nexport const MAX_OBSERVATION_AGE_MS = 60 * 60 * 1000;\n\n// Persisted Quota Pool calibration state (states.quota in the provider file).\n// The file shape is owned by the settings subsystem; the coordinator only sees\n// this narrow view through its store.\nexport interface QuotaState {\n [key: string]: unknown;\n}\n\n// The seam behind the coordinator: production uses the file-backed store\n// from local config file, tests use an in-memory adapter or custom file.\nexport interface QuotaStatusStore {\n loadMode: () => QuotaFooterMode;\n loadQuotaState: () => QuotaState | undefined;\n saveQuotaState: (state: {\n weeklyTo5hRatio: number;\n previousObservation: Record<string, WindowFractionPair>;\n updatedAt: number;\n }) => boolean;\n}\n\n// Production QuotaStatusStore backed by the provider file. Reads per call:\n// tiny file, and edits apply on the next refresh without a restart.\nexport function fileQuotaStatusStore(file = defaultConfigFile()): QuotaStatusStore {\n return {\n loadMode: () => resolveFooterMode(loadProviderConfig(file)),\n loadQuotaState: () => loadSubsystemState<QuotaState>(\"quota\", file),\n saveQuotaState: (state) => saveSubsystemState(\"quota\", state, file),\n };\n}\n\nexport function createQuotaFooterField(\n quotaStatus: QuotaStatusCoordinator,\n): SettingsFieldDef {\n return {\n key: \"quotaFooter\",\n label: \"Quota footer\",\n description: \"Show remaining quota in Pi's status footer\",\n options: FOOTER_MODE_OPTIONS,\n defaultValue: \"off\",\n optionNotes: FOOTER_MODE_NOTES,\n renderPreview: (mode, ctx, theme) => {\n if (mode === \"off\") return \"hidden\";\n const activeTheme = theme || (ctx.ui as { theme?: Theme })?.theme;\n return previewQuotaFooterText(quotaStatus, ctx.model?.id, mode, activeTheme);\n },\n prepare: async (ctx) => {\n await quotaStatus.ensurePreview(ctx);\n },\n onChange: async (ctx, _value) => {\n if (quotaStatus.mode() !== \"off\") {\n await quotaStatus.refresh(ctx, { ignoreMode: true });\n }\n quotaStatus.paint(ctx);\n },\n };\n}\n\nexport function registerQuotaSettings(quotaStatus: QuotaStatusCoordinator): void {\n registerSettingField(createQuotaFooterField(quotaStatus));\n}\n\nexport interface RefreshOptions {\n force?: boolean;\n // Explicit looks at quota (/antigravity usage) bypass the mode and model\n // gates but still calibrate, persist, and share the throttle window.\n ignoreMode?: boolean;\n signal?: AbortSignal;\n}\n\nfunction isFiniteNumber(value: unknown): value is number {\n return typeof value === \"number\" && Number.isFinite(value);\n}\n\n// Lenient shape check for persisted observations; garbage restores as absent.\nfunction validPairs(raw: unknown): Record<string, WindowFractionPair> | undefined {\n if (!raw || typeof raw !== \"object\" || Array.isArray(raw)) return undefined;\n const pairs: Record<string, WindowFractionPair> = {};\n for (const [key, value] of Object.entries(raw)) {\n const rec = value as { \"5h\"?: unknown; weekly?: unknown };\n const fiveHour = rec?.[\"5h\"];\n const weekly = rec?.weekly;\n if (isFiniteNumber(fiveHour) && isFiniteNumber(weekly)) pairs[key] = { \"5h\": fiveHour, weekly };\n }\n return Object.keys(pairs).length > 0 ? pairs : undefined;\n}\n\nexport type QuotaStatusCtx = Pick<ExtensionContext, \"ui\" | \"modelRegistry\" | \"model\">;\n\n// Pi binds every ExtensionContext property read to a liveness assertion, so a\n// ctx captured before a session replacement or reload throws on any read once\n// the runtime is invalidated. A turn aborted by teardown still emits\n// agent_settled from that invalidated runtime, so handlers receive a dead ctx.\n// Probe once before touching it \u2014 painting a dead session's footer is meaningless.\nfunction isLiveCtx(ctx: QuotaStatusCtx): boolean {\n try {\n void ctx.ui;\n return true;\n } catch {\n return false;\n }\n}\n\nexport interface FooterModeDef {\n key: QuotaFooterMode;\n note?: string;\n render: (\n summary: QuotaSummary | undefined,\n modelId?: string,\n ratio?: number,\n style?: QuotaColorStyle,\n ) => { plain?: string; colored?: string };\n}\n\nexport const FOOTER_MODES: Record<QuotaFooterMode, FooterModeDef> = Object.freeze({\n off: {\n key: \"off\",\n render: () => ({}),\n },\n smart: {\n key: \"smart\",\n note: FOOTER_MODE_NOTES.smart,\n render: (summary, modelId, ratio = DEFAULT_WEEKLY_TO_5H_RATIO, style) => {\n if (!summary) return {};\n const plain = buildQuotaFooter(summary, modelId, ratio);\n return { plain, colored: colorizeQuotaFooter(plain, style) };\n },\n },\n all: {\n key: \"all\",\n note: FOOTER_MODE_NOTES.all,\n render: (summary, modelId, _ratio, style) => {\n if (!summary) return {};\n const plain = buildQuotaFooterBoth(summary, modelId);\n return { plain, colored: colorizeQuotaFooterBoth(plain, style) };\n },\n },\n});\n\nexport function isAntigravityModel(model?: { provider?: string }): boolean {\n return model?.provider === PROVIDER_ID;\n}\n\nexport function paintQuotaStatus(coord: QuotaStatusCoordinator, ctx: QuotaStatusCtx): void {\n coord.paint(ctx);\n}\n\n// In-memory throttle around the quota fetch: at most one network call per\n// QUOTA_REFRESH_INTERVAL_MS, with inflight dedup. Failures keep the stale\n// footer instead of flashing errors in the status bar.\nexport class QuotaStatusCoordinator {\n private summary: QuotaSummary | undefined;\n private fetchedAt = 0;\n private inflight: Promise<QuotaSummary | undefined> | null = null;\n private weeklyTo5hRatio: number;\n private lastPairs: Record<string, WindowFractionPair> | undefined;\n private readonly store: QuotaStatusStore;\n\n constructor(storeOrFile?: string | QuotaStatusStore) {\n if (typeof storeOrFile === \"string\" || !storeOrFile) {\n this.store = fileQuotaStatusStore(storeOrFile || defaultConfigFile());\n } else {\n this.store = storeOrFile;\n }\n this.weeklyTo5hRatio = DEFAULT_WEEKLY_TO_5H_RATIO;\n this.loadPersisted();\n }\n\n get ratio(): number {\n return this.weeklyTo5hRatio;\n }\n\n // Single source of truth for the mode: the injected store.\n mode(): QuotaFooterMode {\n return this.store.loadMode();\n }\n\n footerFor(modelId?: string, mode: QuotaFooterMode = \"smart\"): string | undefined {\n return FOOTER_MODES[mode]?.render(this.summary, modelId, this.weeklyTo5hRatio).plain;\n }\n\n renderFooter(\n modelId?: string,\n mode: QuotaFooterMode = \"smart\",\n style?: QuotaColorStyle,\n ): { plain?: string; colored?: string } {\n return FOOTER_MODES[mode]?.render(this.summary, modelId, this.weeklyTo5hRatio, style) ?? {};\n }\n\n get isFresh(): boolean {\n return !!this.summary && Date.now() - this.fetchedAt < QUOTA_REFRESH_INTERVAL_MS;\n }\n\n refresh(ctx: QuotaStatusCtx, opts: RefreshOptions = {}): Promise<QuotaSummary | undefined> {\n if (!isLiveCtx(ctx)) return Promise.resolve(undefined);\n if (!opts.ignoreMode && (this.mode() === \"off\" || !isAntigravityModel(ctx.model))) {\n return Promise.resolve(undefined);\n }\n if (this.inflight) return this.inflight;\n if (!opts.force && this.isFresh) return Promise.resolve(this.summary);\n return this.fetchOnce(ctx, opts.signal);\n }\n\n // The single ordering behind the footer slot: paint cached text instantly,\n // refresh when the throttle window expired, repaint with fresh text.\n // Event handlers delegate here instead of replicating the sequence.\n async refreshAndPaint(ctx: QuotaStatusCtx): Promise<void> {\n this.paint(ctx);\n await this.refresh(ctx);\n this.paint(ctx);\n }\n\n // Paints current cached quota status to the footer slot.\n paint(ctx: QuotaStatusCtx): void {\n if (!isLiveCtx(ctx)) return;\n const mode = this.mode();\n if (mode === \"off\" || !isAntigravityModel(ctx.model)) {\n ctx.ui.setStatus(QUOTA_STATUS_KEY, undefined);\n return;\n }\n const theme = (ctx.ui as { theme?: Theme })?.theme;\n const { colored } = this.renderFooter(ctx.model?.id, mode, theme);\n ctx.ui.setStatus(QUOTA_STATUS_KEY, colored);\n }\n\n // Atomic inspect for /antigravity usage: forces fresh quota fetch, repaints\n // the footer slot, and formats the full summary. Callers need no flag knowledge.\n async inspectUsage(ctx: QuotaStatusCtx & { signal?: AbortSignal }): Promise<string> {\n const summary = await this.refresh(ctx, { force: true, ignoreMode: true, signal: ctx.signal });\n if (!summary) {\n throw new Error(\"Failed to fetch usage.\");\n }\n this.paint(ctx);\n return formatQuotaSummary(summary);\n }\n\n // One fetch for preview purposes even when the footer slot is off or the\n // current model belongs to another provider: opening quota settings is an\n // explicit look at quota (like /antigravity usage), and the preview is the\n // only place that quota is visible while a foreign model is selected.\n ensurePreview(ctx: QuotaStatusCtx): Promise<QuotaSummary | undefined> {\n if (this.summary) return Promise.resolve(this.summary);\n if (this.inflight) return this.inflight;\n return this.fetchOnce(ctx);\n }\n\n private fetchOnce(ctx: QuotaStatusCtx, signal?: AbortSignal): Promise<QuotaSummary | undefined> {\n this.inflight = this.fetch(ctx, signal).finally(() => {\n this.inflight = null;\n });\n return this.inflight;\n }\n\n private async fetch(\n ctx: QuotaStatusCtx,\n signal?: AbortSignal,\n ): Promise<QuotaSummary | undefined> {\n try {\n const creds = await resolveCredentials(ctx);\n if (!creds) return undefined;\n const rawSummary = await postAntigravityJson<any>({\n auth: creds,\n path: \"v1internal:retrieveUserQuotaSummary\",\n body: { project: creds.projectId },\n signal,\n });\n const summary = parseQuotaSummary(rawSummary);\n this.ingest(summary);\n return summary;\n } catch {\n return undefined;\n }\n }\n\n // Accepts an externally fetched summary into the shared cache: same\n // calibration, persistence, and freshness as fetch().\n ingest(summary: QuotaSummary): void {\n const calibrated = calibrateWeeklyTo5hRatio(\n this.lastPairs,\n extractWindowFractionPairs(summary),\n this.weeklyTo5hRatio,\n );\n this.weeklyTo5hRatio = calibrated;\n this.lastPairs = extractWindowFractionPairs(summary);\n this.summary = summary;\n this.fetchedAt = Date.now();\n this.saveState();\n }\n\n private loadPersisted(): void {\n const entry = this.store.loadQuotaState();\n const ratio = entry?.weeklyTo5hRatio;\n if (typeof ratio === \"number\" && Number.isFinite(ratio) && ratio > 0) {\n this.weeklyTo5hRatio = ratio;\n }\n const at = entry?.updatedAt;\n this.lastPairs =\n typeof at === \"number\" && Date.now() - at <= MAX_OBSERVATION_AGE_MS\n ? validPairs(entry?.previousObservation)\n : undefined;\n }\n\n // Persists calibration state through the injected store. Best-effort: a\n // stale ratio is still usable.\n private saveState(): void {\n try {\n this.store.saveQuotaState({\n weeklyTo5hRatio: this.weeklyTo5hRatio,\n previousObservation: this.lastPairs ?? {},\n updatedAt: Date.now(),\n });\n } catch {\n // Cache is best-effort; a stale ratio is still usable.\n }\n }\n}\n", "import {\n type AssistantMessage,\n type AssistantMessageEventStream,\n type Model,\n type SimpleStreamOptions,\n type TextContent,\n type ThinkingContent,\n type ToolCall,\n type TranscriptContext,\n createAssistantMessageEventStream,\n} from \"@earendil-works/pi-ai\";\nimport { requireCredentials } from \"./auth.ts\";\nimport { buildAntigravityRequestBody } from \"./builder.ts\";\nimport { postAntigravityStream } from \"./protocol.ts\";\nimport type { ModelCatalog } from \"./model-catalog.ts\";\n\n/**\n * One assembled content block, Pi-spelled (TextContent | ThinkingContent |\n * ToolCall): thinking blocks carry thinkingSignature, text blocks carry\n * textSignature, toolCalls carry the wire-spelled thoughtSignature.\n */\nexport type ParsedBlock = TextContent | ThinkingContent | ToolCall;\n\nexport interface ParsedStreamResult {\n content: ParsedBlock[];\n usage: {\n input: number;\n output: number;\n cacheRead: number;\n /**\n * Reasoning tokens, a subset of `output` (pi-ai Usage.reasoning). Captured\n * turns without a `thoughtsTokenCount` report 0, like pi-ai's own Google\n * adapter does for a missing count.\n */\n reasoning: number;\n total: number;\n };\n stopReason: \"stop\" | \"toolUse\" | \"length\" | \"error\";\n responseId?: string;\n}\n\nexport type StreamDeliveryEvent =\n | { type: \"text_start\" | \"thinking_start\"; contentIndex: number }\n | { type: \"text_delta\" | \"thinking_delta\"; contentIndex: number; delta: string }\n | { type: \"text_end\" | \"thinking_end\"; contentIndex: number; content: string }\n | { type: \"toolcall_start\"; contentIndex: number }\n | { type: \"toolcall_delta\"; contentIndex: number; delta: string }\n | { type: \"toolcall_end\"; contentIndex: number; toolCall: ToolCall };\n\ninterface StreamParserState {\n content: ParsedBlock[];\n usage: ParsedStreamResult[\"usage\"];\n stopReason: ParsedStreamResult[\"stopReason\"];\n openType: \"text\" | \"thinking\" | null;\n lastThoughtSignature?: string;\n responseId?: string;\n buffer: string;\n}\n\nfunction attachLoneSignature(content: ParsedBlock[], lastThoughtSignature?: string): void {\n if (!lastThoughtSignature) return;\n // Not lone: a block already carries it. The wire sends\n // `{thoughtSignature, functionCall}`, whose signature the toolCall branch\n // attaches itself \u2014 pushing a carrier on top of that put an empty text\n // block on a turn that never had one.\n const attached = content.some((b) =>\n b.type === \"thinking\"\n ? Boolean(b.thinkingSignature)\n : b.type === \"toolCall\"\n ? Boolean(b.thoughtSignature)\n : b.type === \"text\"\n ? Boolean(b.textSignature)\n : false,\n );\n if (attached) return;\n\n const thinking = content.find((b): b is ThinkingContent => b.type === \"thinking\");\n if (thinking) {\n if (!thinking.thinkingSignature) thinking.thinkingSignature = lastThoughtSignature;\n return;\n }\n\n for (let i = content.length - 1; i >= 0; i--) {\n const block = content[i];\n if (block?.type === \"text\" && !block.textSignature) {\n block.textSignature = lastThoughtSignature;\n return;\n }\n }\n\n // The turn carried no block to hold it: keep the signature rather than\n // dropping it silently. The builder drops the empty part and replays the\n // signature on the next one, so this never puts an empty text on the wire.\n content.push({ type: \"text\", text: \"\", textSignature: lastThoughtSignature });\n}\n\nfunction closeOpenBlock(\n state: StreamParserState,\n onEvent?: (ev: StreamDeliveryEvent) => void,\n): void {\n if (state.openType === null) return;\n const contentIndex = state.content.length - 1;\n const block = state.content[contentIndex];\n if (block?.type === \"thinking\") {\n onEvent?.({ type: \"thinking_end\", contentIndex, content: block.thinking });\n } else if (block?.type === \"text\") {\n onEvent?.({ type: \"text_end\", contentIndex, content: block.text });\n }\n state.openType = null;\n}\n\nfunction processLine(\n rawLine: string,\n state: StreamParserState,\n onEvent?: (ev: StreamDeliveryEvent) => void,\n): void {\n const line = rawLine.trim();\n if (!line.startsWith(\"data:\")) return;\n\n const dataStr = line.slice(5).trim();\n if (!dataStr || dataStr === \"[DONE]\") return;\n\n let payload: any;\n try {\n payload = JSON.parse(dataStr);\n } catch {\n return;\n }\n\n const response = payload.response || payload;\n\n if (response.responseId && !state.responseId) {\n state.responseId = response.responseId;\n }\n\n // Usage metadata (promptTokenCount includes cached tokens per Google spec).\n // output counts thinking tokens too, mirroring the pi-ai Google adapter:\n // usageMetadata reports candidates and thoughts separately.\n if (response.usageMetadata) {\n const um = response.usageMetadata;\n const promptTokens = typeof um.promptTokenCount === \"number\" ? um.promptTokenCount : 0;\n const cacheRead = typeof um.cachedContentTokenCount === \"number\" ? um.cachedContentTokenCount : 0;\n state.usage.input = Math.max(0, promptTokens - cacheRead);\n state.usage.cacheRead = cacheRead;\n const candidates = typeof um.candidatesTokenCount === \"number\" ? um.candidatesTokenCount : 0;\n const thoughts = typeof um.thoughtsTokenCount === \"number\" ? um.thoughtsTokenCount : 0;\n state.usage.output = candidates + thoughts;\n state.usage.reasoning = thoughts;\n if (typeof um.totalTokenCount === \"number\") state.usage.total = um.totalTokenCount;\n }\n\n const candidate = response.candidates?.[0];\n if (!candidate) return;\n\n // Sticky: length/error/toolUse are never downgraded by a later STOP.\n // Mirrors pi-ai mapStopReasonString: only STOP is benign, MAX_TOKENS is\n // length, every other reason (SAFETY, RECITATION, BLOCKLIST, ...) is error.\n if (candidate.finishReason === \"MAX_TOKENS\") {\n state.stopReason = \"length\";\n } else if (typeof candidate.finishReason === \"string\" && candidate.finishReason !== \"STOP\") {\n state.stopReason = \"error\";\n }\n\n const parts = candidate.content?.parts || [];\n for (const part of parts) {\n if (part.thoughtSignature) {\n state.lastThoughtSignature = part.thoughtSignature;\n }\n\n if (part.thought) {\n const delta = part.text || \"\";\n // A part carrying no thinking text opens no block: the wire uses empty\n // thought parts as Thought Signature carriers, and an eager block would\n // outlive the turn as an empty thinking block, which the builder replays\n // as `{thought:true,text:\"\"}` \u2014 a part the wire never sends. The signature is\n // already recorded above; close() keeps a carrier for it.\n if (delta === \"\" && state.openType !== \"thinking\") continue;\n if (state.openType !== \"thinking\") {\n closeOpenBlock(state, onEvent);\n state.content.push({ type: \"thinking\", thinking: \"\" });\n onEvent?.({ type: \"thinking_start\", contentIndex: state.content.length - 1 });\n state.openType = \"thinking\";\n }\n const block = state.content[state.content.length - 1];\n if (block?.type !== \"thinking\") continue;\n block.thinking += delta;\n if (part.thoughtSignature) {\n block.thinkingSignature = part.thoughtSignature;\n }\n onEvent?.({\n type: \"thinking_delta\",\n contentIndex: state.content.length - 1,\n delta,\n });\n } else if (part.functionCall) {\n closeOpenBlock(state, onEvent);\n state.stopReason = \"toolUse\";\n const block: ToolCall = {\n type: \"toolCall\",\n id: part.functionCall.id || `call_${state.content.length}`,\n name: part.functionCall.name || \"\",\n arguments: part.functionCall.args || {},\n thoughtSignature: part.thoughtSignature || state.lastThoughtSignature,\n };\n state.content.push(block);\n const contentIndex = state.content.length - 1;\n onEvent?.({ type: \"toolcall_start\", contentIndex });\n onEvent?.({\n type: \"toolcall_delta\",\n contentIndex,\n delta: JSON.stringify(block.arguments),\n });\n onEvent?.({ type: \"toolcall_end\", contentIndex, toolCall: block });\n } else if (part.text !== undefined) {\n // Same rule as the thinking branch: an empty text part is a Thought\n // Signature carrier (or a streamed artifact), not content, so it opens no\n // block. 7 of the 26 frozen responses and 91% of live antigravity turns\n // carried the empty block this used to create.\n if (part.text === \"\" && state.openType !== \"text\") continue;\n if (state.openType !== \"text\") {\n closeOpenBlock(state, onEvent);\n state.content.push({ type: \"text\", text: \"\" });\n onEvent?.({ type: \"text_start\", contentIndex: state.content.length - 1 });\n state.openType = \"text\";\n }\n const block = state.content[state.content.length - 1];\n if (block?.type !== \"text\") continue;\n block.text += part.text;\n onEvent?.({ type: \"text_delta\", contentIndex: state.content.length - 1, delta: part.text });\n }\n }\n}\n\nfunction feedChunk(\n chunk: string,\n state: StreamParserState,\n onEvent?: (ev: StreamDeliveryEvent) => void,\n): void {\n state.buffer += chunk;\n const lines = state.buffer.split(\"\\n\");\n state.buffer = lines.pop() || \"\";\n for (const line of lines) {\n processLine(line, state, onEvent);\n }\n}\n\nfunction finishStream(\n state: StreamParserState,\n onEvent?: (ev: StreamDeliveryEvent) => void,\n): void {\n if (state.buffer.trim() !== \"\") {\n processLine(state.buffer, state, onEvent);\n }\n state.buffer = \"\";\n closeOpenBlock(state, onEvent);\n attachLoneSignature(state.content, state.lastThoughtSignature);\n}\n\n/**\n * Pure parsing seam for whole or chunked SSE wire responses (fixtures, replay, tests).\n * Replaces the shallow createSseFeed adapter with direct response decoding.\n */\nexport function parseAntigravitySseResponse(\n rawSse: string | Iterable<string>,\n onEvent?: (ev: StreamDeliveryEvent) => void,\n): ParsedStreamResult {\n const state: StreamParserState = {\n content: [],\n usage: { input: 0, output: 0, cacheRead: 0, reasoning: 0, total: 0 },\n stopReason: \"stop\",\n openType: null,\n buffer: \"\",\n };\n\n if (typeof rawSse === \"string\") {\n feedChunk(rawSse, state, onEvent);\n } else {\n for (const chunk of rawSse) {\n feedChunk(chunk, state, onEvent);\n }\n }\n finishStream(state, onEvent);\n\n return {\n content: state.content,\n usage: state.usage,\n stopReason: state.stopReason,\n responseId: state.responseId,\n };\n}\n\nasync function consumeAntigravityStream(\n streamBody: ReadableStream<Uint8Array>,\n output: AssistantMessage,\n stream: AssistantMessageEventStream,\n modelCost?: Model<any>[\"cost\"],\n): Promise<void> {\n const state: StreamParserState = {\n content: output.content,\n usage: { input: 0, output: 0, cacheRead: 0, reasoning: 0, total: 0 },\n stopReason: \"stop\",\n openType: null,\n buffer: \"\",\n };\n\n const updateUsageAndCost = () => {\n output.usage.input = state.usage.input;\n output.usage.cacheRead = state.usage.cacheRead;\n output.usage.output = state.usage.output;\n output.usage.reasoning = state.usage.reasoning;\n output.usage.totalTokens = state.usage.total;\n\n if (modelCost) {\n const inputCost = (output.usage.input * (modelCost.input || 0)) / 1_000_000;\n const outputCost = (output.usage.output * (modelCost.output || 0)) / 1_000_000;\n const cacheCost = (output.usage.cacheRead * (modelCost.cacheRead || 0)) / 1_000_000;\n output.usage.cost = {\n input: inputCost,\n output: outputCost,\n cacheRead: cacheCost,\n cacheWrite: 0,\n total: inputCost + outputCost + cacheCost,\n };\n }\n if (state.responseId) {\n output.responseId ||= state.responseId;\n }\n output.stopReason = state.stopReason;\n };\n\n const dispatchEvent = (ev: StreamDeliveryEvent) => {\n updateUsageAndCost();\n stream.push({ ...ev, partial: output });\n };\n\n const reader = streamBody.getReader();\n const decoder = new TextDecoder();\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n feedChunk(decoder.decode(value, { stream: true }), state, dispatchEvent);\n }\n\n finishStream(state, dispatchEvent);\n updateUsageAndCost();\n}\n\n/**\n * Stream Delivery Module: the deep module encapsulating wire byte streaming,\n * incremental SSE decoding, usage accounting, Thought Signature placement,\n * and direct Pi AssistantMessageEventStream dispatch.\n */\nexport function streamAntigravity(\n model: Model<any>,\n context: TranscriptContext,\n options: SimpleStreamOptions | undefined,\n catalog: ModelCatalog,\n): AssistantMessageEventStream {\n const stream = createAssistantMessageEventStream();\n\n (async () => {\n const output: AssistantMessage = {\n role: \"assistant\",\n content: [],\n api: model.api,\n provider: model.provider,\n model: model.id,\n usage: {\n input: 0,\n output: 0,\n cacheRead: 0,\n cacheWrite: 0,\n totalTokens: 0,\n cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n },\n stopReason: \"pending\",\n timestamp: Date.now(),\n };\n\n try {\n stream.push({ type: \"start\", partial: output });\n\n const { token, projectId } = await requireCredentials(options);\n\n const effort = options?.reasoning;\n // trajectoryId is provider-specific (absent from the SDK options\n // type), so read it via runtime-checked `in` narrowing instead of a cast.\n const trajectoryId =\n options && \"trajectoryId\" in options && typeof options.trajectoryId === \"string\"\n ? options.trajectoryId\n : undefined;\n const plan = catalog.resolvePlan(model.id, effort);\n\n const requestBody = buildAntigravityRequestBody({\n projectId,\n plan,\n context,\n sessionId: options?.sessionId,\n trajectoryId,\n maxOutputTokens: options?.maxTokens ?? model.maxTokens,\n toolChoice: options?.toolChoice,\n });\n\n const streamBody = await postAntigravityStream({\n auth: token,\n path: \"v1internal:streamGenerateContent?alt=sse\",\n body: requestBody,\n signal: options?.signal,\n });\n\n await consumeAntigravityStream(streamBody, output, stream, model.cost);\n\n const doneReason: \"stop\" | \"toolUse\" | \"length\" =\n output.stopReason === \"toolUse\" || output.stopReason === \"length\"\n ? output.stopReason\n : \"stop\";\n\n stream.push({\n type: \"done\",\n reason: doneReason,\n message: output,\n });\n stream.end();\n } catch (error) {\n output.stopReason = options?.signal?.aborted ? \"aborted\" : \"error\";\n output.errorMessage = error instanceof Error ? error.message : String(error);\n stream.push({ type: \"error\", reason: output.stopReason, error: output });\n stream.end();\n }\n })();\n\n return stream;\n}\n", "import { createHash, randomUUID } from \"node:crypto\";\nimport {\n collapseSystemMessages,\n getCurrentSystemPrompt,\n getCurrentTools,\n normalizeContext,\n withoutInitialSystemMessage,\n type TranscriptContext,\n} from \"@earendil-works/pi-ai\";\n// Load-bearing: re-exported for private/ tests without requiring private/node_modules\nexport { normalizeContext };\nimport type { ModelPlan } from \"./model-catalog.ts\";\nimport { classifyModelFamily, isCompatibleFamily } from \"./model-identity.ts\";\nimport { PROVIDER_ID } from \"./protocol.ts\";\n\nexport interface BuildRequestBodyParams {\n projectId: string;\n plan: ModelPlan;\n context: TranscriptContext;\n sessionId?: string;\n trajectoryId?: string;\n maxOutputTokens?: number;\n toolChoice?: string;\n}\n\nconst BASE64_SIGNATURE_PATTERN = /^[A-Za-z0-9+/_-]+={0,2}$/;\n\n/**\n * Gemini 3 rejects a `functionCall` part that carries no `thoughtSignature` while\n * it sits inside the current turn (validation covers \"all steps in the current\n * turn\"; a turn begins with the most recent user message that is not a\n * functionResponse) with 400 INVALID_ARGUMENT \"Function call is missing a\n * thought_signature in functionCall parts\". Dropping an unreplayable signature\n * (below) leaves exactly that state, and a cross-provider model switch mid-tool\n * turn is the everyday way to produce it: the other provider's tool call has no\n * signature to replay, and it is the pending step of the current turn.\n *\n * Google documents one escape hatch for `functionCall` parts \"that were not\n * generated by the API ... for example, when transferring history from a model\n * that does not include thought signatures\" \u2014 the literal sentinel below, which\n * trades that call's reasoning continuity (it is gone either way) for a request\n * the backend accepts.\n *\n * Live probe validation (gemini-3.8-flash-low): unsigned foreign functionCall as the pending step\n * of the current turn \u2192 400 with the message above; the identical body with this\n * sentinel on that single part \u2192 200.\n *\n * Applied to foreign calls only. A signature we *should* have had \u2014\n * same provider and family, yet missing or unreadable (pipeline regression, damaged\n * session) \u2014 keeps failing loudly with the 400 above instead of being papered over,\n * so a lost signature stays visible as a bug rather than silently degrading the\n * model's reasoning for that call.\n */\nexport const SKIP_THOUGHT_SIGNATURE_VALIDATOR = \"skip_thought_signature_validator\";\n\n/**\n * Verifies that a thought signature candidate is a valid base64 string suitable\n * for Google Protobuf TYPE_BYTES fields in JSON mapping.\n */\nfunction isValidThoughtSignature(sig: unknown): sig is string {\n if (typeof sig !== \"string\" || sig.length === 0) return false;\n if (sig.includes(\"=\") && sig.length % 4 !== 0) return false;\n return BASE64_SIGNATURE_PATTERN.test(sig);\n}\n\n/**\n * Resolves a thoughtSignature candidate only when coming from the same provider and\n * compatible model family, and only when formatted as valid base64.\n */\nfunction resolveThoughtSignature(\n isSameProviderAndModel: boolean,\n sig: unknown\n): string | undefined {\n if (!isSameProviderAndModel) return undefined;\n return isValidThoughtSignature(sig) ? sig : undefined;\n}\n\n/**\n * Deterministically derives a persistent session ID from the initial conversation turn.\n */\nfunction deriveSessionId(\n conversation: Array<any>,\n explicitSessionId?: string\n): string {\n if (explicitSessionId && typeof explicitSessionId === \"string\" && explicitSessionId.trim().length > 0) {\n return explicitSessionId.trim();\n }\n\n const firstMsg = conversation?.[0];\n if (!firstMsg) {\n return randomUUID();\n }\n\n const seedContent =\n typeof firstMsg.content === \"string\"\n ? firstMsg.content\n : JSON.stringify(firstMsg.content || \"\");\n\n const hash = createHash(\"sha256\")\n .update(`antigravity:conversation:${seedContent}`)\n .digest()\n .subarray(0, 16);\n\n hash[6] = (hash[6] & 0x0f) | 0x40; // v4 UUID\n hash[8] = (hash[8] & 0x3f) | 0x80;\n const hex = [...hash].map((b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;\n}\n\n/**\n * Computes deterministic v5 UUID trajectory ID from the session ID.\n */\nfunction resolveSessionTrajectory(sessionId: string): string {\n const bytes = createHash(\"sha1\").update(`antigravity:${sessionId}`).digest().subarray(0, 16);\n bytes[6] = (bytes[6] & 0x0f) | 0x50; // v5 UUID\n bytes[8] = (bytes[8] & 0x3f) | 0x80;\n const hex = [...bytes].map((b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;\n}\n\n/**\n * Signed 64-bit `request.sessionId`. Constant in the wire protocol specification \u2014 no\n * conversation/account input.\n */\nconst DEFAULT_SESSION_ID = \"-3750763034362895579\";\n\n/**\n * Pure-numeric session IDs (`stream.ts` override) pass through verbatim.\n */\nfunction resolveNumericSessionId(sessionId: string): string {\n if (/^-?\\d+$/.test(sessionId)) {\n return sessionId;\n }\n return DEFAULT_SESSION_ID;\n}\n\n/**\n * Normalizes tool call IDs for cross-provider compatibility.\n */\nfunction normalizeToolCallId(id: string | undefined): string | undefined {\n if (!id || typeof id !== \"string\") return id;\n return id.replace(/[^a-zA-Z0-9_-]/g, \"_\").slice(0, 64);\n}\n\nconst CUSTOM_TOOL_SCHEMA_ALLOW = new Set([\n \"type\",\n \"description\",\n \"properties\",\n \"required\",\n \"items\",\n \"enum\",\n]);\n\nfunction stripMetaSchema(schema: unknown): unknown {\n if (!schema || typeof schema !== \"object\" || Array.isArray(schema)) return schema;\n const omit = new Set([\"$schema\", \"$id\", \"$defs\", \"definitions\"]);\n const out: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(schema)) {\n if (!omit.has(key)) out[key] = stripMetaSchema(value);\n }\n return out;\n}\n\nfunction normalizeCustomToolSchema(schema: unknown): unknown {\n if (!schema || typeof schema !== \"object\") return schema;\n if (Array.isArray(schema)) return schema.map(normalizeCustomToolSchema);\n\n const s = schema as Record<string, unknown>;\n const out: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(s)) {\n if (!CUSTOM_TOOL_SCHEMA_ALLOW.has(key)) {\n // Map string const to single-item enum for Claude bridge compatibility\n if (key === \"const\" && s.enum === undefined && typeof value === \"string\") {\n out.enum = [value];\n }\n continue;\n }\n if (key === \"type\" && Array.isArray(value)) {\n const scalar = value.find((e) => typeof e === \"string\" && e !== \"null\");\n if (scalar) out.type = scalar;\n continue;\n }\n if (key === \"properties\" && value && typeof value === \"object\" && !Array.isArray(value)) {\n const props: Record<string, unknown> = {};\n for (const [propName, propSchema] of Object.entries(value as Record<string, unknown>)) {\n props[propName] = normalizeCustomToolSchema(propSchema);\n }\n out.properties = props;\n continue;\n }\n if (key === \"enum\" && Array.isArray(value) && !value.every((e) => typeof e === \"string\")) {\n continue;\n }\n out[key] = normalizeCustomToolSchema(value);\n }\n return out;\n}\n\n/**\n * Strict wire compatibility: declarations use legacy\n * `parameters`, never `parametersJsonSchema` \u2014 for Gemini\n * and non-Gemini models alike. Declarations also carry no\n * anyOf/patternProperties/const keys, hence the normalization below.\n */\nfunction convertTools(\n tools: Array<any> | undefined\n): Array<{ functionDeclarations: Array<any> }> | undefined {\n if (!tools?.length) return undefined;\n return [\n {\n functionDeclarations: tools.map((tool) => {\n const schema = stripMetaSchema(tool.parameters) || { type: \"object\", properties: {} };\n return {\n name: tool.name,\n description: tool.description,\n parameters: normalizeCustomToolSchema(schema),\n };\n }),\n },\n ];\n}\n\n/**\n * Translates a conversation turn trace into Antigravity wire contents.\n */\nfunction translateTurnTrace(\n conversation: Array<any>,\n runtimeModelId: string\n): Array<any> {\n const contents: Array<any> = [];\n const messages = conversation || [];\n\n // The sentinel is Gemini-specific evidence: the probe shows a Claude runtime model\n // accepts the same unsigned foreign functionCall with no sentinel at all (and merely\n // tolerates the sentinel), so Claude/GPT requests keep today's shape.\n const isGeminiRequest = classifyModelFamily(runtimeModelId) === \"gemini\";\n // GPT requests carry no reasoning history on the wire: a replay sends\n // the response as plain text only, no thought part and no signature.\n // Gemini and Claude both replay reasoning, so a gpt request drops the\n // block instead of serializing it.\n const isGptRequest = classifyModelFamily(runtimeModelId) === \"gpt\";\n\n for (const msg of messages) {\n if (msg.role === \"user\") {\n const parts: Array<any> = [];\n if (typeof msg.content === \"string\") {\n parts.push({ text: msg.content });\n } else if (Array.isArray(msg.content)) {\n for (const item of msg.content) {\n if (item.type === \"text\") {\n parts.push({ text: item.text });\n } else if (item.type === \"image\") {\n parts.push({\n inlineData: {\n mimeType: item.mimeType || \"image/png\",\n data: item.data,\n },\n });\n }\n }\n }\n if (parts.length > 0) {\n contents.push({ role: \"user\", parts });\n }\n } else if (msg.role === \"assistant\") {\n if (msg.stopReason === \"error\" || msg.stopReason === \"aborted\") {\n continue;\n }\n\n const isSameProvider = !msg.provider || msg.provider === PROVIDER_ID;\n const isSameModel = isCompatibleFamily(msg.model, runtimeModelId);\n const isSameProviderAndModel = isSameProvider && isSameModel;\n\n const parts: Array<any> = [];\n // Canonical wire shape: a thinking replay never carries its\n // own signature \u2014 it stays pending and rides on the NEXT text/functionCall\n // part. Only when the turn ends with no carrying part does it fall back\n // onto the last part (uncovered edge, same as the message-level fallback).\n // Signature fields are canonical SDK spellings only (textSignature /\n // thinkingSignature on blocks, thoughtSignature on toolCalls). No\n // legacy-spelling reads: pre-#26 sessions are abandoned (see #26).\n let pendingThinkingSig: string | undefined;\n if (typeof msg.content === \"string\") {\n parts.push({ text: msg.content });\n } else if (Array.isArray(msg.content)) {\n for (const item of msg.content) {\n if (item.type === \"text\") {\n if (typeof item.text !== \"string\" || item.text === \"\") {\n // Vacuous text block (e.g. a leading empty part the live feed\n // opened): drop the part but keep a valid signature pending\n // for the next part carrying one, mirroring the precedence\n // below. The Claude backend rejects {\"text\": \"\"} with 400\n // (text.text: Field required, observed live on multi-turn\n // replay); Gemini accepts the same payload (probed 200), but\n // an empty part carries nothing either way, and the wire never\n // emits one, so this stays regardless of model family.\n pendingThinkingSig =\n resolveThoughtSignature(isSameProviderAndModel, item.textSignature) ||\n pendingThinkingSig;\n continue;\n }\n const part: any = { text: item.text };\n const sig =\n resolveThoughtSignature(\n isSameProviderAndModel,\n item.textSignature\n ) || pendingThinkingSig;\n if (sig) {\n part.thoughtSignature = sig;\n pendingThinkingSig = undefined;\n }\n parts.push(part);\n } else if (item.type === \"thinking\") {\n const candidateSig = item.thinkingSignature;\n const isForeignReasoning =\n !isSameProviderAndModel ||\n (typeof candidateSig === \"string\" && candidateSig.trim().startsWith(\"{\"));\n\n // Same-family gpt reasoning is dropped, not serialized: the wire has no\n // shape for it. Foreign reasoning keeps the\n // context-preserving text fallback below, which has no single-provider counterpart.\n if (isGptRequest && !isForeignReasoning) continue;\n\n if (!isForeignReasoning) {\n // No thoughtSignature here by design: it stays pending for the\n // next text/functionCall part (canonical wire part-split shape).\n const part: any = {\n thought: true,\n text: item.thinking || \"\",\n };\n const sig = resolveThoughtSignature(true, candidateSig);\n if (sig) {\n pendingThinkingSig = sig;\n }\n parts.push(part);\n } else {\n // Cross-provider/model or foreign reasoning item: drop foreign signature and\n // serialize reasoning text (or summary) as plain text so the model retains\n // conversation context without failing Google's TYPE_BYTES base64 validation.\n let text = item.thinking || \"\";\n if (!text && typeof candidateSig === \"string\" && candidateSig.trim().startsWith(\"{\")) {\n try {\n const parsed = JSON.parse(candidateSig);\n if (Array.isArray(parsed.summary)) {\n text = parsed.summary\n .filter((s: any) => s && typeof s.text === \"string\")\n .map((s: any) => s.text)\n .join(\"\\n\");\n }\n } catch {\n // Ignore JSON parse errors\n }\n }\n if (text && text.trim() !== \"\") {\n parts.push({ text });\n }\n }\n } else if (item.type === \"tool_use\" || item.type === \"toolCall\") {\n const part: any = {\n functionCall: {\n id: normalizeToolCallId(item.id),\n name: item.name,\n args: item.input || item.arguments || {},\n },\n };\n const sig =\n resolveThoughtSignature(\n isSameProviderAndModel,\n item.thoughtSignature\n ) || pendingThinkingSig;\n if (sig) {\n part.thoughtSignature = sig;\n pendingThinkingSig = undefined;\n } else if (isGeminiRequest && !isSameProviderAndModel) {\n part.thoughtSignature = SKIP_THOUGHT_SIGNATURE_VALIDATOR;\n }\n parts.push(part);\n }\n }\n }\n if (parts.length > 0) {\n if (pendingThinkingSig && !parts.some((p) => p.thoughtSignature)) {\n parts[parts.length - 1].thoughtSignature = pendingThinkingSig;\n }\n contents.push({ role: \"model\", parts });\n }\n } else if (msg.role === \"toolResult\") {\n let toolName = msg.toolName || msg.name;\n if (!toolName && (msg.toolCallId || msg.id)) {\n const rawTargetId = msg.toolCallId || msg.id;\n const normTargetId = normalizeToolCallId(rawTargetId);\n for (const prev of messages) {\n if (prev.role === \"assistant\" && Array.isArray(prev.content)) {\n const found = prev.content.find(\n (c: any) =>\n (c.type === \"tool_use\" || c.type === \"toolCall\") &&\n (c.id === rawTargetId || normalizeToolCallId(c.id) === normTargetId)\n );\n if (found) {\n toolName = found.name;\n break;\n }\n }\n }\n }\n\n let toolText = \"\";\n const imageParts: Array<any> = [];\n\n if (Array.isArray(msg.content)) {\n const textParts: string[] = [];\n for (const c of msg.content) {\n if (typeof c === \"string\") {\n textParts.push(c);\n } else if (c.type === \"text\") {\n textParts.push(c.text);\n } else if (c.type === \"image\") {\n imageParts.push({\n inlineData: {\n mimeType: c.mimeType || \"image/png\",\n data: c.data,\n },\n });\n } else {\n textParts.push(JSON.stringify(c));\n }\n }\n toolText = textParts.join(\"\\n\");\n } else if (typeof msg.content === \"string\") {\n toolText = msg.content;\n } else if (msg.content) {\n toolText = JSON.stringify(msg.content);\n }\n\n // Strict wire parity:\n // - response is always { output: string }, never a top-level list.\n // - error tool results also use the \"output\" key.\n const responseObj = { output: toolText };\n\n const functionResponse: any = {\n name: toolName || \"tool\",\n response: responseObj,\n };\n\n const rawCallId = msg.toolCallId || msg.id;\n const callId = normalizeToolCallId(rawCallId);\n if (callId) {\n functionResponse.id = callId;\n }\n\n if (imageParts.length > 0) {\n functionResponse.parts = imageParts;\n }\n\n contents.push({\n role: \"model\",\n parts: [{ functionResponse }],\n });\n }\n }\n\n // Antigravity rejects requests ending with an incomplete model turn.\n if (contents.length > 0) {\n const lastContent = contents[contents.length - 1];\n if (\n lastContent.role === \"model\" &&\n !lastContent.parts?.some((p: any) => p.functionResponse)\n ) {\n contents.push({\n role: \"user\",\n parts: [{ text: \"continue\" }],\n });\n }\n }\n\n return contents;\n}\n\n/**\n * Builds the complete Antigravity Wire Fingerprint request envelope.\n * Encapsulates session identity derivation, Thought Signature replay,\n * Turn Trace translation, and tool schema normalization.\n */\nexport function buildAntigravityRequestBody(params: BuildRequestBodyParams): Record<string, any> {\n const {\n projectId,\n plan,\n context,\n maxOutputTokens = 65536,\n } = params;\n const runtimeModelId = plan.runtimeModelId;\n\n // Pi 0.86: System prompt and tool declarations live in the transcript's system messages.\n const transcript = collapseSystemMessages(context);\n const systemPrompt = getCurrentSystemPrompt(transcript.messages);\n const tools = convertTools(getCurrentTools(transcript.messages));\n const conversation = withoutInitialSystemMessage(transcript.messages);\n\n const sessionId = deriveSessionId(conversation, params.sessionId);\n const trajectoryId =\n params.trajectoryId && typeof params.trajectoryId === \"string\" && params.trajectoryId.trim().length > 0\n ? params.trajectoryId.trim()\n : resolveSessionTrajectory(sessionId);\n const contents = translateTurnTrace(conversation, runtimeModelId);\n\n // Request ID sequence increments by completed assistant turns **as carried by\n // this request**: derive it from the payload, so a turn the translation drops\n // (stopReason error/aborted, empty content, all-empty parts) can never desync\n // the label from `contents` \u2014 matches the wire protocol specification.\n const requestIndex = contents.filter(\n (c) => c.role === \"model\" && !c.parts?.some((p: any) => p.functionResponse)\n ).length;\n const requestId = `agent/${sessionId}/${Date.now()}/${trajectoryId}/${contents.length}`;\n\n const modelEnum = plan.modelEnum;\n\n const labels: Record<string, string> = {\n last_step_index: String(Math.max(0, contents.length - 1)),\n model_enum: modelEnum,\n request_id: `${trajectoryId}-${requestIndex}`,\n trajectory_id: trajectoryId,\n used_claude: String(plan.isClaude),\n used_claude_conservative: String(plan.isClaude),\n used_non_gemini_model: String(plan.isNonGemini),\n };\n\n const generationConfig: Record<string, any> = {\n maxOutputTokens,\n thinkingConfig: plan.thinkingConfig,\n };\n\n const request: Record<string, any> = {\n contents,\n };\n\n if (systemPrompt) {\n request.systemInstruction = {\n role: \"user\",\n parts: [{ text: systemPrompt }],\n };\n }\n\n if (tools) {\n request.tools = tools;\n }\n\n if (params.toolChoice && params.toolChoice !== \"auto\" && params.toolChoice !== \"Auto\") {\n let mode = \"AUTO\";\n const tc = String(params.toolChoice).toLowerCase();\n if (tc === \"none\") mode = \"NONE\";\n else if (tc === \"any\" || tc === \"required\") mode = \"ANY\";\n request.toolConfig = {\n functionCallingConfig: {\n mode,\n },\n };\n }\n\n request.labels = labels;\n request.generationConfig = generationConfig;\n request.sessionId = resolveNumericSessionId(sessionId);\n\n return {\n project: projectId,\n requestId,\n request,\n model: runtimeModelId,\n userAgent: \"antigravity\",\n requestType: \"agent\",\n };\n}\n", "import { postAntigravityJson } from \"./protocol.ts\";\nimport { FALLBACK_PROJECT_ID, type AntigravityCredentials } from \"./auth.ts\";\n\nexport interface WebSearchOptions {\n query: string;\n domain?: string;\n signal?: AbortSignal;\n}\n\nexport interface GroundingChunk {\n web?: {\n uri: string;\n title: string;\n };\n}\n\nexport interface GroundingSupport {\n segment?: {\n startIndex?: number;\n endIndex?: number;\n text?: string;\n };\n groundingChunkIndices?: number[];\n}\n\nexport interface GroundingMetadata {\n webSearchQueries?: string[];\n searchEntryPoint?: {\n renderedContent?: string;\n };\n groundingChunks?: GroundingChunk[];\n groundingSupports?: GroundingSupport[];\n}\n\nexport interface SearchCandidate {\n content?: {\n role: string;\n parts?: Array<{\n text?: string;\n thoughtSignature?: string;\n }>;\n };\n finishReason?: string;\n groundingMetadata?: GroundingMetadata;\n}\n\nexport interface SearchApiResponse {\n response?: {\n candidates?: SearchCandidate[];\n usageMetadata?: {\n promptTokenCount?: number;\n candidatesTokenCount?: number;\n totalTokenCount?: number;\n };\n modelVersion?: string;\n responseId?: string;\n };\n traceId?: string;\n metadata?: unknown;\n}\n\nexport interface SearchSource {\n index: number;\n title: string;\n url: string;\n}\n\nexport interface SearchResult {\n query: string;\n rawText: string;\n formattedOutput: string;\n sources: SearchSource[];\n queries: string[];\n createdAt: string;\n completedAt: string;\n}\n\nexport const SEARCH_SYSTEM_INSTRUCTION =\n \"You are a search engine bot. You will be given a query from a user. \" +\n \"Your task is to search the web for relevant information that will help the user. \" +\n \"You MUST perform a web search. Do not respond or interact with the user, \" +\n \"please respond as if they typed the query into a search bar.\";\n\nexport const SEARCH_MODEL = \"gemini-3.1-flash-lite\";\n\n/**\n * Annotates the raw text with inline citations [1][2] and appends Sources list,\n * matching agy CLI's exact Wire output shape.\n */\nexport function formatSearchResults(\n rawText: string,\n metadata: GroundingMetadata | undefined,\n query: string,\n createdAt: string,\n completedAt: string\n): SearchResult {\n const sources: SearchSource[] = (metadata?.groundingChunks || [])\n .map((chunk, i) => ({\n index: i + 1,\n title: chunk.web?.title || \"Web Source\",\n url: chunk.web?.uri || \"\",\n }))\n .filter((s) => Boolean(s.url));\n\n const queries = metadata?.webSearchQueries || [];\n\n let annotatedText = rawText;\n const supports = (metadata?.groundingSupports || [])\n .filter(\n (s): s is GroundingSupport & { segment: { endIndex: number } } =>\n typeof s.segment?.endIndex === \"number\" &&\n Array.isArray(s.groundingChunkIndices) &&\n s.groundingChunkIndices.length > 0\n )\n .slice()\n .sort((a, b) => (b.segment.endIndex ?? 0) - (a.segment.endIndex ?? 0));\n\n // Insert footnote citations from end to start so indices stay stable\n for (const sup of supports) {\n const end = sup.segment.endIndex;\n if (end >= 0 && end <= annotatedText.length) {\n const citations = (sup.groundingChunkIndices || [])\n .map((idx) => `[${idx + 1}]`)\n .join(\"\");\n annotatedText = annotatedText.slice(0, end) + citations + annotatedText.slice(end);\n }\n }\n\n const sourceLines = sources.map((s) => `[${s.index}] [${s.title}](${s.url})`);\n\n let formattedOutput =\n `Created At: ${createdAt}\\n` +\n `Completed At: ${completedAt}\\n` +\n `The search for \"${query}\" returned the following summary:\\n` +\n `${annotatedText.trim() || \"No content returned.\"}`;\n\n if (sourceLines.length > 0) {\n formattedOutput += `\\n\\nSources:\\n${sourceLines.join(\"\\n\")}`;\n }\n\n return {\n query,\n rawText,\n formattedOutput,\n sources,\n queries,\n createdAt,\n completedAt,\n };\n}\n\n/**\n * Executes a live Google Web Search with Search Grounding via Antigravity backend,\n * replicating agy CLI's native search_web tool call.\n */\nexport async function performWebSearch(\n creds: AntigravityCredentials,\n options: WebSearchOptions\n): Promise<SearchResult> {\n const createdAt = new Date().toISOString();\n let effectiveQuery = options.query.trim();\n if (options.domain && options.domain.trim()) {\n const d = options.domain.trim();\n if (!effectiveQuery.toLowerCase().includes(`site:${d.toLowerCase()}`)) {\n effectiveQuery = `${effectiveQuery} site:${d}`;\n }\n }\n\n const reqBody = {\n project: creds.projectId || FALLBACK_PROJECT_ID,\n request: {\n contents: [\n {\n role: \"user\",\n parts: [{ text: effectiveQuery }],\n },\n ],\n systemInstruction: {\n role: \"user\",\n parts: [{ text: SEARCH_SYSTEM_INSTRUCTION }],\n },\n tools: [\n {\n googleSearch: {\n enhancedContent: {\n imageSearch: {\n maxResultCount: 5,\n },\n },\n },\n },\n ],\n generationConfig: {\n candidateCount: 1,\n },\n },\n model: SEARCH_MODEL,\n userAgent: \"antigravity\",\n requestType: \"web_search\",\n };\n\n const resp = await postAntigravityJson<SearchApiResponse>({\n auth: creds.token,\n path: \"v1internal:generateContent\",\n body: reqBody,\n signal: options.signal,\n });\n\n const completedAt = new Date().toISOString();\n const candidate = resp.response?.candidates?.[0];\n const rawText =\n candidate?.content?.parts\n ?.filter((p) => typeof p.text === \"string\")\n .map((p) => p.text)\n .join(\"\") || \"\";\n const metadata = candidate?.groundingMetadata;\n\n return formatSearchResults(rawText, metadata, effectiveQuery, createdAt, completedAt);\n}\n", "import type { ExtensionCommandContext } from \"@earendil-works/pi-coding-agent\";\nimport { resolveCredentials, NOT_LOGGED_IN, type AntigravityCredentials } from \"./auth.ts\";\nimport { PROVIDER_ID } from \"./protocol.ts\";\nimport { openSettings } from \"./config.ts\";\nimport { type QuotaStatusCoordinator, registerQuotaSettings } from \"./quota-status.ts\";\nimport type { ModelCatalog } from \"./model-catalog.ts\";\nimport { performWebSearch } from \"./search.ts\";\n\nexport function emitOutput(\n ctx: ExtensionCommandContext,\n text: string,\n type: \"info\" | \"warning\" | \"error\" = \"info\",\n): void {\n if (ctx.hasUI) {\n ctx.ui.notify(text, type);\n } else {\n if (type === \"error\" || type === \"warning\") console.error(text);\n else console.log(text);\n }\n}\n\nexport interface SubcommandContext {\n ctx: ExtensionCommandContext;\n quotaStatus?: QuotaStatusCoordinator;\n catalog: ModelCatalog;\n subArgs?: string;\n}\n\nexport interface SubcommandDef {\n name: string;\n description: string;\n aliases?: readonly string[];\n run: (deps: SubcommandContext) => Promise<void> | void;\n}\n\nexport interface SubcommandCompletion {\n value: string;\n label: string;\n description: string;\n}\n\nexport const SUBCOMMANDS: readonly SubcommandDef[] = Object.freeze([\n {\n name: \"usage\",\n description: \"Show remaining 5h and weekly quota\",\n run: async ({ ctx, quotaStatus }) => runUsageSubcommand(ctx, quotaStatus),\n },\n {\n name: \"models\",\n description: \"List recommended models with context window and remaining quota\",\n aliases: Object.freeze([\"model\"]),\n run: async ({ ctx, catalog }) => runModelsSubcommand(ctx, catalog),\n },\n {\n name: \"refresh\",\n description: \"Fetch the latest model list\",\n run: async ({ ctx, catalog }) => runRefreshSubcommand(ctx, catalog),\n },\n {\n name: \"settings\",\n description: \"Configure provider settings\",\n aliases: Object.freeze([\"setting\"]),\n run: async ({ ctx, quotaStatus }) => {\n if (quotaStatus) registerQuotaSettings(quotaStatus);\n await openSettings(ctx);\n },\n },\n {\n name: \"websearch\",\n description: \"Search the web using Google Search Grounding\",\n run: async ({ ctx, subArgs }) => runSearchSubcommand(ctx, subArgs),\n },\n {\n name: \"login\",\n description: \"Run /login antigravity\",\n run: ({ ctx }) => runLoginSubcommand(ctx),\n },\n]);\n\nexport function buildUsageText(commands: readonly SubcommandDef[] = SUBCOMMANDS): string {\n const maxNameLen = Math.max(...commands.map((c) => c.name.length));\n const lines = commands.map((c) => {\n const aliasPart = c.aliases?.length ? ` (alias: ${c.aliases.join(\", \")})` : \"\";\n return ` ${c.name.padEnd(maxNameLen)} ${c.description}${aliasPart}`;\n });\n return `Usage: /antigravity <command>\\n\\nCommands:\\n${lines.join(\"\\n\")}`;\n}\n\nexport const USAGE_TEXT = buildUsageText();\n\nexport function completeSubcommands(\n prefix: string,\n commands: readonly SubcommandDef[] = SUBCOMMANDS,\n): SubcommandCompletion[] | null {\n const trimmed = prefix.trim();\n if (trimmed === \"\") {\n return commands.map((s) => ({ value: s.name, label: s.name, description: s.description }));\n }\n if (/\\s/.test(trimmed)) return null;\n const lower = trimmed.toLowerCase();\n return commands\n .filter((s) => s.name.startsWith(lower))\n .map((s) => ({\n value: s.name,\n label: s.name,\n description: s.description,\n }));\n}\n\nexport function parseAntigravitySubcommand(\n args: string,\n commands: readonly SubcommandDef[] = SUBCOMMANDS,\n): string {\n const sub = (args || \"\").trim().toLowerCase();\n for (const cmd of commands) {\n if (cmd.name === sub || cmd.aliases?.includes(sub)) {\n return cmd.name;\n }\n }\n return sub;\n}\n\nexport async function resolveToken(\n ctx: ExtensionCommandContext\n): Promise<AntigravityCredentials | null> {\n return resolveCredentials(ctx);\n}\n\nasync function runModelsSubcommand(ctx: ExtensionCommandContext, catalog: ModelCatalog): Promise<void> {\n if ((await resolveCredentials(ctx)) === null) {\n emitOutput(ctx, NOT_LOGGED_IN, \"warning\");\n return;\n }\n try {\n if (ctx.hasUI) ctx.ui.notify(\"Fetching available models\u2026\", \"info\");\n // Single Model Catalog path: freshness lives behind the catalog seam \u2014\n // this module only branches on the verdict and prints.\n const { status, catalog: items } = await catalog.refreshGeneration(() =>\n ctx.modelRegistry?.refresh?.({ force: true, providers: [PROVIDER_ID], signal: ctx.signal }),\n );\n if (status === \"failed\" || !items) {\n throw new Error(\"no models were returned\");\n }\n if (status === \"stale\") {\n // Refresh failed: say so, but still show the retained generation \u2014\n // a stale list beats no list, as long as it is labeled.\n emitOutput(ctx, \"Failed to refresh models; showing last known list.\", \"warning\");\n emitOutput(ctx, catalog.formatList());\n return;\n }\n emitOutput(ctx, catalog.formatList());\n } catch (err: any) {\n emitOutput(ctx, `Failed to fetch models: ${err.message}`, \"error\");\n }\n}\n\nasync function runUsageSubcommand(\n ctx: ExtensionCommandContext,\n quotaStatus?: QuotaStatusCoordinator,\n): Promise<void> {\n if ((await resolveCredentials(ctx)) === null) {\n emitOutput(ctx, NOT_LOGGED_IN, \"warning\");\n return;\n }\n if (!quotaStatus) {\n emitOutput(ctx, \"Quota status is unavailable.\", \"error\");\n return;\n }\n try {\n if (ctx.hasUI) ctx.ui.notify(\"Fetching quota summary\u2026\", \"info\");\n const text = await quotaStatus.inspectUsage(ctx);\n emitOutput(ctx, text);\n } catch (err: any) {\n emitOutput(ctx, `Failed to fetch usage: ${err.message}`, \"error\");\n }\n}\n\nasync function runRefreshSubcommand(ctx: ExtensionCommandContext, catalog: ModelCatalog): Promise<void> {\n try {\n if (ctx.hasUI) ctx.ui.notify(\"Refreshing models\u2026\", \"info\");\n const { status } = await catalog.refreshGeneration(() =>\n ctx.modelRegistry?.refresh?.({ force: true, providers: [PROVIDER_ID], signal: ctx.signal }),\n );\n if (status === \"fresh\") {\n emitOutput(ctx, \"Antigravity models refreshed successfully.\");\n } else if (status === \"stale\") {\n emitOutput(ctx, \"Failed to refresh models; keeping last known list.\", \"warning\");\n } else {\n emitOutput(ctx, \"Failed to refresh models: no models were returned.\", \"error\");\n }\n } catch (err: any) {\n emitOutput(ctx, `Failed to refresh: ${err.message}`, \"error\");\n }\n}\n\nfunction runLoginSubcommand(ctx: ExtensionCommandContext): void {\n if (ctx.hasUI) {\n ctx.ui.setEditorText(\"/login antigravity\");\n ctx.ui.notify(\"Press Enter to log in to Antigravity.\", \"info\");\n } else {\n emitOutput(ctx, \"Please run /login antigravity to authenticate.\");\n }\n}\n\nasync function runSearchSubcommand(\n ctx: ExtensionCommandContext,\n query?: string,\n): Promise<void> {\n const creds = await resolveCredentials(ctx);\n if (!creds) {\n emitOutput(ctx, NOT_LOGGED_IN, \"warning\");\n return;\n }\n\n const trimmedQuery = (query || \"\").trim();\n if (!trimmedQuery) {\n emitOutput(ctx, \"Usage: /antigravity websearch <query>\", \"warning\");\n return;\n }\n\n try {\n if (ctx.hasUI) ctx.ui.notify(`Searching: \"${trimmedQuery}\"\u2026`, \"info\");\n const result = await performWebSearch(creds, {\n query: trimmedQuery,\n signal: ctx.signal,\n });\n emitOutput(ctx, result.formattedOutput);\n } catch (err: any) {\n emitOutput(ctx, `Search failed: ${err.message}`, \"error\");\n }\n}\n\nexport async function runAntigravitySubcommand(\n args: string,\n ctx: ExtensionCommandContext,\n quotaStatus: QuotaStatusCoordinator | undefined,\n catalog: ModelCatalog,\n): Promise<void> {\n const raw = (args || \"\").trim();\n const parts = raw.split(/\\s+/).filter(Boolean);\n const sub = parseAntigravitySubcommand(parts[0] || \"\");\n const subArgs = raw.slice(parts[0]?.length || 0).trim();\n const cmd = SUBCOMMANDS.find((c) => c.name === sub);\n if (cmd) {\n await cmd.run({ ctx, quotaStatus, catalog, subArgs });\n return;\n }\n\n emitOutput(ctx, USAGE_TEXT);\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["path", "createHash", "createHash"]
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-provider-antigravity",
3
- "version": "0.13.0",
3
+ "version": "0.14.0",
4
4
  "description": "Minimal Antigravity provider for Pi Coding Agent",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -33,14 +33,14 @@
33
33
  ]
34
34
  },
35
35
  "peerDependencies": {
36
- "@earendil-works/pi-ai": ">=0.80.0",
37
- "@earendil-works/pi-coding-agent": ">=0.80.0",
38
- "@earendil-works/pi-tui": ">=0.80.0"
36
+ "@earendil-works/pi-ai": ">=0.86.0",
37
+ "@earendil-works/pi-coding-agent": ">=0.86.0",
38
+ "@earendil-works/pi-tui": ">=0.86.0"
39
39
  },
40
40
  "devDependencies": {
41
- "@earendil-works/pi-ai": "^0.85.0",
42
- "@earendil-works/pi-coding-agent": "^0.85.0",
43
- "@earendil-works/pi-tui": "^0.85.1",
41
+ "@earendil-works/pi-ai": "^0.86.1",
42
+ "@earendil-works/pi-coding-agent": "^0.86.1",
43
+ "@earendil-works/pi-tui": "^0.86.1",
44
44
  "@types/node": "^26.4.1",
45
45
  "esbuild": "^0.28.2",
46
46
  "typescript": "^7.0.2"