@xiaoso/dsh-tool-plus 0.1.0-beta.2 → 0.1.0-beta.3
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.en.md +122 -0
- package/README.md +3 -2
- package/THIRD_PARTY_NOTICES.md +4 -35
- package/lib/abort-B7izMMna.mjs +51 -0
- package/lib/amazon-bedrock-D-shAr1X.mjs +917 -0
- package/lib/anthropic-BWsZFzU8.mjs +262 -0
- package/lib/anthropic-CMT1Qj1t.mjs +3115 -0
- package/lib/api-key-login-CpzSezsi.mjs +157 -0
- package/lib/aws-credentials-8Mgn5MAy.mjs +867 -0
- package/lib/azure-openai-responses-CNkHiLUh.mjs +274 -0
- package/lib/bun-shim.mjs +172 -7
- package/lib/bundled-references-CSuBco5p.mjs +55 -0
- package/lib/callback-server-BEFNf-jf.mjs +398 -0
- package/lib/client.js +110 -40
- package/lib/cursor-BIQfBC6V.mjs +135 -0
- package/lib/cursor-DNk6eXDd.mjs +5470 -0
- package/lib/cursor-MjSm74IJ.mjs +273 -0
- package/lib/device-code-OI_tQcmc.mjs +51 -0
- package/lib/devin-CldyPD8K.mjs +95 -0
- package/lib/devin-CzRpTUOA.mjs +114 -0
- package/lib/devin-DXOeNyU7.mjs +542 -0
- package/lib/error-B3bevhrs.mjs +1449 -0
- package/lib/event-stream-BDPi64mK.mjs +151 -0
- package/lib/github-copilot-4GaMtQmg.mjs +208 -0
- package/lib/github-copilot-B2HGSIJK.mjs +104 -0
- package/lib/gitlab-duo-akICyfeD.mjs +155 -0
- package/lib/gitlab-duo-workflow-CSEgYk3N.mjs +91 -0
- package/lib/google-antigravity-Dlkdhahq.mjs +198 -0
- package/lib/google-auth-DhqpOYrX.mjs +232 -0
- package/lib/google-gemini-cli-BG_LRdIV.mjs +850 -0
- package/lib/google-gemini-cli-zJhiOcND.mjs +211 -0
- package/lib/google-oauth-shared-CwNWYdmR.mjs +147 -0
- package/lib/google-shared-DzhCb9b0.mjs +760 -0
- package/lib/google-vertex-kscbkyRb.mjs +99 -0
- package/lib/google-zyDOG9x7.mjs +30 -0
- package/lib/identity-DnB63pS7.mjs +219 -0
- package/lib/idle-iterator-C6XbWcuB.mjs +366 -0
- package/lib/index.mjs +2865 -2745
- package/lib/kimi-DMVI-zrZ.mjs +236 -0
- package/lib/markit-M0jhziqU.mjs +1417 -0
- package/lib/minimax-code-BK-3eBbz.mjs +53 -0
- package/lib/models-CfT4coYT.mjs +104660 -0
- package/lib/ollama-BQMGPxtV.mjs +589 -0
- package/lib/openai-codex-CQL_kvYL.mjs +255 -0
- package/lib/openai-codex-responses-Cz-2qpC7.mjs +3144 -0
- package/lib/openai-completions-i8doczAk.mjs +1360 -0
- package/lib/openai-reasoning-fallback-DGVVLgd1.mjs +286 -0
- package/lib/openai-responses-DTkBiiy-.mjs +867 -0
- package/lib/opencode-DaJjcUbf.mjs +38 -0
- package/lib/perplexity-9b-RQ0mV.mjs +194 -0
- package/lib/proxy-ZtUcl6r5.mjs +190 -0
- package/lib/scrapers-CL-WgdU1.mjs +9198 -0
- package/lib/scrapers-CipyKyCH.mjs +9198 -0
- package/lib/scrapers-DGfrYhtw.mjs +9198 -0
- package/lib/scrapers-DSUPYoUF.mjs +9198 -0
- package/lib/scrapers-DZ2GXmp7.mjs +9198 -0
- package/lib/src-DTid0g4K.mjs +5001 -0
- package/lib/stream-C_RAoxJC.mjs +10236 -0
- package/lib/stream-markup-healing-2toHXWXM.mjs +491 -0
- package/lib/types/client/locales.d.ts +1 -1
- package/lib/types/config/fields.d.ts +1 -1
- package/lib/types/config/settings.d.ts +16 -2
- package/lib/types/tools/omp/sdk.d.ts +6 -0
- package/lib/types/tools/omp/tools/fetch.d.ts +2 -0
- package/lib/types/tools/omp/tools/read.d.ts +2 -8
- package/lib/types/tools/omp/utils/image-loading.d.ts +10 -36
- package/lib/types/tools/read/adapter/index.d.ts +4 -1
- package/lib/types/tools/read-image/index.d.ts +4 -0
- package/lib/types/tools/shared/bun-shim.d.ts +35 -3
- package/lib/types/tools/shared/image-bridge.d.ts +98 -0
- package/lib/types/tools/shared/omp-prompt.d.ts +4 -2
- package/lib/utils-2Wq2eATG.mjs +8119 -0
- package/lib/utils-BnX8O3vi.mjs +12303 -0
- package/lib/utils-CE8N8P4Q.mjs +12315 -0
- package/lib/utils-C_MrQ_0z.mjs +12301 -0
- package/lib/utils-D0Z1fyoO.mjs +12299 -0
- package/lib/utils-DppGHXQB.mjs +51 -0
- package/lib/utils-W8WdSBpX.mjs +12315 -0
- package/lib/vision-guard-BDD4OrKo.mjs +92 -0
- package/lib/wafer-DRU0EjZX.mjs +17 -0
- package/lib/xai-oauth-DPHDXKD7.mjs +446 -0
- package/lib/xiaomi-Dd87KSg5.mjs +157 -0
- package/lib/zai-CFeOt-53.mjs +203 -0
- package/lib/zip-D6QXpvaJ.mjs +1316 -0
- package/package.json +14 -10
- package/presets/package.json +1 -1
- package/presets/tool-plus-ptc/preset.yml +1 -1
- package/presets/tool-plus-standard/preset.yml +1 -1
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { installBunShim as __installBunShim } from "./bun-shim.mjs";
|
|
2
|
+
__installBunShim();
|
|
3
|
+
import { c as OAuthError } from "./error-B3bevhrs.mjs";
|
|
4
|
+
import { t as OAuthCallbackFlow } from "./callback-server-BEFNf-jf.mjs";
|
|
5
|
+
import { t as generatePKCE } from "./pkce-BlQikGPu.mjs";
|
|
6
|
+
//#region node_modules/.pnpm/@oh-my-pi+pi-ai@17.3.5/node_modules/@oh-my-pi/pi-ai/src/registry/oauth/gitlab-duo-workflow.ts
|
|
7
|
+
const GITLAB_COM_URL = "https://gitlab.com";
|
|
8
|
+
const GITLAB_DUO_WORKFLOW_OAUTH_CLIENT_ID = "36f2a70cddeb5a0889d4fd8295c241b7e9848e89cf9e599d0eed2d8e5350fbf5";
|
|
9
|
+
const GITLAB_DUO_WORKFLOW_OAUTH_REDIRECT_URI = "vscode://gitlab.gitlab-workflow/authentication";
|
|
10
|
+
const OAUTH_SCOPES = ["api"];
|
|
11
|
+
function mapTokenResponse(payload) {
|
|
12
|
+
if (!payload.access_token || !payload.refresh_token || typeof payload.expires_in !== "number") throw new OAuthError("GitLab Duo Workflow OAuth token response missing required fields", {
|
|
13
|
+
kind: "validation",
|
|
14
|
+
provider: "gitlab-duo-workflow"
|
|
15
|
+
});
|
|
16
|
+
const createdAtMs = typeof payload.created_at === "number" && Number.isFinite(payload.created_at) ? payload.created_at * 1e3 : Date.now();
|
|
17
|
+
return {
|
|
18
|
+
access: payload.access_token,
|
|
19
|
+
refresh: payload.refresh_token,
|
|
20
|
+
expires: createdAtMs + payload.expires_in * 1e3 - 3e5
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
var GitLabDuoWorkflowOAuthFlow = class extends OAuthCallbackFlow {
|
|
24
|
+
#pkce;
|
|
25
|
+
#fetch;
|
|
26
|
+
constructor(ctrl, pkce) {
|
|
27
|
+
super(ctrl, {
|
|
28
|
+
preferredPort: 0,
|
|
29
|
+
redirectUri: GITLAB_DUO_WORKFLOW_OAUTH_REDIRECT_URI
|
|
30
|
+
});
|
|
31
|
+
this.#pkce = pkce;
|
|
32
|
+
this.#fetch = ctrl.fetch ?? fetch;
|
|
33
|
+
}
|
|
34
|
+
async generateAuthUrl(state) {
|
|
35
|
+
const authParams = new URLSearchParams({
|
|
36
|
+
client_id: GITLAB_DUO_WORKFLOW_OAUTH_CLIENT_ID,
|
|
37
|
+
redirect_uri: GITLAB_DUO_WORKFLOW_OAUTH_REDIRECT_URI,
|
|
38
|
+
response_type: "code",
|
|
39
|
+
scope: OAUTH_SCOPES.join(" "),
|
|
40
|
+
code_challenge: this.#pkce.challenge,
|
|
41
|
+
code_challenge_method: "S256",
|
|
42
|
+
state
|
|
43
|
+
});
|
|
44
|
+
return {
|
|
45
|
+
url: `${GITLAB_COM_URL}/oauth/authorize?${authParams.toString()}`,
|
|
46
|
+
instructions: "Complete GitLab login in your browser. This uses GitLab's official VS Code OAuth application. If the redirect opens VS Code instead of returning to OMP, copy the full vscode://gitlab.gitlab-workflow/authentication?... callback URL from VS Code/browser and paste it back into OMP."
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
async exchangeToken(code) {
|
|
50
|
+
const response = await this.#fetch(`${GITLAB_COM_URL}/oauth/token`, {
|
|
51
|
+
method: "POST",
|
|
52
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
53
|
+
body: new URLSearchParams({
|
|
54
|
+
client_id: GITLAB_DUO_WORKFLOW_OAUTH_CLIENT_ID,
|
|
55
|
+
redirect_uri: GITLAB_DUO_WORKFLOW_OAUTH_REDIRECT_URI,
|
|
56
|
+
grant_type: "authorization_code",
|
|
57
|
+
code,
|
|
58
|
+
code_verifier: this.#pkce.verifier
|
|
59
|
+
}).toString()
|
|
60
|
+
});
|
|
61
|
+
if (!response.ok) throw new OAuthError(`GitLab Duo Workflow OAuth token exchange failed: ${response.status} ${await response.text()}`, {
|
|
62
|
+
kind: "token-exchange",
|
|
63
|
+
provider: "gitlab-duo-workflow",
|
|
64
|
+
status: response.status
|
|
65
|
+
});
|
|
66
|
+
return mapTokenResponse(await response.json());
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
async function loginGitLabDuoWorkflow(callbacks) {
|
|
70
|
+
return new GitLabDuoWorkflowOAuthFlow(callbacks, await generatePKCE()).login();
|
|
71
|
+
}
|
|
72
|
+
async function refreshGitLabDuoWorkflowToken(credentials, fetchImpl = fetch) {
|
|
73
|
+
const response = await fetchImpl(`${GITLAB_COM_URL}/oauth/token`, {
|
|
74
|
+
method: "POST",
|
|
75
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
76
|
+
body: new URLSearchParams({
|
|
77
|
+
client_id: GITLAB_DUO_WORKFLOW_OAUTH_CLIENT_ID,
|
|
78
|
+
redirect_uri: GITLAB_DUO_WORKFLOW_OAUTH_REDIRECT_URI,
|
|
79
|
+
grant_type: "refresh_token",
|
|
80
|
+
refresh_token: credentials.refresh
|
|
81
|
+
}).toString()
|
|
82
|
+
});
|
|
83
|
+
if (!response.ok) throw new OAuthError(`GitLab Duo Workflow OAuth refresh failed: ${response.status} ${await response.text()}`, {
|
|
84
|
+
kind: "token-refresh",
|
|
85
|
+
provider: "gitlab-duo-workflow",
|
|
86
|
+
status: response.status
|
|
87
|
+
});
|
|
88
|
+
return mapTokenResponse(await response.json());
|
|
89
|
+
}
|
|
90
|
+
//#endregion
|
|
91
|
+
export { loginGitLabDuoWorkflow, refreshGitLabDuoWorkflowToken };
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { installBunShim as __installBunShim } from "./bun-shim.mjs";
|
|
2
|
+
__installBunShim();
|
|
3
|
+
import { c as OAuthError, h as LoginCancelledError } from "./error-B3bevhrs.mjs";
|
|
4
|
+
import { n as getAntigravityUserAgent, r as getAntigravityVersion } from "./gemini-headers-DKUShltF.mjs";
|
|
5
|
+
import { n as runGoogleOAuthLogin, r as throwIfLoginCancelled, t as oauthFetch } from "./google-oauth-shared-CwNWYdmR.mjs";
|
|
6
|
+
//#region node_modules/.pnpm/@oh-my-pi+pi-ai@17.3.5/node_modules/@oh-my-pi/pi-ai/src/registry/oauth/google-antigravity.ts
|
|
7
|
+
/**
|
|
8
|
+
* Antigravity OAuth flow (Gemini 3, Claude, GPT-OSS via Google Cloud)
|
|
9
|
+
* Uses different OAuth credentials than google-gemini-cli for access to additional models.
|
|
10
|
+
*/
|
|
11
|
+
const decode = (s) => atob(s);
|
|
12
|
+
const CLIENT_ID = decode("MTA3MTAwNjA2MDU5MS10bWhzc2luMmgyMWxjcmUyMzV2dG9sb2poNGc0MDNlcC5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbQ==");
|
|
13
|
+
const CLIENT_SECRET = decode("R09DU1BYLUs1OEZXUjQ4NkxkTEoxbUxCOHNYQzR6NnFEQWY=");
|
|
14
|
+
const CALLBACK_PORT = 51121;
|
|
15
|
+
const CALLBACK_PATH = "/oauth-callback";
|
|
16
|
+
const SCOPES = [
|
|
17
|
+
"https://www.googleapis.com/auth/cloud-platform",
|
|
18
|
+
"https://www.googleapis.com/auth/userinfo.email",
|
|
19
|
+
"https://www.googleapis.com/auth/userinfo.profile",
|
|
20
|
+
"https://www.googleapis.com/auth/cclog",
|
|
21
|
+
"https://www.googleapis.com/auth/experimentsandconfigs"
|
|
22
|
+
];
|
|
23
|
+
const AUTH_URL = "https://accounts.google.com/o/oauth2/v2/auth";
|
|
24
|
+
const TOKEN_URL = "https://oauth2.googleapis.com/token";
|
|
25
|
+
const CLOUD_CODE_ENDPOINT = "https://cloudcode-pa.googleapis.com";
|
|
26
|
+
const DAILY_CLOUD_CODE_ENDPOINT = "https://daily-cloudcode-pa.googleapis.com";
|
|
27
|
+
const NODE_API_CLIENT_USER_AGENT = "google-api-nodejs-client/10.3.0";
|
|
28
|
+
const GOOG_API_CLIENT_HEADER = "gl-node/22.21.1";
|
|
29
|
+
const TIER_FREE = "free-tier";
|
|
30
|
+
const PROJECT_ONBOARD_MAX_ATTEMPTS = 5;
|
|
31
|
+
const PROJECT_ONBOARD_INTERVAL_MS = 2e3;
|
|
32
|
+
const ANTIGRAVITY_LOAD_CODE_ASSIST_METADATA = Object.freeze({ ideType: "ANTIGRAVITY" });
|
|
33
|
+
function getAntigravityOnboardMetadata() {
|
|
34
|
+
return {
|
|
35
|
+
ide_type: "ANTIGRAVITY",
|
|
36
|
+
ide_version: getAntigravityVersion(),
|
|
37
|
+
ide_name: "antigravity"
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function readProjectId(value) {
|
|
41
|
+
if (typeof value === "string" && value.length > 0) return value.trim();
|
|
42
|
+
if (value && typeof value === "object" && "id" in value && typeof value.id === "string") {
|
|
43
|
+
const id = value.id.trim();
|
|
44
|
+
if (id.length > 0) return id;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function extractProjectId(payload) {
|
|
48
|
+
if (!payload || typeof payload !== "object") return void 0;
|
|
49
|
+
const record = payload;
|
|
50
|
+
for (const key of [
|
|
51
|
+
"cloudaicompanionProject",
|
|
52
|
+
"projectId",
|
|
53
|
+
"project"
|
|
54
|
+
]) {
|
|
55
|
+
const id = readProjectId(record[key]);
|
|
56
|
+
if (id) return id;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
function getDefaultTierId(allowedTiers, currentTier) {
|
|
60
|
+
if (allowedTiers && allowedTiers.length > 0) {
|
|
61
|
+
const defaultTier = allowedTiers.find((tier) => tier.isDefault && typeof tier.id === "string" && tier.id.trim().length > 0);
|
|
62
|
+
if (defaultTier?.id) return defaultTier.id.trim();
|
|
63
|
+
}
|
|
64
|
+
if (currentTier && typeof currentTier.id === "string" && currentTier.id.trim().length > 0) return currentTier.id.trim();
|
|
65
|
+
return TIER_FREE;
|
|
66
|
+
}
|
|
67
|
+
async function onboardProjectWithRetries(endpoint, headers, onboardBody, signal, onProgress) {
|
|
68
|
+
for (let attempt = 1; attempt <= PROJECT_ONBOARD_MAX_ATTEMPTS; attempt += 1) {
|
|
69
|
+
if (attempt > 1) {
|
|
70
|
+
onProgress?.(`Waiting for project provisioning (attempt ${attempt}/${PROJECT_ONBOARD_MAX_ATTEMPTS})...`);
|
|
71
|
+
throwIfLoginCancelled(signal);
|
|
72
|
+
await Bun.sleep(PROJECT_ONBOARD_INTERVAL_MS);
|
|
73
|
+
}
|
|
74
|
+
throwIfLoginCancelled(signal);
|
|
75
|
+
const onboardResponse = await oauthFetch(`${endpoint}/v1internal:onboardUser`, {
|
|
76
|
+
method: "POST",
|
|
77
|
+
headers,
|
|
78
|
+
body: JSON.stringify(onboardBody)
|
|
79
|
+
}, {
|
|
80
|
+
provider: "google-antigravity",
|
|
81
|
+
signal
|
|
82
|
+
});
|
|
83
|
+
if (!onboardResponse.ok) {
|
|
84
|
+
const errorText = await onboardResponse.text();
|
|
85
|
+
throw new OAuthError(`onboardUser failed: ${onboardResponse.status} ${onboardResponse.statusText}: ${errorText}`, {
|
|
86
|
+
kind: "provisioning",
|
|
87
|
+
provider: "google-antigravity",
|
|
88
|
+
status: onboardResponse.status
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
const operation = await onboardResponse.json();
|
|
92
|
+
if (!operation.done) continue;
|
|
93
|
+
const projectId = extractProjectId(operation.response);
|
|
94
|
+
if (projectId) return projectId;
|
|
95
|
+
}
|
|
96
|
+
throw new OAuthError(`onboardUser did not return a provisioned project id after ${PROJECT_ONBOARD_MAX_ATTEMPTS} attempts`, {
|
|
97
|
+
kind: "provisioning",
|
|
98
|
+
provider: "google-antigravity"
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
async function discoverProject(accessToken, onProgress, signal) {
|
|
102
|
+
const headers = {
|
|
103
|
+
Authorization: `Bearer ${accessToken}`,
|
|
104
|
+
"Content-Type": "application/json",
|
|
105
|
+
"User-Agent": getAntigravityUserAgent()
|
|
106
|
+
};
|
|
107
|
+
onProgress?.("Checking for existing project...");
|
|
108
|
+
try {
|
|
109
|
+
let lastErrorText;
|
|
110
|
+
let lastStatus;
|
|
111
|
+
let fallbackTierId = TIER_FREE;
|
|
112
|
+
let loadedSuccessfully = false;
|
|
113
|
+
for (const endpoint of [DAILY_CLOUD_CODE_ENDPOINT, CLOUD_CODE_ENDPOINT]) {
|
|
114
|
+
throwIfLoginCancelled(signal);
|
|
115
|
+
const loadResponse = await oauthFetch(`${endpoint}/v1internal:loadCodeAssist`, {
|
|
116
|
+
method: "POST",
|
|
117
|
+
headers,
|
|
118
|
+
body: JSON.stringify({ metadata: ANTIGRAVITY_LOAD_CODE_ASSIST_METADATA })
|
|
119
|
+
}, {
|
|
120
|
+
provider: "google-antigravity",
|
|
121
|
+
signal
|
|
122
|
+
});
|
|
123
|
+
if (!loadResponse.ok) {
|
|
124
|
+
lastStatus = loadResponse.status;
|
|
125
|
+
lastErrorText = await loadResponse.text();
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
loadedSuccessfully = true;
|
|
129
|
+
const loadPayload = await loadResponse.json();
|
|
130
|
+
const existingProject = extractProjectId(loadPayload);
|
|
131
|
+
if (existingProject) return existingProject;
|
|
132
|
+
fallbackTierId = getDefaultTierId(loadPayload.allowedTiers, loadPayload.currentTier);
|
|
133
|
+
}
|
|
134
|
+
if (!loadedSuccessfully && lastStatus !== void 0) throw new OAuthError(`loadCodeAssist failed: ${lastStatus}: ${lastErrorText || "unknown error"}`, {
|
|
135
|
+
kind: "discovery",
|
|
136
|
+
status: lastStatus
|
|
137
|
+
});
|
|
138
|
+
onProgress?.("Provisioning project...");
|
|
139
|
+
const onboardBody = {
|
|
140
|
+
tier_id: fallbackTierId,
|
|
141
|
+
metadata: getAntigravityOnboardMetadata()
|
|
142
|
+
};
|
|
143
|
+
const onboardHeaders = {
|
|
144
|
+
...headers,
|
|
145
|
+
"User-Agent": `${headers["User-Agent"]} ${NODE_API_CLIENT_USER_AGENT}`,
|
|
146
|
+
"X-Goog-Api-Client": GOOG_API_CLIENT_HEADER
|
|
147
|
+
};
|
|
148
|
+
return await onboardProjectWithRetries(DAILY_CLOUD_CODE_ENDPOINT, onboardHeaders, onboardBody, signal, onProgress);
|
|
149
|
+
} catch (error) {
|
|
150
|
+
if (error instanceof LoginCancelledError || error instanceof OAuthError) throw error;
|
|
151
|
+
throw new OAuthError(`Could not discover or provision an Antigravity project. ${error instanceof Error ? error.message : String(error)}`, {
|
|
152
|
+
kind: "discovery",
|
|
153
|
+
provider: "google-antigravity",
|
|
154
|
+
cause: error
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
async function loginAntigravity(ctrl) {
|
|
159
|
+
return runGoogleOAuthLogin(ctrl, {
|
|
160
|
+
provider: "google-antigravity",
|
|
161
|
+
clientId: CLIENT_ID,
|
|
162
|
+
clientSecret: CLIENT_SECRET,
|
|
163
|
+
authUrl: AUTH_URL,
|
|
164
|
+
tokenUrl: TOKEN_URL,
|
|
165
|
+
scopes: SCOPES,
|
|
166
|
+
callbackPort: CALLBACK_PORT,
|
|
167
|
+
callbackPath: CALLBACK_PATH,
|
|
168
|
+
discoverProject
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Refresh Antigravity token
|
|
173
|
+
*/
|
|
174
|
+
async function refreshAntigravityToken(refreshToken, projectId) {
|
|
175
|
+
const response = await fetch(TOKEN_URL, {
|
|
176
|
+
method: "POST",
|
|
177
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
178
|
+
body: new URLSearchParams({
|
|
179
|
+
client_id: CLIENT_ID,
|
|
180
|
+
client_secret: CLIENT_SECRET,
|
|
181
|
+
refresh_token: refreshToken,
|
|
182
|
+
grant_type: "refresh_token"
|
|
183
|
+
})
|
|
184
|
+
});
|
|
185
|
+
if (!response.ok) {
|
|
186
|
+
const error = await response.text();
|
|
187
|
+
throw new OAuthError(`Antigravity token refresh failed: ${error}`, { kind: "token-refresh" });
|
|
188
|
+
}
|
|
189
|
+
const data = await response.json();
|
|
190
|
+
return {
|
|
191
|
+
refresh: data.refresh_token || refreshToken,
|
|
192
|
+
access: data.access_token,
|
|
193
|
+
expires: Date.now() + data.expires_in * 1e3 - 3e5,
|
|
194
|
+
projectId
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
//#endregion
|
|
198
|
+
export { loginAntigravity, refreshAntigravityToken };
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
import { installBunShim as __installBunShim } from "./bun-shim.mjs";
|
|
2
|
+
__installBunShim();
|
|
3
|
+
import { F as $envpos, S as debug, y as isEnoent } from "./src-DTid0g4K.mjs";
|
|
4
|
+
import { c as OAuthError, g as MissingApiKeyError, t as ConfigurationError } from "./error-B3bevhrs.mjs";
|
|
5
|
+
import { n as raceWithSignal } from "./abort-B7izMMna.mjs";
|
|
6
|
+
import * as path from "node:path";
|
|
7
|
+
import * as os from "node:os";
|
|
8
|
+
import { Buffer } from "node:buffer";
|
|
9
|
+
//#region node_modules/.pnpm/@oh-my-pi+pi-ai@17.3.5/node_modules/@oh-my-pi/pi-ai/src/providers/google-auth.ts
|
|
10
|
+
/**
|
|
11
|
+
* Application Default Credentials (ADC) resolution for Vertex AI.
|
|
12
|
+
*
|
|
13
|
+
* Replaces `google-auth-library` with a direct WebCrypto + REST implementation.
|
|
14
|
+
* Sources, in priority order:
|
|
15
|
+
* 1. `GOOGLE_APPLICATION_CREDENTIALS` env → file with `type: "service_account"` (RS256 JWT exchange)
|
|
16
|
+
* or `type: "authorized_user"` (refresh-token exchange).
|
|
17
|
+
* 2. `~/.config/gcloud/application_default_credentials.json` (user ADC, same authorized_user flow).
|
|
18
|
+
* 3. GCE / Cloud Run metadata server (`metadata.google.internal`).
|
|
19
|
+
*
|
|
20
|
+
* Tokens are cached per source key and refreshed `GOOGLE_VERTEX_REFRESH_SKEW_MS` before expiry
|
|
21
|
+
* (default 60s). Concurrent callers waiting on a refresh share the same in-flight promise.
|
|
22
|
+
*/
|
|
23
|
+
const OAUTH_TOKEN_URL = "https://oauth2.googleapis.com/token";
|
|
24
|
+
const METADATA_TOKEN_URL = "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token";
|
|
25
|
+
const CLOUD_PLATFORM_SCOPE = "https://www.googleapis.com/auth/cloud-platform";
|
|
26
|
+
const JWT_BEARER_GRANT = "urn:ietf:params:oauth:grant-type:jwt-bearer";
|
|
27
|
+
const tokenCache = /* @__PURE__ */ new Map();
|
|
28
|
+
const inflight = /* @__PURE__ */ new Map();
|
|
29
|
+
function getRefreshSkewMs() {
|
|
30
|
+
return $envpos("GOOGLE_VERTEX_REFRESH_SKEW_MS", 6e4);
|
|
31
|
+
}
|
|
32
|
+
function userAdcPath() {
|
|
33
|
+
return path.join(os.homedir(), ".config", "gcloud", "application_default_credentials.json");
|
|
34
|
+
}
|
|
35
|
+
async function readJsonFile(filePath) {
|
|
36
|
+
try {
|
|
37
|
+
return await Bun.file(filePath).json();
|
|
38
|
+
} catch (err) {
|
|
39
|
+
if (isEnoent(err)) return void 0;
|
|
40
|
+
throw err;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
async function loadAdcCredentials() {
|
|
44
|
+
const gacPath = Bun.env.GOOGLE_APPLICATION_CREDENTIALS;
|
|
45
|
+
if (gacPath) {
|
|
46
|
+
const creds = await readJsonFile(gacPath);
|
|
47
|
+
if (!creds) throw new ConfigurationError(`GOOGLE_APPLICATION_CREDENTIALS points to a missing file: ${gacPath}`);
|
|
48
|
+
return {
|
|
49
|
+
source: `gac:${gacPath}`,
|
|
50
|
+
creds
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
const userPath = userAdcPath();
|
|
54
|
+
const creds = await readJsonFile(userPath);
|
|
55
|
+
if (creds) return {
|
|
56
|
+
source: `user:${userPath}`,
|
|
57
|
+
creds
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
function base64UrlEncode(bytes) {
|
|
61
|
+
const buf = typeof bytes === "string" ? Buffer.from(bytes, "utf8") : bytes;
|
|
62
|
+
return Buffer.from(buf.buffer, buf.byteOffset, buf.byteLength).toString("base64url");
|
|
63
|
+
}
|
|
64
|
+
function pemToPkcs8(pem) {
|
|
65
|
+
const body = pem.replace(/-----BEGIN [^-]+-----/g, "").replace(/-----END [^-]+-----/g, "").replace(/\s+/g, "");
|
|
66
|
+
if (!body) throw new ConfigurationError("Invalid PEM: empty body");
|
|
67
|
+
return Uint8Array.fromBase64(body);
|
|
68
|
+
}
|
|
69
|
+
async function signJwtRs256(claims, privateKeyPem, keyId) {
|
|
70
|
+
const header = {
|
|
71
|
+
alg: "RS256",
|
|
72
|
+
typ: "JWT"
|
|
73
|
+
};
|
|
74
|
+
if (keyId) header.kid = keyId;
|
|
75
|
+
const payload = `${base64UrlEncode(JSON.stringify(header))}.${base64UrlEncode(JSON.stringify(claims))}`;
|
|
76
|
+
const key = await globalThis.crypto.subtle.importKey("pkcs8", pemToPkcs8(privateKeyPem), {
|
|
77
|
+
name: "RSASSA-PKCS1-v1_5",
|
|
78
|
+
hash: "SHA-256"
|
|
79
|
+
}, false, ["sign"]);
|
|
80
|
+
return `${payload}.${base64UrlEncode(new Uint8Array(await globalThis.crypto.subtle.sign("RSASSA-PKCS1-v1_5", key, new TextEncoder().encode(payload))))}`;
|
|
81
|
+
}
|
|
82
|
+
async function exchangeJwtForToken(creds, signal, fetchImpl) {
|
|
83
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
84
|
+
const assertion = await signJwtRs256({
|
|
85
|
+
iss: creds.client_email,
|
|
86
|
+
scope: CLOUD_PLATFORM_SCOPE,
|
|
87
|
+
aud: OAUTH_TOKEN_URL,
|
|
88
|
+
exp: now + 3600,
|
|
89
|
+
iat: now
|
|
90
|
+
}, creds.private_key, creds.private_key_id);
|
|
91
|
+
const body = new URLSearchParams({
|
|
92
|
+
grant_type: JWT_BEARER_GRANT,
|
|
93
|
+
assertion
|
|
94
|
+
});
|
|
95
|
+
return postForToken(OAUTH_TOKEN_URL, body, signal, fetchImpl);
|
|
96
|
+
}
|
|
97
|
+
async function exchangeRefreshToken(creds, signal, fetchImpl) {
|
|
98
|
+
const body = new URLSearchParams({
|
|
99
|
+
client_id: creds.client_id,
|
|
100
|
+
client_secret: creds.client_secret,
|
|
101
|
+
refresh_token: creds.refresh_token,
|
|
102
|
+
grant_type: "refresh_token"
|
|
103
|
+
});
|
|
104
|
+
return postForToken(OAUTH_TOKEN_URL, body, signal, fetchImpl);
|
|
105
|
+
}
|
|
106
|
+
async function fetchMetadataToken(signal, fetchImpl) {
|
|
107
|
+
const timeout = AbortSignal.timeout(2e3);
|
|
108
|
+
const combined = signal ? AbortSignal.any([signal, timeout]) : timeout;
|
|
109
|
+
try {
|
|
110
|
+
const response = await fetchImpl(METADATA_TOKEN_URL, {
|
|
111
|
+
method: "GET",
|
|
112
|
+
headers: { "Metadata-Flavor": "Google" },
|
|
113
|
+
signal: combined
|
|
114
|
+
});
|
|
115
|
+
if (!response.ok) return void 0;
|
|
116
|
+
return await response.json();
|
|
117
|
+
} catch {
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
async function postForToken(url, body, signal, fetchImpl) {
|
|
122
|
+
const response = await fetchImpl(url, {
|
|
123
|
+
method: "POST",
|
|
124
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
125
|
+
body: body.toString(),
|
|
126
|
+
signal
|
|
127
|
+
});
|
|
128
|
+
if (!response.ok) {
|
|
129
|
+
const detail = await response.text().catch(() => "");
|
|
130
|
+
throw new OAuthError(`Google OAuth token exchange failed (${response.status}): ${detail}`, {
|
|
131
|
+
kind: "token-exchange",
|
|
132
|
+
provider: "google-vertex",
|
|
133
|
+
status: response.status
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
return await response.json();
|
|
137
|
+
}
|
|
138
|
+
async function resolveAccessTokenUncached(signal, fetchImpl) {
|
|
139
|
+
const adc = await loadAdcCredentials();
|
|
140
|
+
if (adc) {
|
|
141
|
+
const creds = adc.creds;
|
|
142
|
+
let token;
|
|
143
|
+
if (creds.type === "impersonated_service_account") {
|
|
144
|
+
const targetPrincipal = /(?<target>[^/]+):(generateAccessToken|generateIdToken)$/.exec(creds.service_account_impersonation_url)?.groups?.target;
|
|
145
|
+
if (!targetPrincipal) throw new RangeError(`Cannot extract target principal from ${creds.service_account_impersonation_url}`);
|
|
146
|
+
const sourceToken = creds.source_credentials.type === "service_account" ? await exchangeJwtForToken(creds.source_credentials, signal, fetchImpl) : await exchangeRefreshToken(creds.source_credentials, signal, fetchImpl);
|
|
147
|
+
const response = await fetchImpl(`https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/${targetPrincipal}:generateAccessToken`, {
|
|
148
|
+
method: "POST",
|
|
149
|
+
headers: {
|
|
150
|
+
"Content-Type": "application/json",
|
|
151
|
+
Authorization: `Bearer ${sourceToken.access_token}`
|
|
152
|
+
},
|
|
153
|
+
body: JSON.stringify({
|
|
154
|
+
delegates: creds.delegates ?? [],
|
|
155
|
+
scope: [CLOUD_PLATFORM_SCOPE],
|
|
156
|
+
lifetime: "3600s"
|
|
157
|
+
}),
|
|
158
|
+
signal
|
|
159
|
+
});
|
|
160
|
+
if (!response.ok) {
|
|
161
|
+
const detail = await response.text().catch(() => "");
|
|
162
|
+
throw new OAuthError(`Google Impersonation token exchange failed (${response.status}): ${detail}`, {
|
|
163
|
+
kind: "token-exchange",
|
|
164
|
+
provider: "google-vertex",
|
|
165
|
+
status: response.status
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
const data = await response.json();
|
|
169
|
+
const expiresIn = Math.max(0, Math.floor((new Date(data.expireTime).getTime() - Date.now()) / 1e3));
|
|
170
|
+
token = {
|
|
171
|
+
access_token: data.accessToken,
|
|
172
|
+
expires_in: expiresIn,
|
|
173
|
+
token_type: "Bearer"
|
|
174
|
+
};
|
|
175
|
+
} else token = creds.type === "service_account" ? await exchangeJwtForToken(creds, signal, fetchImpl) : await exchangeRefreshToken(creds, signal, fetchImpl);
|
|
176
|
+
return {
|
|
177
|
+
source: adc.source,
|
|
178
|
+
token
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
const metadata = await fetchMetadataToken(signal, fetchImpl);
|
|
182
|
+
if (metadata) return {
|
|
183
|
+
source: "metadata",
|
|
184
|
+
token: metadata
|
|
185
|
+
};
|
|
186
|
+
throw new MissingApiKeyError(void 0, "Vertex AI requires Application Default Credentials. Set GOOGLE_APPLICATION_CREDENTIALS, run `gcloud auth application-default login`, or run on a GCE/Cloud Run instance with a service account.");
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Bound for the detached (signal-free) shared token resolution: a hung OAuth
|
|
190
|
+
* exchange or metadata fetch must not pin the inflight slot forever — every
|
|
191
|
+
* later call would await the stuck promise until process restart.
|
|
192
|
+
*/
|
|
193
|
+
const SHARED_TOKEN_RESOLVE_TIMEOUT_MS = 3e4;
|
|
194
|
+
/**
|
|
195
|
+
* Returns a Bearer access token suitable for the `Authorization` header on Vertex AI calls.
|
|
196
|
+
* The token is cached in module scope and refreshed `GOOGLE_VERTEX_REFRESH_SKEW_MS` ms before it expires.
|
|
197
|
+
*/
|
|
198
|
+
async function getVertexAccessToken(options) {
|
|
199
|
+
const explicitToken = Bun.env.GOOGLE_CLOUD_ACCESS_TOKEN || Bun.env.CLOUDSDK_AUTH_ACCESS_TOKEN;
|
|
200
|
+
if (explicitToken) return explicitToken;
|
|
201
|
+
const fetchImpl = options?.fetch ?? globalThis.fetch.bind(globalThis);
|
|
202
|
+
const skew = getRefreshSkewMs();
|
|
203
|
+
const now = Date.now();
|
|
204
|
+
for (const [source, cached] of tokenCache) {
|
|
205
|
+
if (cached.expiresAtMs - skew > now) return cached.token;
|
|
206
|
+
tokenCache.delete(source);
|
|
207
|
+
}
|
|
208
|
+
const cacheKey = "vertex-adc";
|
|
209
|
+
const existing = inflight.get(cacheKey);
|
|
210
|
+
if (existing) return raceWithSignal(existing, options?.signal);
|
|
211
|
+
const promise = (async () => {
|
|
212
|
+
try {
|
|
213
|
+
const { source, token } = await resolveAccessTokenUncached(AbortSignal.timeout(SHARED_TOKEN_RESOLVE_TIMEOUT_MS), fetchImpl);
|
|
214
|
+
const expiresAtMs = Date.now() + Math.max(0, token.expires_in * 1e3);
|
|
215
|
+
tokenCache.set(source, {
|
|
216
|
+
token: token.access_token,
|
|
217
|
+
expiresAtMs
|
|
218
|
+
});
|
|
219
|
+
debug("vertex.adc acquired access token", {
|
|
220
|
+
source,
|
|
221
|
+
expiresInSec: token.expires_in
|
|
222
|
+
});
|
|
223
|
+
return token.access_token;
|
|
224
|
+
} finally {
|
|
225
|
+
inflight.delete(cacheKey);
|
|
226
|
+
}
|
|
227
|
+
})();
|
|
228
|
+
inflight.set(cacheKey, promise);
|
|
229
|
+
return raceWithSignal(promise, options?.signal);
|
|
230
|
+
}
|
|
231
|
+
//#endregion
|
|
232
|
+
export { getVertexAccessToken as t };
|