@eddyskywalker/dsh-chatgpt-subscription 0.64.1 → 0.65.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/CHANGELOG.md +28 -0
- package/lib/client.js.map +1 -1
- package/lib/index.js +451 -62
- package/lib/types/compat.d.ts +1 -1
- package/lib/types/host/antigravity/adapter.d.ts.map +1 -1
- package/lib/types/host/antigravity/client-version.d.ts +55 -0
- package/lib/types/host/antigravity/client-version.d.ts.map +1 -0
- package/lib/types/host/antigravity/client.d.ts +13 -1
- package/lib/types/host/antigravity/client.d.ts.map +1 -1
- package/lib/types/host/antigravity/image-tool.d.ts.map +1 -1
- package/lib/types/host/antigravity/mapper.d.ts.map +1 -1
- package/lib/types/host/antigravity/oauth.d.ts +9 -0
- package/lib/types/host/antigravity/oauth.d.ts.map +1 -1
- package/lib/types/host/antigravity/types.d.ts +52 -3
- package/lib/types/host/antigravity/types.d.ts.map +1 -1
- package/lib/types/host/proxy-manager.d.ts +87 -1
- package/lib/types/host/proxy-manager.d.ts.map +1 -1
- package/lib/types/index.d.ts.map +1 -1
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -19,12 +19,13 @@ import fs$1, { appendFileSync, constants as constants$1, copyFileSync, existsSyn
|
|
|
19
19
|
import http, { createServer } from "node:http";
|
|
20
20
|
import { WebError } from "@deepseek-ai/dsh-web";
|
|
21
21
|
import { lookup } from "node:dns/promises";
|
|
22
|
-
import { isIP } from "node:net";
|
|
22
|
+
import net, { isIP } from "node:net";
|
|
23
23
|
import { MAX_TIMER_DELAY_MS, idleWatchdog, timeoutOf } from "@deepseek-ai/dsh-timeout";
|
|
24
24
|
import { boundContextSummary, createUserMessage as createUserMessage$1 } from "@deepseek-ai/dsh-llm/message";
|
|
25
25
|
import * as SettingsModule from "@deepseek-ai/dsh-settings";
|
|
26
26
|
import { URL as URL$1, URLSearchParams as URLSearchParams$1, fileURLToPath } from "node:url";
|
|
27
|
-
import
|
|
27
|
+
import tls from "node:tls";
|
|
28
|
+
import { Agent, ProxyAgent, fetch as fetch$1 } from "undici";
|
|
28
29
|
import { setTimeout as setTimeout$1 } from "node:timers/promises";
|
|
29
30
|
import { gzipSync } from "node:zlib";
|
|
30
31
|
//#region src/shared/i18n-contracts.ts
|
|
@@ -808,7 +809,7 @@ const ROUTE_PREFIX$5 = "/api/dsh-chatgpt-subscription";
|
|
|
808
809
|
* `test/responses-client.test.ts` asserts the two agree, so a release that
|
|
809
810
|
* forgets this constant fails the suite instead of shipping quietly.
|
|
810
811
|
*/
|
|
811
|
-
const PLUGIN_VERSION = "0.
|
|
812
|
+
const PLUGIN_VERSION = "0.65.0";
|
|
812
813
|
const CODEX_CHATGPT_PROVIDER_ID = "codex-chatgpt";
|
|
813
814
|
const CODEX_API_BASE = "https://chatgpt.com/backend-api/codex";
|
|
814
815
|
const CODEX_RESPONSES_URL = `${CODEX_API_BASE}/responses`;
|
|
@@ -6521,6 +6522,28 @@ const ENDPOINT_FALLBACKS = ["https://daily-cloudcode-pa.googleapis.com", "https:
|
|
|
6521
6522
|
const FREE_TIER_ID = "free-tier";
|
|
6522
6523
|
const ONBOARD_TIMEOUT_MS = 3e4;
|
|
6523
6524
|
const ONBOARD_POLL_INTERVAL_MS = 1e3;
|
|
6525
|
+
/**
|
|
6526
|
+
* The two identity fields the Hub adds on `onboardUser` control-plane calls.
|
|
6527
|
+
*
|
|
6528
|
+
* Onboarding is not served by the same surface as inference: the Hub appends a
|
|
6529
|
+
* Node API client to its User-Agent there and states an X-Goog-Api-Client, while
|
|
6530
|
+
* content requests carry neither.
|
|
6531
|
+
*/
|
|
6532
|
+
const HUB_ONBOARD_UA_SUFFIX = "google-api-nodejs-client/10.3.0";
|
|
6533
|
+
const HUB_ONBOARD_API_CLIENT = "gl-node/22.21.1";
|
|
6534
|
+
/**
|
|
6535
|
+
* Headers the native Antigravity client never sends, but Node's fetch adds itself.
|
|
6536
|
+
*
|
|
6537
|
+
* `sec-fetch-mode` and `accept-language` are browser idioms: undici's `fetch` adds
|
|
6538
|
+
* them to every request and offers no way to suppress them, so the only seam is
|
|
6539
|
+
* the dispatcher underneath. The native client is a Go HTTP client and sends
|
|
6540
|
+
* neither, which makes them a shape difference an upstream can match on without
|
|
6541
|
+
* any TLS inspection.
|
|
6542
|
+
*
|
|
6543
|
+
* `connection: keep-alive` is deliberately NOT listed: undici's HTTP/1.1 writer
|
|
6544
|
+
* re-adds it regardless of what the dispatcher is handed.
|
|
6545
|
+
*/
|
|
6546
|
+
const ANTIGRAVITY_ABSENT_HEADERS = ["sec-fetch-mode", "accept-language"];
|
|
6524
6547
|
const REDIRECT_PATH = "/oauth-callback";
|
|
6525
6548
|
const AUTH_URL = "https://accounts.google.com/o/oauth2/v2/auth";
|
|
6526
6549
|
const TOKEN_URL = "https://oauth2.googleapis.com/token";
|
|
@@ -6534,8 +6557,16 @@ const SCOPES = [
|
|
|
6534
6557
|
];
|
|
6535
6558
|
const DEFAULT_CLIENT_ID = Buffer.from("MTA3MTAwNjA2MDU5MS10bWhzc2luMmgyMWxjcmUyMzV2dG9sb2poNGc0MDNlcC5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbQ==", "base64").toString("utf8");
|
|
6536
6559
|
const DEFAULT_CLIENT_SECRET = Buffer.from("R09DU1BYLUs1OEZXUjQ4NkxkTEoxbUxCOHNYQzR6NnFEQWY=", "base64").toString("utf8");
|
|
6537
|
-
|
|
6538
|
-
|
|
6560
|
+
/**
|
|
6561
|
+
* The Antigravity persona, as the native client states it.
|
|
6562
|
+
*
|
|
6563
|
+
* Only these two opening sentences are attested — they are the part captured
|
|
6564
|
+
* `language_server` traffic and the reference reimplementations quote. The
|
|
6565
|
+
* capture's tail is a truncated fragment (`**Absolute paths only****
|
|
6566
|
+
* Proactiveness**`), so nothing past these sentences is reconstructed here: a
|
|
6567
|
+
* guessed continuation would be one more thing only this route sends.
|
|
6568
|
+
*/
|
|
6569
|
+
const ANTIGRAVITY_SYSTEM_INSTRUCTION = "You are Antigravity, a powerful agentic AI coding assistant designed by the Google Deepmind team working on Advanced Agentic Coding. You are pair programming with a USER to solve their coding task.";
|
|
6539
6570
|
const GEMINI_ROLE = {
|
|
6540
6571
|
user: "user",
|
|
6541
6572
|
model: "model"
|
|
@@ -7210,15 +7241,137 @@ const DEFAULT_CALLBACK_PORT$2 = 51121;
|
|
|
7210
7241
|
* once per sign-in. The ordinary case stops at the first usable port.
|
|
7211
7242
|
*/
|
|
7212
7243
|
const CALLBACK_PORT_ATTEMPTS$2 = 1024;
|
|
7244
|
+
//#endregion
|
|
7245
|
+
//#region src/host/antigravity/client-version.ts
|
|
7246
|
+
/**
|
|
7247
|
+
* The Hub release this process reports to Cloud Code.
|
|
7248
|
+
*
|
|
7249
|
+
* The service gates its model catalogue and its Gemini quota buckets on the
|
|
7250
|
+
* client version in `User-Agent`, so a pinned constant silently ages into a
|
|
7251
|
+
* worse client: the same account sees fewer models and fewer quota buckets than
|
|
7252
|
+
* the official app on the same day. The Hub publishes the release it currently
|
|
7253
|
+
* ships in its updater manifest, which is what this module reads.
|
|
7254
|
+
*
|
|
7255
|
+
* The read is deliberately non-blocking. `defaultUserAgent()` is synchronous
|
|
7256
|
+
* and is called while a request is being built, so the process always has a
|
|
7257
|
+
* usable version to report: the built-in one until a manifest has been read,
|
|
7258
|
+
* the last known release after that. A manifest that cannot be read is not a
|
|
7259
|
+
* failure -- the reference reimplementations treat it the same way, because a
|
|
7260
|
+
* release that is one version old still serves requests.
|
|
7261
|
+
*
|
|
7262
|
+
* @see https://github.com/router-for-me/CLIProxyAPI — `internal/misc/antigravity_version.go`
|
|
7263
|
+
*/
|
|
7264
|
+
/** The Hub updater manifest for the arm64 macOS build. */
|
|
7265
|
+
const HUB_MANIFEST_URL = "https://antigravity-hub-auto-updater-974169037036.us-central1.run.app/manifest/latest-arm64-mac.yml";
|
|
7266
|
+
/**
|
|
7267
|
+
* The updater is an electron-builder client, and it says so when it reads its
|
|
7268
|
+
* own manifest. Sending the Hub User-Agent here would be this plugin's invention.
|
|
7269
|
+
*/
|
|
7270
|
+
const HUB_MANIFEST_USER_AGENT = "electron-builder";
|
|
7271
|
+
/**
|
|
7272
|
+
* Build changelists of known Hub releases: the `cl=` field of the User-Agent.
|
|
7273
|
+
*
|
|
7274
|
+
* A release with no entry here omits `cl=` instead of claiming another build's
|
|
7275
|
+
* changelist, which is what the official app does for a build it does not know.
|
|
7276
|
+
* `2.24.0` was read out of the official darwin-arm archive's build metadata; keep
|
|
7277
|
+
* the newest entry and {@link DEFAULT_ANTIGRAVITY_VERSION} in step.
|
|
7278
|
+
*/
|
|
7279
|
+
const HUB_RELEASE_CHANGELISTS = {
|
|
7280
|
+
"2.23.0": "998057262",
|
|
7281
|
+
"2.24.0": "1000335682",
|
|
7282
|
+
"2.29.0": "1013060670"
|
|
7283
|
+
};
|
|
7284
|
+
const MANIFEST_TIMEOUT_MS = 5e3;
|
|
7285
|
+
/** How long a read manifest is trusted before another read is attempted. */
|
|
7286
|
+
const MANIFEST_TTL_MS = 360 * 60 * 1e3;
|
|
7287
|
+
/** Retry cadence while no manifest has ever been read. */
|
|
7288
|
+
const MANIFEST_RETRY_MS = 1800 * 1e3;
|
|
7289
|
+
let discoveredVersion;
|
|
7290
|
+
let lastAttempt = 0;
|
|
7291
|
+
let inFlight;
|
|
7292
|
+
/**
|
|
7293
|
+
* The Hub release to report right now.
|
|
7294
|
+
*
|
|
7295
|
+
* `DSH_ANTIGRAVITY_VERSION` still wins: pinning a version is how a user works
|
|
7296
|
+
* around a Hub release that misbehaves, and discovery must not override it.
|
|
7297
|
+
*/
|
|
7298
|
+
function currentHubVersion() {
|
|
7299
|
+
return process.env.DSH_ANTIGRAVITY_VERSION?.trim() || discoveredVersion || "2.29.0";
|
|
7300
|
+
}
|
|
7301
|
+
/**
|
|
7302
|
+
* The changelist that belongs to a release, or undefined when it is unknown.
|
|
7303
|
+
*
|
|
7304
|
+
* `DSH_ANTIGRAVITY_CL` wins for the same reason the version pin does.
|
|
7305
|
+
*/
|
|
7306
|
+
function hubChangelist(version = currentHubVersion()) {
|
|
7307
|
+
return process.env.DSH_ANTIGRAVITY_CL?.trim() || HUB_RELEASE_CHANGELISTS[version];
|
|
7308
|
+
}
|
|
7309
|
+
/** The release an electron-builder manifest declares, e.g. `version: 2.24.0`. */
|
|
7310
|
+
function parseHubManifestVersion(text) {
|
|
7311
|
+
return /^\s*version:\s*['"]?(\d+\.\d+\.\d+)['"]?\s*$/m.exec(text)?.[1];
|
|
7312
|
+
}
|
|
7313
|
+
/**
|
|
7314
|
+
* Read the Hub release the updater manifest currently publishes.
|
|
7315
|
+
*
|
|
7316
|
+
* Single-flight and TTL-gated, so calling it on every request costs a `Date.now()`
|
|
7317
|
+
* most of the time. Never throws: the caller is a request path, and a manifest
|
|
7318
|
+
* that does not answer must not turn into a failed request.
|
|
7319
|
+
*/
|
|
7320
|
+
function refreshHubVersion(fetchFn = fetch, now = Date.now()) {
|
|
7321
|
+
if (process.env.DSH_ANTIGRAVITY_VERSION?.trim()) return Promise.resolve();
|
|
7322
|
+
if (inFlight) return inFlight;
|
|
7323
|
+
const interval = discoveredVersion === void 0 ? MANIFEST_RETRY_MS : MANIFEST_TTL_MS;
|
|
7324
|
+
if (lastAttempt !== 0 && now - lastAttempt < interval) return Promise.resolve();
|
|
7325
|
+
lastAttempt = now;
|
|
7326
|
+
inFlight = (async () => {
|
|
7327
|
+
try {
|
|
7328
|
+
const response = await fetchFn(HUB_MANIFEST_URL, {
|
|
7329
|
+
headers: { "User-Agent": HUB_MANIFEST_USER_AGENT },
|
|
7330
|
+
signal: AbortSignal.timeout(MANIFEST_TIMEOUT_MS)
|
|
7331
|
+
});
|
|
7332
|
+
if (!response.ok) return;
|
|
7333
|
+
const version = parseHubManifestVersion(await response.text());
|
|
7334
|
+
if (version) discoveredVersion = version;
|
|
7335
|
+
} catch {} finally {
|
|
7336
|
+
inFlight = void 0;
|
|
7337
|
+
}
|
|
7338
|
+
})();
|
|
7339
|
+
return inFlight;
|
|
7340
|
+
}
|
|
7213
7341
|
let cachedQuota;
|
|
7214
7342
|
let quotaFetchInFlight = null;
|
|
7215
7343
|
/** Bumped by every cache clear so an in-flight fetch cannot publish stale state. */
|
|
7216
7344
|
let quotaCacheEpoch$3 = 0;
|
|
7217
7345
|
const PLATFORM = process.platform === "darwin" ? "MACOS" : process.platform === "win32" ? "WINDOWS" : "LINUX";
|
|
7218
7346
|
function defaultUserAgent() {
|
|
7219
|
-
const version =
|
|
7220
|
-
const cl =
|
|
7221
|
-
return `antigravity/hub/${version} (aidev_client; os_type=${process.env.DSH_ANTIGRAVITY_OS || (process.platform === "darwin" ? "darwin" : process.platform === "win32" ? "windows" : "linux")}; arch=${process.env.DSH_ANTIGRAVITY_ARCH || (process.arch === "x64" ? "amd64" : process.arch)}
|
|
7347
|
+
const version = currentHubVersion();
|
|
7348
|
+
const cl = hubChangelist(version);
|
|
7349
|
+
return `antigravity/hub/${version} (aidev_client; os_type=${process.env.DSH_ANTIGRAVITY_OS || (process.platform === "darwin" ? "darwin" : process.platform === "win32" ? "windows" : "linux")}; arch=${process.env.DSH_ANTIGRAVITY_ARCH || (process.arch === "x64" ? "amd64" : process.arch)}${cl === void 0 ? "" : `; cl=${cl}`})`;
|
|
7350
|
+
}
|
|
7351
|
+
/**
|
|
7352
|
+
* The identity headers a captured Antigravity request does NOT carry.
|
|
7353
|
+
*
|
|
7354
|
+
* `X-Goog-Api-Client` and `Client-Metadata` are Gemini-CLI idioms: the native
|
|
7355
|
+
* `language_server` states its `ideType` in the JSON envelope (the
|
|
7356
|
+
* `loadCodeAssist` metadata) and sends a much smaller header set. Sending them
|
|
7357
|
+
* on every request therefore marked this route as a reimplementation while
|
|
7358
|
+
* buying nothing.
|
|
7359
|
+
*
|
|
7360
|
+
* Captures disagree about the exact header set, so the pair stays reachable
|
|
7361
|
+
* behind `DSH_ANTIGRAVITY_LEGACY_HEADERS` — an account that turns out to need it
|
|
7362
|
+
* gets a one-line switch instead of a code change.
|
|
7363
|
+
*/
|
|
7364
|
+
const LEGACY_IDENTITY_HEADERS = {
|
|
7365
|
+
"X-Goog-Api-Client": "google-cloud-sdk vscode_cloudshelleditor/0.1",
|
|
7366
|
+
"Client-Metadata": JSON.stringify({
|
|
7367
|
+
ideType: "ANTIGRAVITY",
|
|
7368
|
+
platform: PLATFORM,
|
|
7369
|
+
pluginType: "GEMINI"
|
|
7370
|
+
})
|
|
7371
|
+
};
|
|
7372
|
+
function legacyIdentityHeadersEnabled() {
|
|
7373
|
+
const raw = (process.env.DSH_ANTIGRAVITY_LEGACY_HEADERS || "").trim().toLowerCase();
|
|
7374
|
+
return raw === "1" || raw === "true" || raw === "yes" || raw === "on";
|
|
7222
7375
|
}
|
|
7223
7376
|
function antigravityHeaders(token) {
|
|
7224
7377
|
return {
|
|
@@ -7226,12 +7379,7 @@ function antigravityHeaders(token) {
|
|
|
7226
7379
|
"Content-Type": "application/json",
|
|
7227
7380
|
Accept: "text/event-stream",
|
|
7228
7381
|
"User-Agent": process.env.DSH_ANTIGRAVITY_USER_AGENT || defaultUserAgent(),
|
|
7229
|
-
|
|
7230
|
-
"Client-Metadata": JSON.stringify({
|
|
7231
|
-
ideType: "ANTIGRAVITY",
|
|
7232
|
-
platform: PLATFORM,
|
|
7233
|
-
pluginType: "GEMINI"
|
|
7234
|
-
})
|
|
7382
|
+
...legacyIdentityHeadersEnabled() ? LEGACY_IDENTITY_HEADERS : {}
|
|
7235
7383
|
};
|
|
7236
7384
|
}
|
|
7237
7385
|
function jsonHeaders(token) {
|
|
@@ -7240,6 +7388,21 @@ function jsonHeaders(token) {
|
|
|
7240
7388
|
Accept: "application/json"
|
|
7241
7389
|
};
|
|
7242
7390
|
}
|
|
7391
|
+
/**
|
|
7392
|
+
* The identity the Hub presents on `onboardUser` control-plane calls.
|
|
7393
|
+
*
|
|
7394
|
+
* Onboarding is the one surface where the native client is visibly a Node API
|
|
7395
|
+
* client: it appends `google-api-nodejs-client/<version>` to its User-Agent and
|
|
7396
|
+
* states `X-Goog-Api-Client`. Content requests carry neither, which is why this
|
|
7397
|
+
* is a separate builder rather than another field on {@link antigravityHeaders}.
|
|
7398
|
+
*/
|
|
7399
|
+
function antigravityControlPlaneHeaders(token) {
|
|
7400
|
+
return {
|
|
7401
|
+
...jsonHeaders(token),
|
|
7402
|
+
"User-Agent": `${process.env.DSH_ANTIGRAVITY_USER_AGENT || defaultUserAgent()} ${HUB_ONBOARD_UA_SUFFIX}`,
|
|
7403
|
+
"X-Goog-Api-Client": HUB_ONBOARD_API_CLIENT
|
|
7404
|
+
};
|
|
7405
|
+
}
|
|
7243
7406
|
function endpointCandidates() {
|
|
7244
7407
|
const custom = process.env.DSH_ANTIGRAVITY_ENDPOINT?.trim();
|
|
7245
7408
|
if (custom) return [custom];
|
|
@@ -7265,11 +7428,7 @@ function extractProjectId(data) {
|
|
|
7265
7428
|
}
|
|
7266
7429
|
}
|
|
7267
7430
|
async function loadCodeAssistDetail(token, fetchFn = fetch, signal) {
|
|
7268
|
-
const metadata = {
|
|
7269
|
-
ideType: "ANTIGRAVITY",
|
|
7270
|
-
platform: "PLATFORM_UNSPECIFIED",
|
|
7271
|
-
pluginType: "GEMINI"
|
|
7272
|
-
};
|
|
7431
|
+
const metadata = { ideType: "ANTIGRAVITY" };
|
|
7273
7432
|
for (const endpoint of endpointCandidates()) try {
|
|
7274
7433
|
const response = await fetchFn(`${endpoint}/v1internal:loadCodeAssist`, {
|
|
7275
7434
|
method: "POST",
|
|
@@ -7292,11 +7451,15 @@ async function loadCodeAssistDetail(token, fetchFn = fetch, signal) {
|
|
|
7292
7451
|
};
|
|
7293
7452
|
} catch {}
|
|
7294
7453
|
}
|
|
7295
|
-
async function onboardUser(token, fetchFn = fetch, signal) {
|
|
7454
|
+
async function onboardUser(token, fetchFn = fetch, signal, tierId = FREE_TIER_ID) {
|
|
7296
7455
|
const deadline = Date.now() + ONBOARD_TIMEOUT_MS;
|
|
7297
7456
|
const body = JSON.stringify({
|
|
7298
|
-
tierId
|
|
7299
|
-
metadata: {
|
|
7457
|
+
tierId,
|
|
7458
|
+
metadata: {
|
|
7459
|
+
ide_type: "ANTIGRAVITY",
|
|
7460
|
+
ide_version: currentHubVersion(),
|
|
7461
|
+
ide_name: "antigravity"
|
|
7462
|
+
}
|
|
7300
7463
|
});
|
|
7301
7464
|
let lastError;
|
|
7302
7465
|
for (const endpoint of endpointCandidates()) try {
|
|
@@ -7305,7 +7468,7 @@ async function onboardUser(token, fetchFn = fetch, signal) {
|
|
|
7305
7468
|
const callSignal = signal ? AbortSignal.any([signal, timeoutSignal]) : timeoutSignal;
|
|
7306
7469
|
const response = await fetchFn(`${endpoint}/v1internal:onboardUser`, {
|
|
7307
7470
|
method: "POST",
|
|
7308
|
-
headers:
|
|
7471
|
+
headers: antigravityControlPlaneHeaders(token),
|
|
7309
7472
|
body,
|
|
7310
7473
|
signal: callSignal
|
|
7311
7474
|
});
|
|
@@ -7333,7 +7496,7 @@ async function onboardUser(token, fetchFn = fetch, signal) {
|
|
|
7333
7496
|
const pollSignal = signal ? AbortSignal.any([signal, pollTimeoutSignal]) : pollTimeoutSignal;
|
|
7334
7497
|
const pollResp = await fetchFn(`${endpoint}/v1internal/${operationName}`, {
|
|
7335
7498
|
method: "GET",
|
|
7336
|
-
headers:
|
|
7499
|
+
headers: antigravityControlPlaneHeaders(token),
|
|
7337
7500
|
signal: pollSignal
|
|
7338
7501
|
});
|
|
7339
7502
|
if (!pollResp.ok) {
|
|
@@ -7468,14 +7631,11 @@ async function fetchAccountQuota(store = new FileCredentialStore$3(), modelSetti
|
|
|
7468
7631
|
if (quotaFetchInFlight) return quotaFetchInFlight;
|
|
7469
7632
|
const epoch = quotaCacheEpoch$3;
|
|
7470
7633
|
const request = (async () => {
|
|
7634
|
+
refreshHubVersion(fetchFn);
|
|
7471
7635
|
const { token, projectId: credentialProjectId } = await ensureApiKey(store, fetchFn);
|
|
7472
|
-
const [assistResult, summaryResult] = await Promise.all([postJson("/v1internal:loadCodeAssist", token, { metadata: {
|
|
7473
|
-
ideType: "ANTIGRAVITY",
|
|
7474
|
-
platform: "PLATFORM_UNSPECIFIED",
|
|
7475
|
-
pluginType: "GEMINI"
|
|
7476
|
-
} }, fetchFn).catch(() => null), postJson("/v1internal:retrieveUserQuotaSummary", token, {}, fetchFn).catch(() => null)]);
|
|
7636
|
+
const [assistResult, summaryResult] = await Promise.all([postJson("/v1internal:loadCodeAssist", token, { metadata: { ideType: "ANTIGRAVITY" } }, fetchFn).catch(() => null), postJson("/v1internal:retrieveUserQuotaSummary", token, {}, fetchFn).catch(() => null)]);
|
|
7477
7637
|
const discoveredProject = assistResult ? extractProjectId(assistResult.data) : void 0;
|
|
7478
|
-
const projectId = credentialProjectId || discoveredProject || "
|
|
7638
|
+
const projectId = credentialProjectId || discoveredProject || "rising-fact-p41fc";
|
|
7479
7639
|
const modelsData = (await postJson("/v1internal:fetchAvailableModels", token, { project: projectId }, fetchFn).catch(() => null))?.data;
|
|
7480
7640
|
const { groups, description } = summaryResult ? parseQuotaSummary(summaryResult.data) : { groups: [] };
|
|
7481
7641
|
const catalogModels = modelsData ? parseCatalogModels(modelsData) : [];
|
|
@@ -7725,6 +7885,18 @@ function assertFreeTierEligible(payload) {
|
|
|
7725
7885
|
if (ineligibility.validationUrl) err.validationUrl = ineligibility.validationUrl;
|
|
7726
7886
|
throw err;
|
|
7727
7887
|
}
|
|
7888
|
+
/**
|
|
7889
|
+
* The tier to onboard with, chosen the way the Hub chooses one.
|
|
7890
|
+
*
|
|
7891
|
+
* The Hub onboards into its own default allowed tier; this route additionally
|
|
7892
|
+
* requires the free tier to be on offer (it is the only tier this line claims
|
|
7893
|
+
* eligibility for), so that one is preferred next. Everything else is the
|
|
7894
|
+
* reference implementation's order: first allowed tier, current tier, free tier.
|
|
7895
|
+
*/
|
|
7896
|
+
function selectOnboardTier(payload) {
|
|
7897
|
+
const allowed = payload.allowedTiers ?? [];
|
|
7898
|
+
return allowed.find((tier) => tier.isDefault === true && tier.id)?.id ?? allowed.find((tier) => tier.id === "free-tier")?.id ?? allowed[0]?.id ?? payload.currentTier?.id ?? "free-tier";
|
|
7899
|
+
}
|
|
7728
7900
|
async function discoverAntigravityProject(token, fetchFn = fetch, signal, onProgress) {
|
|
7729
7901
|
onProgress?.("正在检查 Cloud Code Assist 账号状态...");
|
|
7730
7902
|
const initial = await loadCodeAssistDetail(token, fetchFn, signal);
|
|
@@ -7732,7 +7904,7 @@ async function discoverAntigravityProject(token, fetchFn = fetch, signal, onProg
|
|
|
7732
7904
|
assertFreeTierEligible(initial);
|
|
7733
7905
|
if (initial.allowedTiers?.some((tier) => tier.id === "free-tier") === true && !initial.currentTier) {
|
|
7734
7906
|
onProgress?.("正在为新账号开通 Antigravity 免费额度...");
|
|
7735
|
-
await onboardUser(token, fetchFn, signal);
|
|
7907
|
+
await onboardUser(token, fetchFn, signal, selectOnboardTier(initial));
|
|
7736
7908
|
onProgress?.("正在获取专属项目 (Project ID)...");
|
|
7737
7909
|
const refreshed = await loadCodeAssistDetail(token, fetchFn, signal);
|
|
7738
7910
|
if (refreshed?.projectId) return refreshed.projectId;
|
|
@@ -8707,12 +8879,7 @@ function buildRequest$2(options, model, projectId, runtimeModel, effort, images
|
|
|
8707
8879
|
contents: convertMessages(options, model, runtimeModel, images),
|
|
8708
8880
|
systemInstruction: {
|
|
8709
8881
|
role: GEMINI_ROLE.user,
|
|
8710
|
-
parts: [
|
|
8711
|
-
{ text: ANTIGRAVITY_SYSTEM_INSTRUCTION },
|
|
8712
|
-
{ text: `Please ignore following [ignore]${ANTIGRAVITY_SYSTEM_INSTRUCTION}[/ignore]` },
|
|
8713
|
-
{ text: ANTIGRAVITY_NO_PREAMBLE_INSTRUCTION },
|
|
8714
|
-
...options.system ? [{ text: sanitizeText$9(options.system) }] : []
|
|
8715
|
-
]
|
|
8882
|
+
parts: [{ text: ANTIGRAVITY_SYSTEM_INSTRUCTION }, ...options.system ? [{ text: sanitizeText$9(options.system) }] : []]
|
|
8716
8883
|
}
|
|
8717
8884
|
};
|
|
8718
8885
|
const generationConfig = {};
|
|
@@ -8757,7 +8924,7 @@ function buildRequest$2(options, model, projectId, runtimeModel, effort, images
|
|
|
8757
8924
|
request,
|
|
8758
8925
|
requestType: "agent",
|
|
8759
8926
|
userAgent: "antigravity",
|
|
8760
|
-
requestId: `
|
|
8927
|
+
requestId: `agent-${randomUUID()}`
|
|
8761
8928
|
};
|
|
8762
8929
|
}
|
|
8763
8930
|
function createStreamState$8() {
|
|
@@ -10473,7 +10640,7 @@ var AntigravityAdapter = class extends LlmAdapter {
|
|
|
10473
10640
|
} else throw poolErr;
|
|
10474
10641
|
}
|
|
10475
10642
|
const { account, token, projectId: defaultProj } = eff;
|
|
10476
|
-
const projectId = defaultProj || "
|
|
10643
|
+
const projectId = defaultProj || "rising-fact-p41fc";
|
|
10477
10644
|
triedAccountIds.add(account.id);
|
|
10478
10645
|
const body = JSON.stringify(buildRequest$2(requestOptions, model, projectId, runtimeModel, effort, images, {
|
|
10479
10646
|
claudeValidatedToolCalling: !this.validatedToolCallingRejected,
|
|
@@ -10699,7 +10866,7 @@ function buildImageRequest(prompt, projectId, aspectRatio, imageSize) {
|
|
|
10699
10866
|
},
|
|
10700
10867
|
requestType: "image_gen",
|
|
10701
10868
|
userAgent: "antigravity",
|
|
10702
|
-
requestId: `
|
|
10869
|
+
requestId: `agent-${randomUUID()}`
|
|
10703
10870
|
};
|
|
10704
10871
|
}
|
|
10705
10872
|
function record$6(value) {
|
|
@@ -10994,7 +11161,7 @@ async function requestImage(accountPool, store, fetchFn, prompt, aspectRatio, im
|
|
|
10994
11161
|
while (true) {
|
|
10995
11162
|
const { account, token, projectId } = await acquireAccount(accountPool, store, tried, fetchFn);
|
|
10996
11163
|
tried.add(account.id);
|
|
10997
|
-
const body = JSON.stringify(buildImageRequest(prompt, projectId || "
|
|
11164
|
+
const body = JSON.stringify(buildImageRequest(prompt, projectId || "rising-fact-p41fc", aspectRatio, imageSize));
|
|
10998
11165
|
let response;
|
|
10999
11166
|
let firstResponse;
|
|
11000
11167
|
for (const endpoint of endpointCandidates()) try {
|
|
@@ -11217,6 +11384,162 @@ const SYSTEM_PROXY_CACHE_TTL_MS = 5e3;
|
|
|
11217
11384
|
* CONNECT phase only; the request itself keeps undici's own timeouts.
|
|
11218
11385
|
*/
|
|
11219
11386
|
const PROXY_CONNECT_TIMEOUT_MS = 6e4;
|
|
11387
|
+
/**
|
|
11388
|
+
* The ProxyAgent constructor options for one proxy URL.
|
|
11389
|
+
*
|
|
11390
|
+
* `allowH2` is stated only when a caller asks to pin HTTP/1.1: ProxyAgent
|
|
11391
|
+
* forwards whatever it is given into the per-origin Agent, and `allowH2: false`
|
|
11392
|
+
* is what keeps h2 out of the tunnel's ALPN offer. Every other caller gets the
|
|
11393
|
+
* option object it had before, byte for byte.
|
|
11394
|
+
*/
|
|
11395
|
+
function proxyAgentOptions(uri, allowH2) {
|
|
11396
|
+
return {
|
|
11397
|
+
uri,
|
|
11398
|
+
connectTimeout: PROXY_CONNECT_TIMEOUT_MS,
|
|
11399
|
+
...allowH2 === false ? { allowH2: false } : {}
|
|
11400
|
+
};
|
|
11401
|
+
}
|
|
11402
|
+
/** One pool per (proxy, protocol policy, credential): neither policy nor identity may be shared. */
|
|
11403
|
+
function agentCacheKey(proxyUrl, allowH2, poolKey) {
|
|
11404
|
+
return `${poolKey ?? "shared"}:${allowH2 === false ? "h1" : "auto"}:${proxyUrl}`;
|
|
11405
|
+
}
|
|
11406
|
+
/** The key of the dispatcher that serves one credential's unproxied traffic. */
|
|
11407
|
+
function directAgentKey(poolKey, allowH2, omitAlpn) {
|
|
11408
|
+
return `direct:${poolKey}:${allowH2 === true ? "auto" : "h1"}:${omitAlpn === true ? "noalpn" : "alpn"}`;
|
|
11409
|
+
}
|
|
11410
|
+
/**
|
|
11411
|
+
* How many pooled dispatchers may exist at once.
|
|
11412
|
+
*
|
|
11413
|
+
* A pool is per credential, so the bound has to clear the largest account pool
|
|
11414
|
+
* this plugin supports with room for a rotation or two. The oldest pool is
|
|
11415
|
+
* closed (not destroyed) when it is exceeded, so an evicted pool still finishes
|
|
11416
|
+
* the request it is serving.
|
|
11417
|
+
*/
|
|
11418
|
+
const DISPATCHER_POOL_CAPACITY = 64;
|
|
11419
|
+
/**
|
|
11420
|
+
* The pool a request belongs to, derived from its credential.
|
|
11421
|
+
*
|
|
11422
|
+
* Two accounts must never share one TLS connection: the native client is one
|
|
11423
|
+
* credential per process, so a server watching a connection that carries several
|
|
11424
|
+
* different `Authorization` values is watching a rotating pool, which no real
|
|
11425
|
+
* client does. The token is hashed, so the map never holds a raw credential.
|
|
11426
|
+
*
|
|
11427
|
+
* A request with no `Authorization` header is not credentialed (project
|
|
11428
|
+
* discovery before a token exists, the Hub release manifest) and keeps the
|
|
11429
|
+
* shared pool.
|
|
11430
|
+
*/
|
|
11431
|
+
function credentialPoolKey(init) {
|
|
11432
|
+
const headers = init?.headers;
|
|
11433
|
+
if (headers === void 0) return void 0;
|
|
11434
|
+
const authorization = new Headers(headers).get("authorization");
|
|
11435
|
+
if (!authorization) return void 0;
|
|
11436
|
+
return createHash("sha256").update(authorization).digest("hex").slice(0, 16);
|
|
11437
|
+
}
|
|
11438
|
+
/** Timeout for establishing an origin connection on the native connector. */
|
|
11439
|
+
const NATIVE_CONNECT_TIMEOUT_MS = 3e4;
|
|
11440
|
+
/** One connector instance serves every direct agent: it holds no state of its own. */
|
|
11441
|
+
const NATIVE_CONNECTOR = buildNativeConnector();
|
|
11442
|
+
/**
|
|
11443
|
+
* A connector that offers no ALPN at all.
|
|
11444
|
+
*
|
|
11445
|
+
* The native Antigravity client is a Go HTTP/1.1 client and sends no ALPN
|
|
11446
|
+
* extension; undici's built-in connector always advertises `http/1.1`. Offering
|
|
11447
|
+
* nothing does not change the protocol that ends up being spoken (the server
|
|
11448
|
+
* falls back to HTTP/1.1 either way) but it removes one extension the client this
|
|
11449
|
+
* route imitates does not have.
|
|
11450
|
+
*
|
|
11451
|
+
* SNI is set explicitly: undici hands the connector an empty `servername`, and a
|
|
11452
|
+
* hello without SNI is refused by Cloud Code (measured: a bare
|
|
11453
|
+
* `SSL_ALERT_HANDSHAKE_FAILURE`).
|
|
11454
|
+
*
|
|
11455
|
+
* HTTP targets keep a plain TCP connect -- the ALPN question only exists for TLS.
|
|
11456
|
+
* `connectTls` / `connectTcp` are the seams that keep the shape testable.
|
|
11457
|
+
*/
|
|
11458
|
+
function buildNativeConnector(options = {}) {
|
|
11459
|
+
const connectTls = options.connectTls ?? tls.connect;
|
|
11460
|
+
const connectTcp = options.connectTcp ?? net.connect;
|
|
11461
|
+
const timeoutMs = options.timeoutMs ?? NATIVE_CONNECT_TIMEOUT_MS;
|
|
11462
|
+
return (connectorOptions, callback) => {
|
|
11463
|
+
const protocol = String(connectorOptions.protocol ?? "https:");
|
|
11464
|
+
const rawHost = String(connectorOptions.hostname || connectorOptions.host || "");
|
|
11465
|
+
const glued = /^\[?([^\]]+)\]?:(\d+)$/.exec(rawHost);
|
|
11466
|
+
const host = glued === null ? rawHost : glued[1];
|
|
11467
|
+
const port = Number(connectorOptions.port) || Number(glued?.[2] ?? "") || (protocol === "http:" ? 80 : 443);
|
|
11468
|
+
if (protocol === "http:") {
|
|
11469
|
+
const socket = connectTcp({
|
|
11470
|
+
host,
|
|
11471
|
+
port
|
|
11472
|
+
});
|
|
11473
|
+
socket.setTimeout(timeoutMs, () => {
|
|
11474
|
+
socket.destroy();
|
|
11475
|
+
callback(/* @__PURE__ */ new Error("connect timeout"), null);
|
|
11476
|
+
});
|
|
11477
|
+
socket.once("error", (error) => {
|
|
11478
|
+
socket.destroy();
|
|
11479
|
+
callback(error, null);
|
|
11480
|
+
});
|
|
11481
|
+
socket.once("connect", () => {
|
|
11482
|
+
socket.setTimeout(0);
|
|
11483
|
+
callback(null, socket);
|
|
11484
|
+
});
|
|
11485
|
+
return;
|
|
11486
|
+
}
|
|
11487
|
+
const socket = connectTls({
|
|
11488
|
+
host,
|
|
11489
|
+
port,
|
|
11490
|
+
servername: connectorOptions.servername || host
|
|
11491
|
+
});
|
|
11492
|
+
socket.setTimeout(timeoutMs, () => {
|
|
11493
|
+
socket.destroy();
|
|
11494
|
+
callback(/* @__PURE__ */ new Error("connect timeout"), null);
|
|
11495
|
+
});
|
|
11496
|
+
socket.once("error", (error) => {
|
|
11497
|
+
socket.destroy();
|
|
11498
|
+
callback(error, null);
|
|
11499
|
+
});
|
|
11500
|
+
socket.once("secureConnect", () => {
|
|
11501
|
+
socket.setTimeout(0);
|
|
11502
|
+
callback(null, socket);
|
|
11503
|
+
});
|
|
11504
|
+
};
|
|
11505
|
+
}
|
|
11506
|
+
/**
|
|
11507
|
+
* Drop headers before the request is written.
|
|
11508
|
+
*
|
|
11509
|
+
* `fetch` adds `sec-fetch-mode: cors` and `accept-language: *` to every request
|
|
11510
|
+
* and offers no way to suppress a header it adds itself. The dispatcher is the
|
|
11511
|
+
* seam it hands the header list to, so a consumer that imitates a non-browser
|
|
11512
|
+
* client can remove them there. The wrapped dispatcher keeps the inner agent's
|
|
11513
|
+
* pool: this is a filter, not a new connection pool.
|
|
11514
|
+
*/
|
|
11515
|
+
function stripDispatchHeaders(dispatcher, headers) {
|
|
11516
|
+
const banned = new Set(headers.map((name) => name.toLowerCase()));
|
|
11517
|
+
const strip = (input) => {
|
|
11518
|
+
if (Array.isArray(input)) return input.filter((entry) => !banned.has(String(entry[0]).toLowerCase()));
|
|
11519
|
+
if (input !== null && typeof input === "object") {
|
|
11520
|
+
const kept = {};
|
|
11521
|
+
for (const [name, value] of Object.entries(input)) if (!banned.has(name.toLowerCase())) kept[name] = value;
|
|
11522
|
+
return kept;
|
|
11523
|
+
}
|
|
11524
|
+
return input;
|
|
11525
|
+
};
|
|
11526
|
+
const inner = dispatcher;
|
|
11527
|
+
const shaped = {
|
|
11528
|
+
dispatch(options, handler) {
|
|
11529
|
+
return inner.dispatch({
|
|
11530
|
+
...options,
|
|
11531
|
+
headers: strip(options.headers)
|
|
11532
|
+
}, handler);
|
|
11533
|
+
},
|
|
11534
|
+
close: (...args) => inner.close(...args),
|
|
11535
|
+
destroy: (...args) => inner.destroy(...args)
|
|
11536
|
+
};
|
|
11537
|
+
Object.defineProperty(shaped, "wrapped", {
|
|
11538
|
+
value: dispatcher,
|
|
11539
|
+
enumerable: false
|
|
11540
|
+
});
|
|
11541
|
+
return shaped;
|
|
11542
|
+
}
|
|
11220
11543
|
function normalizeProxyUrl(rawUrl) {
|
|
11221
11544
|
const trimmed = rawUrl.trim();
|
|
11222
11545
|
if (!trimmed) return "";
|
|
@@ -11491,6 +11814,8 @@ var ProxyManager = class {
|
|
|
11491
11814
|
detected = false;
|
|
11492
11815
|
proxyListeners = /* @__PURE__ */ new Set();
|
|
11493
11816
|
agents = /* @__PURE__ */ new Map();
|
|
11817
|
+
/** One shaping wrapper per pooled dispatcher, so a pool keeps a stable identity. */
|
|
11818
|
+
shaped = /* @__PURE__ */ new WeakMap();
|
|
11494
11819
|
constructor(options) {
|
|
11495
11820
|
this.getPreferences = options.getPreferences;
|
|
11496
11821
|
this.baseFetch = options.baseFetch ?? fetch;
|
|
@@ -11558,31 +11883,87 @@ var ProxyManager = class {
|
|
|
11558
11883
|
if (mode === "custom") return prefs.customProxyUrl ? normalizeProxyUrl(prefs.customProxyUrl) : null;
|
|
11559
11884
|
return this.getSystemProxy();
|
|
11560
11885
|
}
|
|
11561
|
-
getOrCreateAgent(proxyUrl) {
|
|
11562
|
-
|
|
11563
|
-
|
|
11564
|
-
|
|
11565
|
-
|
|
11566
|
-
|
|
11567
|
-
});
|
|
11568
|
-
this.agents.set(proxyUrl, agent);
|
|
11569
|
-
}
|
|
11886
|
+
getOrCreateAgent(proxyUrl, allowH2, poolKey) {
|
|
11887
|
+
const key = agentCacheKey(proxyUrl, allowH2, poolKey);
|
|
11888
|
+
const existing = this.agents.get(key);
|
|
11889
|
+
if (existing instanceof ProxyAgent) return existing;
|
|
11890
|
+
const agent = new ProxyAgent(proxyAgentOptions(proxyUrl, allowH2));
|
|
11891
|
+
this.remember(key, agent);
|
|
11570
11892
|
return agent;
|
|
11571
11893
|
}
|
|
11572
|
-
|
|
11894
|
+
/**
|
|
11895
|
+
* The dispatcher for one credential's direct (unproxied) traffic.
|
|
11896
|
+
*
|
|
11897
|
+
* Node's global fetch pools every origin in one process-wide agent, so a
|
|
11898
|
+
* credentialed request cannot be given a private connection through it. The
|
|
11899
|
+
* pooled path therefore dispatches through undici's own fetch with an agent of
|
|
11900
|
+
* its own; HTTP/1.1 stays the default, because that is what the global fetch
|
|
11901
|
+
* this replaces would have spoken.
|
|
11902
|
+
*/
|
|
11903
|
+
getOrCreateDirectAgent(poolKey, overrides) {
|
|
11904
|
+
const key = directAgentKey(poolKey, overrides?.allowH2, overrides?.omitAlpn);
|
|
11905
|
+
const existing = this.agents.get(key);
|
|
11906
|
+
if (existing instanceof Agent) return existing;
|
|
11907
|
+
const agent = new Agent({
|
|
11908
|
+
allowH2: overrides?.allowH2 === true,
|
|
11909
|
+
...overrides?.omitAlpn === true ? { connect: NATIVE_CONNECTOR } : {}
|
|
11910
|
+
});
|
|
11911
|
+
this.remember(key, agent);
|
|
11912
|
+
return agent;
|
|
11913
|
+
}
|
|
11914
|
+
/** Store a dispatcher, retiring the oldest pool once the bound is reached. */
|
|
11915
|
+
remember(key, agent) {
|
|
11916
|
+
if (this.agents.size >= DISPATCHER_POOL_CAPACITY) {
|
|
11917
|
+
const oldest = this.agents.keys().next();
|
|
11918
|
+
if (!oldest.done) {
|
|
11919
|
+
const evicted = this.agents.get(oldest.value);
|
|
11920
|
+
this.agents.delete(oldest.value);
|
|
11921
|
+
evicted?.close().catch(() => void 0);
|
|
11922
|
+
}
|
|
11923
|
+
}
|
|
11924
|
+
this.agents.set(key, agent);
|
|
11925
|
+
}
|
|
11926
|
+
/** Hand one request to a specific dispatcher through undici's fetch. */
|
|
11927
|
+
dispatchWith(input, init, dispatcher) {
|
|
11928
|
+
return this.proxyFetchFn(input, {
|
|
11929
|
+
...init,
|
|
11930
|
+
dispatcher
|
|
11931
|
+
});
|
|
11932
|
+
}
|
|
11933
|
+
/**
|
|
11934
|
+
* A fetch that follows this manager's proxy policy, with optional protocol and
|
|
11935
|
+
* credential pins for one consumer.
|
|
11936
|
+
*
|
|
11937
|
+
* `allowH2: false` keeps TLS at HTTP/1.1. Antigravity asks for it: the native
|
|
11938
|
+
* `language_server` speaks HTTP/1.1, and the direct path this manager falls
|
|
11939
|
+
* back to is Node's global fetch, which offers http/1.1 only - without the pin
|
|
11940
|
+
* the same route would speak h2 behind a proxy and HTTP/1.1 without one.
|
|
11941
|
+
*
|
|
11942
|
+
* `credentialPools: true` gives every distinct credential its own connection
|
|
11943
|
+
* pool on both paths, which is what keeps a multi-account rotation from being
|
|
11944
|
+
* visible as one connection carrying several identities.
|
|
11945
|
+
*/
|
|
11946
|
+
createFetch(overrides) {
|
|
11947
|
+
const shape = (dispatcher) => {
|
|
11948
|
+
const headers = overrides?.stripHeaders;
|
|
11949
|
+
if (headers === void 0 || headers.length === 0) return dispatcher;
|
|
11950
|
+
const cached = this.shaped.get(dispatcher);
|
|
11951
|
+
if (cached !== void 0) return cached;
|
|
11952
|
+
const shaped = stripDispatchHeaders(dispatcher, headers);
|
|
11953
|
+
this.shaped.set(dispatcher, shaped);
|
|
11954
|
+
return shaped;
|
|
11955
|
+
};
|
|
11573
11956
|
return async (input, init) => {
|
|
11957
|
+
const poolKey = overrides?.credentialPools === true ? credentialPoolKey(init) : void 0;
|
|
11574
11958
|
const activeProxy = this.resolveActiveProxyUrl();
|
|
11575
|
-
if (!activeProxy) return this.baseFetch(input, init);
|
|
11576
|
-
if (shouldBypassProxy(requestTarget(input), this.getNoProxyList())) return this.baseFetch(input, init);
|
|
11959
|
+
if (!activeProxy) return poolKey === void 0 ? this.baseFetch(input, init) : this.dispatchWith(input, init, shape(this.getOrCreateDirectAgent(poolKey, overrides)));
|
|
11960
|
+
if (shouldBypassProxy(requestTarget(input), this.getNoProxyList())) return poolKey === void 0 ? this.baseFetch(input, init) : this.dispatchWith(input, init, shape(this.getOrCreateDirectAgent(poolKey, overrides)));
|
|
11577
11961
|
for (let attempt = 0;; attempt += 1) try {
|
|
11578
|
-
const agent = this.getOrCreateAgent(activeProxy);
|
|
11579
|
-
return await this.
|
|
11580
|
-
...init,
|
|
11581
|
-
dispatcher: agent
|
|
11582
|
-
});
|
|
11962
|
+
const agent = shape(this.getOrCreateAgent(activeProxy, overrides?.allowH2, poolKey));
|
|
11963
|
+
return await this.dispatchWith(input, init, agent);
|
|
11583
11964
|
} catch (error) {
|
|
11584
11965
|
if (attempt === 0 && isDestroyedClientError(error)) {
|
|
11585
|
-
this.agents.delete(activeProxy);
|
|
11966
|
+
this.agents.delete(agentCacheKey(activeProxy, overrides?.allowH2, poolKey));
|
|
11586
11967
|
continue;
|
|
11587
11968
|
}
|
|
11588
11969
|
throw error;
|
|
@@ -104902,8 +105283,16 @@ function apply(ctx, pluginConfig = {}) {
|
|
|
104902
105283
|
logger: ctx.logger
|
|
104903
105284
|
});
|
|
104904
105285
|
const proxyFetch = proxyManager.createFetch();
|
|
105286
|
+
const antigravityProxyFetch = proxyManager.createFetch({
|
|
105287
|
+
allowH2: false,
|
|
105288
|
+
credentialPools: true,
|
|
105289
|
+
stripHeaders: ANTIGRAVITY_ABSENT_HEADERS,
|
|
105290
|
+
omitAlpn: true
|
|
105291
|
+
});
|
|
105292
|
+
refreshHubVersion(antigravityProxyFetch);
|
|
104905
105293
|
const providerLimits = readModelRequestLimits();
|
|
104906
|
-
const
|
|
105294
|
+
const baseFetchFor = (provider) => provider === "antigravity" ? antigravityProxyFetch : proxyFetch;
|
|
105295
|
+
const modelFetch = Object.fromEntries(CONTROLLED_PROVIDERS.map((provider) => [provider, createControlledModelFetch(createDiagnosticFetch(baseFetchFor(provider), {
|
|
104907
105296
|
provider,
|
|
104908
105297
|
onRecord: (record) => ctx.logger.info("[provider-diagnostics] " + JSON.stringify(record))
|
|
104909
105298
|
}), {
|
|
@@ -104918,7 +105307,7 @@ function apply(ctx, pluginConfig = {}) {
|
|
|
104918
105307
|
attachments: ctx.attachments
|
|
104919
105308
|
}, antigravityAccountPool)
|
|
104920
105309
|
});
|
|
104921
|
-
const disposeAntigravityRoutes = registerAntigravityRoutes(ctx, antigravityStore, antigravityModelSettings, antigravityPreferences,
|
|
105310
|
+
const disposeAntigravityRoutes = registerAntigravityRoutes(ctx, antigravityStore, antigravityModelSettings, antigravityPreferences, antigravityProxyFetch, antigravityAccountPool);
|
|
104922
105311
|
const disposeCommandCodeRoutes = registerCommandCodeRoutes(ctx, commandCodeStore, commandCodeModelSettings, commandCodePreferences, {
|
|
104923
105312
|
fetchFn: proxyFetch,
|
|
104924
105313
|
serving: () => commandCodeClaim.serving(),
|
|
@@ -105419,7 +105808,7 @@ function apply(ctx, pluginConfig = {}) {
|
|
|
105419
105808
|
const disposeAdapter = ctx.llm.registerAdapter([PROVIDER_ID$13], adapter);
|
|
105420
105809
|
const disposeImageTool = ctx.tools.register(createCodexImageTool(oauth, ctx.attachments, { fetchFn: proxyFetch }));
|
|
105421
105810
|
const disposeAntigravityImageTool = ctx.tools.register(createAntigravityImageTool(antigravityAccountPool, antigravityStore, ctx.attachments, {
|
|
105422
|
-
fetchFn:
|
|
105811
|
+
fetchFn: antigravityProxyFetch,
|
|
105423
105812
|
isEnabled: () => antigravityPreferences.status().enabled !== false
|
|
105424
105813
|
}));
|
|
105425
105814
|
const disposeVideoTool = ctx.tools.register(createKimiVideoTool(ctx, { fetchFn: proxyFetch }));
|