@xiaoso/dsh-tool-plus 0.1.16 → 0.1.17-beta.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/lib/{abort-DZ54CaKU.mjs → abort-BTblp0Rt.mjs} +2 -2
- package/lib/{alibaba-coding-plan-DODpkcqi.mjs → alibaba-coding-plan-t3R4YKCB.mjs} +3 -3
- package/lib/{alibaba-token-plan-C6lpKCda.mjs → alibaba-token-plan-CO4djG1y.mjs} +4 -4
- package/lib/{alibaba-token-plan-CHGyWOfX.mjs → alibaba-token-plan-CUjYJX0-.mjs} +1 -1
- package/lib/{anthropic-Dv_GGX6g.mjs → anthropic-nf7w6so1.mjs} +48 -21
- package/lib/{api-key-validation-MnMf_ihX.mjs → api-key-validation-C_tZ7Y9a.mjs} +2 -2
- package/lib/behavior-BwvTUtag.mjs +111 -0
- package/lib/{browser-render-BZXt548F.mjs → browser-render-BQaEVK_n.mjs} +4 -4
- package/lib/{reference-CtvM4zLU.mjs → bundled-references-CrQ4dQcT.mjs} +57 -4
- package/lib/cascade-BWjRTD1q.mjs +30265 -0
- package/lib/{cline-pass-BT9CBEOj.mjs → cline-pass-Bjm-O8GG.mjs} +2 -2
- package/lib/cloudflare-CKXRJ0l9.mjs +37 -0
- package/lib/{cloudflare-ai-gateway-DReN6ohJ.mjs → cloudflare-ai-gateway-BpnBSjwV.mjs} +8 -4
- package/lib/cloudflare-workers-ai-odj9XswL.mjs +32 -0
- package/lib/collapse-_nkb2dn7.mjs +1945 -0
- package/lib/{coreweave-C82HrLpb.mjs → coreweave-CGDZOD8-.mjs} +1 -1
- package/lib/{coreweave-C68UgRQO.mjs → coreweave-DwffcgW5.mjs} +4 -4
- package/lib/cursor-BgOuV7Qf.mjs +794 -0
- package/lib/{cursor-_gHHq-Dq.mjs → cursor-CF1iHHbv.mjs} +68 -19
- package/lib/{cursor-proto-Cr_WEMuv.mjs → cursor-proto-BuNTjX3L.mjs} +823 -23
- package/lib/{devin-QpfTSl9H.mjs → devin-7OEeEb80.mjs} +112 -31
- package/lib/{devin-proto-DYhp4Ty6.mjs → devin-proto-C-QreeAv.mjs} +71 -5
- package/lib/{dom-DG3sPESc.mjs → dom-BmbZv4v9.mjs} +598 -182
- package/lib/{error-O63pC8zg.mjs → error-8LVo7tug.mjs} +725 -104
- package/lib/factory-droid-ChhmsGWb.mjs +71 -0
- package/lib/{fs-promises-shim-B2YFWkcd.mjs → fs-promises-shim-CANAxFWh.mjs} +10 -1
- package/lib/{github-copilot-BMEcw8N1.mjs → github-copilot-QwevdT30.mjs} +4 -4
- package/lib/{github-copilot-headers-DnjGEbko.mjs → github-copilot-headers-CAUZ0rUD.mjs} +138 -26
- package/lib/{gitlab-duo-DnHqJjFY.mjs → gitlab-duo-DigV7k_o.mjs} +2 -2
- package/lib/{google-antigravity-B1mSckrK.mjs → google-antigravity-D-oe0r8A.mjs} +6 -7
- package/lib/{google-gemini-cli-DJwThCCn.mjs → google-gemini-cli-CQBHgGJT.mjs} +5 -6
- package/lib/{google-oauth-shared-BctLpVUN.mjs → google-oauth-shared-CvgVIUwJ.mjs} +2 -2
- package/lib/google-validation-CdvRj4ec.mjs +126 -0
- package/lib/id-EJwVLDHE.mjs +2548 -0
- package/lib/index.mjs +248 -258
- package/lib/{kilo-BEgEwMJQ.mjs → kilo-5r6OffCa.mjs} +2 -2
- package/lib/{kimi-T9NldEIJ.mjs → kimi-DOOtbXmm.mjs} +9 -10
- package/lib/{launch-BIWNyrBB.mjs → launch-DkAjib7h.mjs} +1 -1
- package/lib/{markit-Dvp2JPdT.mjs → markit-CCcyeAds.mjs} +359 -140
- package/lib/{models-DnXMYGcJ.mjs → models-DCpDT_im.mjs} +199203 -112275
- package/lib/{muse-code-CNvqqAp6.mjs → muse-code-CYf8zj_B.mjs} +5 -5
- package/lib/{openai-codex-D5-CyTxa.mjs → openai-codex-Cj-TvSFh.mjs} +13 -10
- package/lib/{perplexity-A2PEoGaC.mjs → perplexity-Dh_Qgsmx.mjs} +68 -25
- package/lib/{pkce-BYjmugmw.mjs → pkce-DO-jBJLV.mjs} +1 -1
- package/lib/pricing-DusBEhwm.mjs +593 -0
- package/lib/{readability-uGhqb4GC.mjs → readability-XHK0o3bv.mjs} +287 -27
- package/lib/{scrapers-C1ujjV8k.mjs → scrapers-B6PADOVm.mjs} +13 -13
- package/lib/slugify-ynYWBIA5.mjs +11 -0
- package/lib/snowflake-B_jap6lz.mjs +666 -0
- package/lib/snowflake-Cu1ZyOp6.mjs +151 -0
- package/lib/{src-AELUUb5U.mjs → src-BhinCSpi.mjs} +1172 -458
- package/lib/{stream-AVOoe5Hj.mjs → stream-D2ivg3GH.mjs} +3740 -5311
- package/lib/{turndown-D6fof1OX.mjs → turndown-Vya8SavL.mjs} +82 -30
- package/lib/types/tools/hashline/native/index.d.ts +2 -2
- package/lib/types/tools/hashline/native/policy.d.ts +19 -21
- package/lib/types/tools/omp/session/agent-storage.d.ts +3 -3
- package/lib/types/tools/shared/bun-named-shim.d.ts +5 -0
- package/lib/{types-BLrLohwK.mjs → types-tH1v9uRm.mjs} +2 -2
- package/lib/{utils-cZX3f_Ls.mjs → utils-C_Ncya1r.mjs} +1737 -509
- package/lib/utils-D2tK38xq.mjs +34006 -0
- package/lib/{utils-I4I8azHN.mjs → utils-DrDwmNtu.mjs} +8 -3
- package/lib/{xai-oauth-CbeldUSV.mjs → xai-oauth-DLLzX6my.mjs} +4 -4
- package/lib/{xiaomi-Dl3VSs04.mjs → xiaomi-CqK-KivK.mjs} +2 -2
- package/lib/{zai-FyjGSypr.mjs → zai-DoJ2xPIH.mjs} +2 -2
- package/lib/{zip-DRrycScC.mjs → zip-DG1mUV6X.mjs} +1 -1
- package/package.json +8 -8
- package/lib/amazon-bedrock-Dx0rr9dY.mjs +0 -996
- package/lib/anthropic-ClCw0PV_.mjs +0 -3624
- package/lib/anthropic-wire-lbGAFzYb.mjs +0 -927
- package/lib/azure-openai-responses-WE_bgFWp.mjs +0 -285
- package/lib/bundled-references-DY3EJxZV.mjs +0 -56
- package/lib/cloudflare-ai-gateway-CrMa97Ap.mjs +0 -44
- package/lib/collapse-CkMNRNr7.mjs +0 -2304
- package/lib/cursor-C6jaIJDg.mjs +0 -283
- package/lib/cursor-D-XZYDf_.mjs +0 -4544
- package/lib/deterministic-id-CUEIMSqR.mjs +0 -17
- package/lib/devin-ExGIghmx.mjs +0 -69
- package/lib/devin-u0ljw5P6.mjs +0 -628
- package/lib/effort-BdtQMN-_.mjs +0 -23
- package/lib/event-stream-BKEtb45Y.mjs +0 -167
- package/lib/gemini-headers-Co9cVvex.mjs +0 -54
- package/lib/google-auth-qAN-6DMW.mjs +0 -232
- package/lib/google-gemini-cli-B2Aw1S5w.mjs +0 -844
- package/lib/google-lTxuq28n.mjs +0 -38
- package/lib/google-shared-Y01j9xOr.mjs +0 -856
- package/lib/google-validation-BEkNs-Bx.mjs +0 -18
- package/lib/google-vertex-DcM-FRC5.mjs +0 -99
- package/lib/hosts-00rjRzUD.mjs +0 -203
- package/lib/id-AL5obQzR.mjs +0 -71
- package/lib/idle-iterator-D0ZXEcUq.mjs +0 -366
- package/lib/ollama-6R0oXZks.mjs +0 -574
- package/lib/openai-codex-responses-C8bnBWOe.mjs +0 -3232
- package/lib/openai-completions-DNr3mUsn.mjs +0 -1430
- package/lib/openai-configuration-update-xMYUjaK_.mjs +0 -150
- package/lib/openai-reasoning-fallback-Ju-5pSR8.mjs +0 -380
- package/lib/openai-responses-CjpafAEr.mjs +0 -861
- package/lib/protobuf-BMgDYu_U.mjs +0 -717
- package/lib/provider-response-SqKSkkUc.mjs +0 -22
- package/lib/proxy-DxvCQOCA.mjs +0 -230
- package/lib/request-debug-BwPOqN_j.mjs +0 -183
- package/lib/sanitize-text-BCf5KmCf.mjs +0 -33
- package/lib/sse-debug-B-tkLCPW.mjs +0 -11
- package/lib/stream-markup-healing-CN3RsqG9.mjs +0 -267
- package/lib/strict-tool-validation-CBTz1dAA.mjs +0 -105
- package/lib/taxonomy-DSIM99rS.mjs +0 -15392
- package/lib/thinking-ngMwf_1Y.mjs +0 -336
- package/lib/type-guards-CttAANEx.mjs +0 -11
- package/lib/utils-CE3DSebh.mjs +0 -11763
- package/lib/vision-guard-BCpXWUj3.mjs +0 -77
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
import { installBunShim as __installBunShim } from "./bun-shim.mjs";
|
|
2
|
-
__installBunShim();
|
|
3
|
-
import { s as ProviderResponseError, w as classifyMessage } from "./error-O63pC8zg.mjs";
|
|
4
|
-
//#region node_modules/.pnpm/@oh-my-pi+pi-ai@18.1.17/node_modules/@oh-my-pi/pi-ai/src/utils/event-stream.ts
|
|
5
|
-
var EventStream = class {
|
|
6
|
-
queue = [];
|
|
7
|
-
waiting = [];
|
|
8
|
-
done = false;
|
|
9
|
-
/** True once finalResultPromise has been resolved or rejected. */
|
|
10
|
-
resultSettled = false;
|
|
11
|
-
#failed = false;
|
|
12
|
-
#error = void 0;
|
|
13
|
-
/**
|
|
14
|
-
* Consumer-side local operations currently in flight for this stream — a
|
|
15
|
-
* provider transport waiting on a server-requested local tool bridge
|
|
16
|
-
* (e.g. the Cursor exec channel) before it can send the result upstream.
|
|
17
|
-
* While non-zero, event silence is attributable to our own pending work,
|
|
18
|
-
* not a provider stall; idle watchdogs consult {@link hasPendingLocalWork}.
|
|
19
|
-
*/
|
|
20
|
-
#pendingLocalWork = 0;
|
|
21
|
-
/**
|
|
22
|
-
* A downstream stream whose local work also counts as ours — set when this
|
|
23
|
-
* stream forwards another stream's events (e.g. the Cursor discovered-id
|
|
24
|
-
* retry drains an inner stream), so the watchdog on this stream sees the
|
|
25
|
-
* inner exec bridge's busy state instead of aborting a healthy tool run.
|
|
26
|
-
*/
|
|
27
|
-
#localWorkDelegate;
|
|
28
|
-
finalResultPromise;
|
|
29
|
-
resolveFinalResult;
|
|
30
|
-
rejectFinalResult;
|
|
31
|
-
isComplete;
|
|
32
|
-
extractResult;
|
|
33
|
-
constructor(isComplete, extractResult) {
|
|
34
|
-
const { promise, resolve, reject } = Promise.withResolvers();
|
|
35
|
-
promise.catch(() => {});
|
|
36
|
-
this.finalResultPromise = promise;
|
|
37
|
-
this.resolveFinalResult = resolve;
|
|
38
|
-
this.rejectFinalResult = reject;
|
|
39
|
-
this.isComplete = isComplete;
|
|
40
|
-
this.extractResult = extractResult;
|
|
41
|
-
}
|
|
42
|
-
push(event) {
|
|
43
|
-
if (this.done) return;
|
|
44
|
-
if (this.isComplete(event)) {
|
|
45
|
-
this.done = true;
|
|
46
|
-
this.resultSettled = true;
|
|
47
|
-
this.resolveFinalResult(this.extractResult(event));
|
|
48
|
-
}
|
|
49
|
-
const waiter = this.waiting.shift();
|
|
50
|
-
if (waiter) waiter.resolve({
|
|
51
|
-
value: event,
|
|
52
|
-
done: false
|
|
53
|
-
});
|
|
54
|
-
else this.queue.push(event);
|
|
55
|
-
}
|
|
56
|
-
deliver(event) {
|
|
57
|
-
const waiter = this.waiting.shift();
|
|
58
|
-
if (waiter) waiter.resolve({
|
|
59
|
-
value: event,
|
|
60
|
-
done: false
|
|
61
|
-
});
|
|
62
|
-
else this.queue.push(event);
|
|
63
|
-
}
|
|
64
|
-
end(result) {
|
|
65
|
-
this.done = true;
|
|
66
|
-
if (result !== void 0) {
|
|
67
|
-
this.resultSettled = true;
|
|
68
|
-
this.resolveFinalResult(result);
|
|
69
|
-
} else if (!this.resultSettled) {
|
|
70
|
-
this.resultSettled = true;
|
|
71
|
-
this.rejectFinalResult(new ProviderResponseError("Stream ended without a final result", { kind: "envelope" }));
|
|
72
|
-
}
|
|
73
|
-
while (this.waiting.length > 0) this.waiting.shift().resolve({
|
|
74
|
-
value: void 0,
|
|
75
|
-
done: true
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
endWaiting() {
|
|
79
|
-
while (this.waiting.length > 0) this.waiting.shift().resolve({
|
|
80
|
-
value: void 0,
|
|
81
|
-
done: true
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
fail(err) {
|
|
85
|
-
if (this.done) return;
|
|
86
|
-
this.done = true;
|
|
87
|
-
this.#failed = true;
|
|
88
|
-
this.#error = err;
|
|
89
|
-
this.resultSettled = true;
|
|
90
|
-
this.rejectFinalResult(err);
|
|
91
|
-
while (this.waiting.length > 0) this.waiting.shift().reject(err);
|
|
92
|
-
}
|
|
93
|
-
async *[Symbol.asyncIterator]() {
|
|
94
|
-
while (true) if (this.queue.length > 0) yield this.queue.shift();
|
|
95
|
-
else if (this.#failed) throw this.#error;
|
|
96
|
-
else if (this.done) return;
|
|
97
|
-
else {
|
|
98
|
-
const result = await new Promise((resolve, reject) => this.waiting.push({
|
|
99
|
-
resolve,
|
|
100
|
-
reject
|
|
101
|
-
}));
|
|
102
|
-
if (result.done) return;
|
|
103
|
-
yield result.value;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
result() {
|
|
107
|
-
return this.finalResultPromise;
|
|
108
|
-
}
|
|
109
|
-
/** True while local work tracked via {@link trackLocalWork} — on this stream or a forwarded delegate — is pending. */
|
|
110
|
-
get hasPendingLocalWork() {
|
|
111
|
-
return this.#pendingLocalWork > 0 || (this.#localWorkDelegate?.hasPendingLocalWork ?? false);
|
|
112
|
-
}
|
|
113
|
-
/**
|
|
114
|
-
* Count `source`'s pending local work as this stream's own. Used when this
|
|
115
|
-
* stream forwards another's events (Cursor discovered-id retry) so the
|
|
116
|
-
* watchdog does not abort a live tool run happening on the inner stream.
|
|
117
|
-
* Pass `undefined` to detach once forwarding ends.
|
|
118
|
-
*/
|
|
119
|
-
forwardLocalWorkFrom(source) {
|
|
120
|
-
this.#localWorkDelegate = source;
|
|
121
|
-
}
|
|
122
|
-
/**
|
|
123
|
-
* Track a local-work promise so idle watchdogs on this stream do not treat
|
|
124
|
-
* the event silence while it is pending as a provider stall.
|
|
125
|
-
*/
|
|
126
|
-
async trackLocalWork(work) {
|
|
127
|
-
this.#pendingLocalWork++;
|
|
128
|
-
try {
|
|
129
|
-
return await work;
|
|
130
|
-
} finally {
|
|
131
|
-
this.#pendingLocalWork--;
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
};
|
|
135
|
-
var AssistantMessageEventStream = class extends EventStream {
|
|
136
|
-
constructor() {
|
|
137
|
-
super((event) => event.type === "done" || event.type === "error", (event) => {
|
|
138
|
-
if (event.type === "done") return event.message;
|
|
139
|
-
else if (event.type === "error") return event.error;
|
|
140
|
-
throw new ProviderResponseError("Unexpected event type for final result", { kind: "envelope" });
|
|
141
|
-
});
|
|
142
|
-
}
|
|
143
|
-
push(event) {
|
|
144
|
-
if (this.done) return;
|
|
145
|
-
if (event.type === "error" && event.error.stopReason === "error") classifyMessage(event.error);
|
|
146
|
-
if (this.isComplete(event)) {
|
|
147
|
-
this.done = true;
|
|
148
|
-
this.resultSettled = true;
|
|
149
|
-
this.resolveFinalResult(this.extractResult(event));
|
|
150
|
-
}
|
|
151
|
-
this.deliver(event);
|
|
152
|
-
}
|
|
153
|
-
end(result) {
|
|
154
|
-
this.done = true;
|
|
155
|
-
if (result !== void 0) {
|
|
156
|
-
if (result.stopReason === "error") classifyMessage(result);
|
|
157
|
-
this.resultSettled = true;
|
|
158
|
-
this.resolveFinalResult(result);
|
|
159
|
-
} else if (!this.resultSettled) {
|
|
160
|
-
this.resultSettled = true;
|
|
161
|
-
this.rejectFinalResult(new ProviderResponseError("Stream ended without a final result", { kind: "envelope" }));
|
|
162
|
-
}
|
|
163
|
-
this.endWaiting();
|
|
164
|
-
}
|
|
165
|
-
};
|
|
166
|
-
//#endregion
|
|
167
|
-
export { AssistantMessageEventStream as t };
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { installBunShim as __installBunShim } from "./bun-shim.mjs";
|
|
2
|
-
__installBunShim();
|
|
3
|
-
//#region node_modules/.pnpm/@oh-my-pi+pi-catalog@18.1.17/node_modules/@oh-my-pi/pi-catalog/src/wire/gemini-headers.ts
|
|
4
|
-
/**
|
|
5
|
-
* Build a User-Agent string that identifies as Gemini CLI to unlock higher rate limits.
|
|
6
|
-
* Uses the same format as the official Gemini CLI (v0.35+):
|
|
7
|
-
* GeminiCLI/VERSION/MODEL (PLATFORM; ARCH; SURFACE)
|
|
8
|
-
*/
|
|
9
|
-
function getGeminiCliUserAgent(modelId = "gemini-3.1-pro-preview") {
|
|
10
|
-
return `GeminiCLI/${process.env.PI_AI_GEMINI_CLI_VERSION || "0.46.0"}/${modelId} (${process.platform === "win32" ? "win32" : process.platform}; ${process.arch === "x64" ? "x64" : process.arch}; terminal)`;
|
|
11
|
-
}
|
|
12
|
-
const getGeminiCliHeaders = (modelId) => ({
|
|
13
|
-
"User-Agent": getGeminiCliUserAgent(modelId),
|
|
14
|
-
"Client-Metadata": "ideType=IDE_UNSPECIFIED,platform=PLATFORM_UNSPECIFIED,pluginType=GEMINI"
|
|
15
|
-
});
|
|
16
|
-
/** Current Antigravity client version: env override → manifest-discovered → pinned fallback. */
|
|
17
|
-
function getAntigravityVersion() {
|
|
18
|
-
return process.env.PI_AI_ANTIGRAVITY_VERSION || "2.8.0";
|
|
19
|
-
}
|
|
20
|
-
/** Antigravity `User-Agent` header value; rebuilt when the discovered version changes. */
|
|
21
|
-
function getAntigravityUserAgent() {
|
|
22
|
-
const version = getAntigravityVersion();
|
|
23
|
-
const cl = process.env.PI_AI_ANTIGRAVITY_CL || "963137146";
|
|
24
|
-
return `antigravity/hub/${version} (aidev_client; os_type=${process.env.PI_AI_ANTIGRAVITY_OS || "darwin"}; arch=${process.env.PI_AI_ANTIGRAVITY_ARCH || "arm64"}; cl=${cl})`;
|
|
25
|
-
}
|
|
26
|
-
const ANTIGRAVITY_MODEL_WIRE_PROFILES = {
|
|
27
|
-
"gemini-3.5-flash-extra-low": {
|
|
28
|
-
modelEnum: "MODEL_PLACEHOLDER_M187",
|
|
29
|
-
maxOutputTokens: 65536
|
|
30
|
-
},
|
|
31
|
-
"gemini-3.5-flash-low": {
|
|
32
|
-
modelEnum: "MODEL_PLACEHOLDER_M20",
|
|
33
|
-
maxOutputTokens: 65536
|
|
34
|
-
},
|
|
35
|
-
"gemini-3-flash-agent": {
|
|
36
|
-
modelEnum: "MODEL_PLACEHOLDER_M132",
|
|
37
|
-
maxOutputTokens: 65536
|
|
38
|
-
},
|
|
39
|
-
"gemini-3.1-pro-low": {
|
|
40
|
-
modelEnum: "MODEL_PLACEHOLDER_M36",
|
|
41
|
-
maxOutputTokens: 65535
|
|
42
|
-
},
|
|
43
|
-
"gemini-pro-agent": {
|
|
44
|
-
modelEnum: "MODEL_PLACEHOLDER_M16",
|
|
45
|
-
maxOutputTokens: 65535
|
|
46
|
-
},
|
|
47
|
-
"claude-sonnet-4-6": { maxOutputTokens: 64e3 },
|
|
48
|
-
"claude-opus-4-6-thinking": { maxOutputTokens: 64e3 }
|
|
49
|
-
};
|
|
50
|
-
function getAntigravityModelWireProfile(wireModelId) {
|
|
51
|
-
return ANTIGRAVITY_MODEL_WIRE_PROFILES[wireModelId];
|
|
52
|
-
}
|
|
53
|
-
//#endregion
|
|
54
|
-
export { getAntigravityUserAgent as n, getGeminiCliHeaders as r, getAntigravityModelWireProfile as t };
|
|
@@ -1,232 +0,0 @@
|
|
|
1
|
-
import { installBunShim as __installBunShim } from "./bun-shim.mjs";
|
|
2
|
-
__installBunShim();
|
|
3
|
-
import { $ as isEnoent, P as $envpos, b as debug } from "./src-AELUUb5U.mjs";
|
|
4
|
-
import { f as OAuthError, h as MissingApiKeyError, t as ConfigurationError } from "./error-O63pC8zg.mjs";
|
|
5
|
-
import { n as raceWithSignal } from "./abort-DZ54CaKU.mjs";
|
|
6
|
-
import * as path$1 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@18.1.17/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$1.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 };
|