@asm-agent/coding-agent 0.9.2 → 0.9.4
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 +4 -0
- package/bundled-extensions/00-COMECE-AQUI.txt +233 -0
- package/bundled-extensions/00-INDEX.md +267 -0
- package/bundled-extensions/OLLAMA-TOOL-FORCING-IMPLEMENTATION.md +323 -0
- package/bundled-extensions/OLLAMA-TOOL-FORCING-QUICK-START.txt +113 -0
- package/bundled-extensions/OLLAMA-TOOL-FORCING-TESTS.md +217 -0
- package/bundled-extensions/OLLAMA-TOOL-FORCING.md +155 -0
- package/bundled-extensions/README.txt +178 -0
- package/bundled-extensions/ollama-tool-forcing.ts +90 -0
- package/dist/asm-agent-runtime/run_test.py +19 -0
- package/dist/asm-agent-runtime/src/rlm/__pycache__/__init__.cpython-312.pyc +0 -0
- package/dist/asm-agent-runtime/src/rlm/__pycache__/__init__.cpython-313.pyc +0 -0
- package/dist/asm-agent-runtime/src/rlm/__pycache__/bash.cpython-312.pyc +0 -0
- package/dist/asm-agent-runtime/src/rlm/__pycache__/bash.cpython-313.pyc +0 -0
- package/dist/asm-agent-runtime/src/rlm/__pycache__/repl.cpython-312.pyc +0 -0
- package/dist/asm-agent-runtime/src/rlm/__pycache__/repl.cpython-313.pyc +0 -0
- package/dist/asm-agent-runtime/test/__pycache__/test_bash.cpython-312.pyc +0 -0
- package/dist/asm-agent-runtime/test/test_bash.py +5 -3
- package/dist/bundle/{anthropic-2VRH36LG.js → anthropic-MHZBPOI3.js} +1 -1
- package/dist/bundle/{azure-openai-responses-COYWHJPT.js → azure-openai-responses-STVL56NS.js} +1 -1
- package/dist/bundle/{bundled-modules-N3FE2F3V.js → bundled-modules-ABB56VC3.js} +3 -3
- package/dist/bundle/{chunk-6GUVYK6P.js → chunk-EBIKTZ7C.js} +1 -0
- package/dist/bundle/{chunk-ZFAQZSZL.js → chunk-GUPU2EEK.js} +420 -31
- package/dist/bundle/{chunk-LRHUL5TM.js → chunk-NESKY6T7.js} +10 -10
- package/dist/bundle/{cli-main-PA7BZMDO.js → cli-main-ZYCGVTZE.js} +3 -3
- package/dist/bundle/cli.js +1 -1
- package/dist/bundle/{google-CSTXROSV.js → google-GMTMUI2A.js} +12 -3
- package/dist/bundle/{main-Y475CMOX.js → main-J36EPND6.js} +3 -3
- package/dist/bundle/{mistral-VAF7JADB.js → mistral-UCXDQPIP.js} +1 -1
- package/dist/bundle/{openai-codex-responses-RWZ6P4I3.js → openai-codex-responses-EGZH34H4.js} +1 -1
- package/dist/bundle/{openai-completions-CFB3BOTU.js → openai-completions-N3OFURZC.js} +1 -1
- package/dist/bundle/{openai-responses-4OPGGCBI.js → openai-responses-DTSHMHFQ.js} +1 -1
- package/dist/core/auth-storage.d.ts +1 -1
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +22 -5
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +10 -1
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/provider-display-names.d.ts.map +1 -1
- package/dist/core/provider-display-names.js +1 -0
- package/dist/core/provider-display-names.js.map +1 -1
- package/dist/postinstall.d.ts.map +1 -1
- package/dist/postinstall.js +40 -3
- package/dist/postinstall.js.map +1 -1
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/package.json +7 -6
|
@@ -329,7 +329,7 @@ import {
|
|
|
329
329
|
waitForPromptAdmission,
|
|
330
330
|
watchWithErrorHandler,
|
|
331
331
|
wrapTextWithAnsi
|
|
332
|
-
} from "./chunk-
|
|
332
|
+
} from "./chunk-NESKY6T7.js";
|
|
333
333
|
import {
|
|
334
334
|
array,
|
|
335
335
|
boolean,
|
|
@@ -354,7 +354,7 @@ import {
|
|
|
354
354
|
import {
|
|
355
355
|
findEnvKeys,
|
|
356
356
|
getEnvApiKey
|
|
357
|
-
} from "./chunk-
|
|
357
|
+
} from "./chunk-EBIKTZ7C.js";
|
|
358
358
|
import {
|
|
359
359
|
getLogger,
|
|
360
360
|
setLogSink,
|
|
@@ -7828,6 +7828,373 @@ var anthropicOAuthProvider = {
|
|
|
7828
7828
|
}
|
|
7829
7829
|
};
|
|
7830
7830
|
|
|
7831
|
+
// ../ai/src/utils/oauth/gemini.ts
|
|
7832
|
+
var nodeApis2 = null;
|
|
7833
|
+
var nodeApisPromise2 = null;
|
|
7834
|
+
var DEFAULT_CLIENT_ID = "681255809395-oo8ft2oprdrnp9e3aqf6av3hmdib135j.apps.googleusercontent.com";
|
|
7835
|
+
var AUTHORIZE_URL2 = "https://accounts.google.com/o/oauth2/v2/auth";
|
|
7836
|
+
var TOKEN_URL2 = "https://oauth2.googleapis.com/token";
|
|
7837
|
+
var CALLBACK_HOST2 = process.env.PI_OAUTH_CALLBACK_HOST || "127.0.0.1";
|
|
7838
|
+
var CALLBACK_PORT2 = Number(process.env.GEMINI_OAUTH_CALLBACK_PORT || process.env.GOOGLE_OAUTH_CALLBACK_PORT || 53694);
|
|
7839
|
+
var CALLBACK_PATH2 = "/oauth2callback";
|
|
7840
|
+
var REDIRECT_URI2 = `http://localhost:${CALLBACK_PORT2}${CALLBACK_PATH2}`;
|
|
7841
|
+
var SCOPES2 = [
|
|
7842
|
+
"https://www.googleapis.com/auth/generative-language",
|
|
7843
|
+
"https://www.googleapis.com/auth/cloud-platform",
|
|
7844
|
+
"openid",
|
|
7845
|
+
"https://www.googleapis.com/auth/userinfo.email",
|
|
7846
|
+
"https://www.googleapis.com/auth/userinfo.profile"
|
|
7847
|
+
].join(" ");
|
|
7848
|
+
function getClientId() {
|
|
7849
|
+
return process.env.GEMINI_OAUTH_CLIENT_ID || process.env.GOOGLE_OAUTH_CLIENT_ID || DEFAULT_CLIENT_ID;
|
|
7850
|
+
}
|
|
7851
|
+
function getClientSecret() {
|
|
7852
|
+
return process.env.GEMINI_OAUTH_CLIENT_SECRET || process.env.GOOGLE_OAUTH_CLIENT_SECRET || void 0;
|
|
7853
|
+
}
|
|
7854
|
+
async function getNodeApis2() {
|
|
7855
|
+
if (nodeApis2) return nodeApis2;
|
|
7856
|
+
if (!nodeApisPromise2) {
|
|
7857
|
+
if (typeof process === "undefined" || !process.versions?.node && !process.versions?.bun) {
|
|
7858
|
+
throw new Error("Gemini OAuth is only available in Node.js environments");
|
|
7859
|
+
}
|
|
7860
|
+
nodeApisPromise2 = import("node:http").then((httpModule) => ({
|
|
7861
|
+
createServer: httpModule.createServer
|
|
7862
|
+
}));
|
|
7863
|
+
}
|
|
7864
|
+
nodeApis2 = await nodeApisPromise2;
|
|
7865
|
+
return nodeApis2;
|
|
7866
|
+
}
|
|
7867
|
+
function parseAuthorizationInput2(input) {
|
|
7868
|
+
const value = input.trim();
|
|
7869
|
+
if (!value) return {};
|
|
7870
|
+
if (value.startsWith("AIza") || value.startsWith("ya29.") && !value.includes("=") && !value.includes("&")) {
|
|
7871
|
+
return { apiKey: value };
|
|
7872
|
+
}
|
|
7873
|
+
try {
|
|
7874
|
+
const url2 = new URL(value);
|
|
7875
|
+
return {
|
|
7876
|
+
code: url2.searchParams.get("code") ?? void 0,
|
|
7877
|
+
state: url2.searchParams.get("state") ?? void 0
|
|
7878
|
+
};
|
|
7879
|
+
} catch {
|
|
7880
|
+
}
|
|
7881
|
+
if (value.includes("#")) {
|
|
7882
|
+
const [code, state] = value.split("#", 2);
|
|
7883
|
+
return { code, state };
|
|
7884
|
+
}
|
|
7885
|
+
if (value.includes("code=")) {
|
|
7886
|
+
const params = new URLSearchParams(value);
|
|
7887
|
+
return {
|
|
7888
|
+
code: params.get("code") ?? void 0,
|
|
7889
|
+
state: params.get("state") ?? void 0
|
|
7890
|
+
};
|
|
7891
|
+
}
|
|
7892
|
+
return { code: value };
|
|
7893
|
+
}
|
|
7894
|
+
function formatErrorDetails2(error) {
|
|
7895
|
+
if (error instanceof Error) {
|
|
7896
|
+
const details = [`${error.name}: ${error.message}`];
|
|
7897
|
+
const errorWithCode = error;
|
|
7898
|
+
if (errorWithCode.code) details.push(`code=${errorWithCode.code}`);
|
|
7899
|
+
if (typeof errorWithCode.errno !== "undefined") details.push(`errno=${String(errorWithCode.errno)}`);
|
|
7900
|
+
if (typeof error.cause !== "undefined") {
|
|
7901
|
+
details.push(`cause=${formatErrorDetails2(error.cause)}`);
|
|
7902
|
+
}
|
|
7903
|
+
if (error.stack) {
|
|
7904
|
+
details.push(`stack=${error.stack}`);
|
|
7905
|
+
}
|
|
7906
|
+
return details.join("; ");
|
|
7907
|
+
}
|
|
7908
|
+
return String(error);
|
|
7909
|
+
}
|
|
7910
|
+
async function startCallbackServer2(expectedState) {
|
|
7911
|
+
const { createServer: createServer3 } = await getNodeApis2();
|
|
7912
|
+
return new Promise((resolve21, reject) => {
|
|
7913
|
+
let settleWait;
|
|
7914
|
+
const waitForCodePromise = new Promise((resolveWait) => {
|
|
7915
|
+
let settled = false;
|
|
7916
|
+
settleWait = (value) => {
|
|
7917
|
+
if (settled) return;
|
|
7918
|
+
settled = true;
|
|
7919
|
+
resolveWait(value);
|
|
7920
|
+
};
|
|
7921
|
+
});
|
|
7922
|
+
const server = createServer3((req, res) => {
|
|
7923
|
+
try {
|
|
7924
|
+
const url2 = new URL(req.url || "", "http://localhost");
|
|
7925
|
+
if (url2.pathname !== CALLBACK_PATH2 && url2.pathname !== "/callback") {
|
|
7926
|
+
res.writeHead(404, { "Content-Type": "text/html; charset=utf-8" });
|
|
7927
|
+
res.end(oauthErrorHtml("Callback route not found."));
|
|
7928
|
+
return;
|
|
7929
|
+
}
|
|
7930
|
+
const code = url2.searchParams.get("code");
|
|
7931
|
+
const state = url2.searchParams.get("state");
|
|
7932
|
+
const error = url2.searchParams.get("error");
|
|
7933
|
+
if (error) {
|
|
7934
|
+
res.writeHead(400, { "Content-Type": "text/html; charset=utf-8" });
|
|
7935
|
+
res.end(oauthErrorHtml("Google Gemini authentication did not complete.", `Error: ${error}`));
|
|
7936
|
+
return;
|
|
7937
|
+
}
|
|
7938
|
+
if (!code || !state) {
|
|
7939
|
+
res.writeHead(400, { "Content-Type": "text/html; charset=utf-8" });
|
|
7940
|
+
res.end(oauthErrorHtml("Missing code or state parameter."));
|
|
7941
|
+
return;
|
|
7942
|
+
}
|
|
7943
|
+
if (state !== expectedState) {
|
|
7944
|
+
res.writeHead(400, { "Content-Type": "text/html; charset=utf-8" });
|
|
7945
|
+
res.end(oauthErrorHtml("State mismatch."));
|
|
7946
|
+
return;
|
|
7947
|
+
}
|
|
7948
|
+
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
7949
|
+
res.end(oauthSuccessHtml("Google Gemini authentication completed. You can close this window."));
|
|
7950
|
+
settleWait?.({ code, state });
|
|
7951
|
+
} catch {
|
|
7952
|
+
res.writeHead(500, { "Content-Type": "text/plain; charset=utf-8" });
|
|
7953
|
+
res.end("Internal error");
|
|
7954
|
+
}
|
|
7955
|
+
});
|
|
7956
|
+
server.on("error", (err) => {
|
|
7957
|
+
reject(err);
|
|
7958
|
+
});
|
|
7959
|
+
server.listen(CALLBACK_PORT2, CALLBACK_HOST2, () => {
|
|
7960
|
+
resolve21({
|
|
7961
|
+
server,
|
|
7962
|
+
redirectUri: REDIRECT_URI2,
|
|
7963
|
+
cancelWait: () => {
|
|
7964
|
+
settleWait?.(null);
|
|
7965
|
+
},
|
|
7966
|
+
waitForCode: () => waitForCodePromise
|
|
7967
|
+
});
|
|
7968
|
+
});
|
|
7969
|
+
});
|
|
7970
|
+
}
|
|
7971
|
+
async function postForm(url2, params) {
|
|
7972
|
+
const body = new URLSearchParams(params);
|
|
7973
|
+
const response = await fetch(url2, {
|
|
7974
|
+
method: "POST",
|
|
7975
|
+
headers: {
|
|
7976
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
7977
|
+
Accept: "application/json"
|
|
7978
|
+
},
|
|
7979
|
+
body: body.toString(),
|
|
7980
|
+
signal: AbortSignal.timeout(3e4)
|
|
7981
|
+
});
|
|
7982
|
+
const responseBody = await response.text();
|
|
7983
|
+
if (!response.ok) {
|
|
7984
|
+
throw new Error(`HTTP request failed. status=${response.status}; url=${url2}; body=${responseBody}`);
|
|
7985
|
+
}
|
|
7986
|
+
return responseBody;
|
|
7987
|
+
}
|
|
7988
|
+
async function exchangeAuthorizationCode2(code, verifier, redirectUri) {
|
|
7989
|
+
const clientId = getClientId();
|
|
7990
|
+
const clientSecret = getClientSecret();
|
|
7991
|
+
const payload = {
|
|
7992
|
+
grant_type: "authorization_code",
|
|
7993
|
+
client_id: clientId,
|
|
7994
|
+
code,
|
|
7995
|
+
redirect_uri: redirectUri,
|
|
7996
|
+
code_verifier: verifier
|
|
7997
|
+
};
|
|
7998
|
+
if (clientSecret) {
|
|
7999
|
+
payload.client_secret = clientSecret;
|
|
8000
|
+
}
|
|
8001
|
+
let responseBody;
|
|
8002
|
+
try {
|
|
8003
|
+
responseBody = await postForm(TOKEN_URL2, payload);
|
|
8004
|
+
} catch (error) {
|
|
8005
|
+
throw new Error(
|
|
8006
|
+
`Token exchange request failed. url=${TOKEN_URL2}; redirect_uri=${redirectUri}; details=${formatErrorDetails2(error)}`
|
|
8007
|
+
);
|
|
8008
|
+
}
|
|
8009
|
+
let tokenData;
|
|
8010
|
+
try {
|
|
8011
|
+
tokenData = JSON.parse(responseBody);
|
|
8012
|
+
} catch (error) {
|
|
8013
|
+
throw new Error(
|
|
8014
|
+
`Token exchange returned invalid JSON. url=${TOKEN_URL2}; body=${responseBody}; details=${formatErrorDetails2(error)}`
|
|
8015
|
+
);
|
|
8016
|
+
}
|
|
8017
|
+
return {
|
|
8018
|
+
access: tokenData.access_token,
|
|
8019
|
+
refresh: tokenData.refresh_token || "",
|
|
8020
|
+
expires: Date.now() + (tokenData.expires_in ?? 3600) * 1e3 - 5 * 60 * 1e3
|
|
8021
|
+
};
|
|
8022
|
+
}
|
|
8023
|
+
async function loginGemini(options) {
|
|
8024
|
+
const { verifier, challenge } = await generatePKCE();
|
|
8025
|
+
const server = await startCallbackServer2(verifier);
|
|
8026
|
+
let code;
|
|
8027
|
+
let state;
|
|
8028
|
+
let manualApiKey;
|
|
8029
|
+
let redirectUriForExchange = REDIRECT_URI2;
|
|
8030
|
+
try {
|
|
8031
|
+
const clientId = getClientId();
|
|
8032
|
+
const authParams = new URLSearchParams({
|
|
8033
|
+
client_id: clientId,
|
|
8034
|
+
response_type: "code",
|
|
8035
|
+
redirect_uri: REDIRECT_URI2,
|
|
8036
|
+
scope: SCOPES2,
|
|
8037
|
+
code_challenge: challenge,
|
|
8038
|
+
code_challenge_method: "S256",
|
|
8039
|
+
state: verifier,
|
|
8040
|
+
access_type: "offline",
|
|
8041
|
+
prompt: "consent"
|
|
8042
|
+
});
|
|
8043
|
+
options.onAuth({
|
|
8044
|
+
url: `${AUTHORIZE_URL2}?${authParams.toString()}`,
|
|
8045
|
+
instructions: "Complete login in your browser. If the browser is on another machine, paste the final redirect URL or an API key here."
|
|
8046
|
+
});
|
|
8047
|
+
if (options.onManualCodeInput) {
|
|
8048
|
+
let manualInput;
|
|
8049
|
+
let manualError;
|
|
8050
|
+
const manualPromise = options.onManualCodeInput().then((input) => {
|
|
8051
|
+
manualInput = input;
|
|
8052
|
+
server.cancelWait();
|
|
8053
|
+
}).catch((err) => {
|
|
8054
|
+
manualError = err instanceof Error ? err : new Error(String(err));
|
|
8055
|
+
server.cancelWait();
|
|
8056
|
+
});
|
|
8057
|
+
const result = await server.waitForCode();
|
|
8058
|
+
if (manualError) {
|
|
8059
|
+
throw manualError;
|
|
8060
|
+
}
|
|
8061
|
+
if (result?.code) {
|
|
8062
|
+
code = result.code;
|
|
8063
|
+
state = result.state;
|
|
8064
|
+
redirectUriForExchange = REDIRECT_URI2;
|
|
8065
|
+
} else if (manualInput) {
|
|
8066
|
+
const parsed = parseAuthorizationInput2(manualInput);
|
|
8067
|
+
if (parsed.apiKey) {
|
|
8068
|
+
manualApiKey = parsed.apiKey;
|
|
8069
|
+
} else {
|
|
8070
|
+
if (parsed.state && parsed.state !== verifier) {
|
|
8071
|
+
throw new Error("OAuth state mismatch");
|
|
8072
|
+
}
|
|
8073
|
+
code = parsed.code;
|
|
8074
|
+
state = parsed.state ?? verifier;
|
|
8075
|
+
}
|
|
8076
|
+
}
|
|
8077
|
+
if (!code && !manualApiKey) {
|
|
8078
|
+
await manualPromise;
|
|
8079
|
+
if (manualError) {
|
|
8080
|
+
throw manualError;
|
|
8081
|
+
}
|
|
8082
|
+
if (manualInput) {
|
|
8083
|
+
const parsed = parseAuthorizationInput2(manualInput);
|
|
8084
|
+
if (parsed.apiKey) {
|
|
8085
|
+
manualApiKey = parsed.apiKey;
|
|
8086
|
+
} else {
|
|
8087
|
+
if (parsed.state && parsed.state !== verifier) {
|
|
8088
|
+
throw new Error("OAuth state mismatch");
|
|
8089
|
+
}
|
|
8090
|
+
code = parsed.code;
|
|
8091
|
+
state = parsed.state ?? verifier;
|
|
8092
|
+
}
|
|
8093
|
+
}
|
|
8094
|
+
}
|
|
8095
|
+
} else {
|
|
8096
|
+
const result = await server.waitForCode();
|
|
8097
|
+
if (result?.code) {
|
|
8098
|
+
code = result.code;
|
|
8099
|
+
state = result.state;
|
|
8100
|
+
redirectUriForExchange = REDIRECT_URI2;
|
|
8101
|
+
}
|
|
8102
|
+
}
|
|
8103
|
+
if (!code && !manualApiKey) {
|
|
8104
|
+
const input = await options.onPrompt({
|
|
8105
|
+
message: "Paste the authorization code, redirect URL, or Gemini API key:",
|
|
8106
|
+
placeholder: REDIRECT_URI2
|
|
8107
|
+
});
|
|
8108
|
+
const parsed = parseAuthorizationInput2(input);
|
|
8109
|
+
if (parsed.apiKey) {
|
|
8110
|
+
manualApiKey = parsed.apiKey;
|
|
8111
|
+
} else {
|
|
8112
|
+
if (parsed.state && parsed.state !== verifier) {
|
|
8113
|
+
throw new Error("OAuth state mismatch");
|
|
8114
|
+
}
|
|
8115
|
+
code = parsed.code;
|
|
8116
|
+
state = parsed.state ?? verifier;
|
|
8117
|
+
}
|
|
8118
|
+
}
|
|
8119
|
+
if (manualApiKey) {
|
|
8120
|
+
return {
|
|
8121
|
+
access: manualApiKey,
|
|
8122
|
+
refresh: "",
|
|
8123
|
+
expires: Date.now() + 365 * 24 * 60 * 60 * 1e3
|
|
8124
|
+
};
|
|
8125
|
+
}
|
|
8126
|
+
if (!code) {
|
|
8127
|
+
throw new Error("Missing authorization code");
|
|
8128
|
+
}
|
|
8129
|
+
if (!state) {
|
|
8130
|
+
throw new Error("Missing OAuth state");
|
|
8131
|
+
}
|
|
8132
|
+
options.onProgress?.("Exchanging authorization code for tokens...");
|
|
8133
|
+
return exchangeAuthorizationCode2(code, verifier, redirectUriForExchange);
|
|
8134
|
+
} finally {
|
|
8135
|
+
server.server.close();
|
|
8136
|
+
}
|
|
8137
|
+
}
|
|
8138
|
+
async function refreshGeminiToken(refreshToken) {
|
|
8139
|
+
if (!refreshToken) {
|
|
8140
|
+
throw new Error("No refresh token available for Google Gemini");
|
|
8141
|
+
}
|
|
8142
|
+
const clientId = getClientId();
|
|
8143
|
+
const clientSecret = getClientSecret();
|
|
8144
|
+
const payload = {
|
|
8145
|
+
grant_type: "refresh_token",
|
|
8146
|
+
client_id: clientId,
|
|
8147
|
+
refresh_token: refreshToken
|
|
8148
|
+
};
|
|
8149
|
+
if (clientSecret) {
|
|
8150
|
+
payload.client_secret = clientSecret;
|
|
8151
|
+
}
|
|
8152
|
+
let responseBody;
|
|
8153
|
+
try {
|
|
8154
|
+
responseBody = await postForm(TOKEN_URL2, payload);
|
|
8155
|
+
} catch (error) {
|
|
8156
|
+
throw new Error(
|
|
8157
|
+
`Google Gemini token refresh request failed. url=${TOKEN_URL2}; details=${formatErrorDetails2(error)}`
|
|
8158
|
+
);
|
|
8159
|
+
}
|
|
8160
|
+
let data;
|
|
8161
|
+
try {
|
|
8162
|
+
data = JSON.parse(responseBody);
|
|
8163
|
+
} catch (error) {
|
|
8164
|
+
throw new Error(
|
|
8165
|
+
`Google Gemini token refresh returned invalid JSON. url=${TOKEN_URL2}; body=${responseBody}; details=${formatErrorDetails2(error)}`
|
|
8166
|
+
);
|
|
8167
|
+
}
|
|
8168
|
+
return {
|
|
8169
|
+
access: data.access_token,
|
|
8170
|
+
refresh: data.refresh_token || refreshToken,
|
|
8171
|
+
expires: Date.now() + (data.expires_in ?? 3600) * 1e3 - 5 * 60 * 1e3
|
|
8172
|
+
};
|
|
8173
|
+
}
|
|
8174
|
+
var geminiOAuthProvider = {
|
|
8175
|
+
id: "google",
|
|
8176
|
+
name: "Google Gemini",
|
|
8177
|
+
usesCallbackServer: true,
|
|
8178
|
+
async login(callbacks) {
|
|
8179
|
+
return loginGemini({
|
|
8180
|
+
onAuth: callbacks.onAuth,
|
|
8181
|
+
onPrompt: callbacks.onPrompt,
|
|
8182
|
+
onProgress: callbacks.onProgress,
|
|
8183
|
+
onManualCodeInput: callbacks.onManualCodeInput
|
|
8184
|
+
});
|
|
8185
|
+
},
|
|
8186
|
+
async refreshToken(credentials) {
|
|
8187
|
+
if (!credentials.refresh) {
|
|
8188
|
+
return credentials;
|
|
8189
|
+
}
|
|
8190
|
+
return refreshGeminiToken(credentials.refresh);
|
|
8191
|
+
},
|
|
8192
|
+
getApiKey(credentials) {
|
|
8193
|
+
return credentials.access;
|
|
8194
|
+
}
|
|
8195
|
+
};
|
|
8196
|
+
var googleOAuthProvider = geminiOAuthProvider;
|
|
8197
|
+
|
|
7831
8198
|
// ../ai/src/utils/oauth/github-copilot.ts
|
|
7832
8199
|
var decode2 = (s) => atob(s);
|
|
7833
8200
|
var CLIENT_ID2 = decode2("SXYxLmI1MDdhMDhjODdlY2ZlOTg=");
|
|
@@ -8100,11 +8467,11 @@ if (typeof process !== "undefined" && (process.versions?.node || process.version
|
|
|
8100
8467
|
_http = m;
|
|
8101
8468
|
});
|
|
8102
8469
|
}
|
|
8103
|
-
var
|
|
8470
|
+
var CALLBACK_HOST3 = process.env.PI_OAUTH_CALLBACK_HOST || "127.0.0.1";
|
|
8104
8471
|
var CLIENT_ID3 = "app_EMoamEEZ73f0CkXaXp7hrann";
|
|
8105
|
-
var
|
|
8106
|
-
var
|
|
8107
|
-
var
|
|
8472
|
+
var AUTHORIZE_URL3 = "https://auth.openai.com/oauth/authorize";
|
|
8473
|
+
var TOKEN_URL3 = "https://auth.openai.com/oauth/token";
|
|
8474
|
+
var REDIRECT_URI3 = "http://localhost:1455/auth/callback";
|
|
8108
8475
|
var SCOPE = "openid profile email offline_access";
|
|
8109
8476
|
var JWT_CLAIM_PATH = "https://api.openai.com/auth";
|
|
8110
8477
|
function createState() {
|
|
@@ -8113,7 +8480,7 @@ function createState() {
|
|
|
8113
8480
|
}
|
|
8114
8481
|
return _randomBytes(16).toString("hex");
|
|
8115
8482
|
}
|
|
8116
|
-
function
|
|
8483
|
+
function parseAuthorizationInput3(input) {
|
|
8117
8484
|
const value = input.trim();
|
|
8118
8485
|
if (!value) return {};
|
|
8119
8486
|
try {
|
|
@@ -8148,8 +8515,8 @@ function decodeJwt(token) {
|
|
|
8148
8515
|
return null;
|
|
8149
8516
|
}
|
|
8150
8517
|
}
|
|
8151
|
-
async function
|
|
8152
|
-
const response = await fetch(
|
|
8518
|
+
async function exchangeAuthorizationCode3(code, verifier, redirectUri = REDIRECT_URI3) {
|
|
8519
|
+
const response = await fetch(TOKEN_URL3, {
|
|
8153
8520
|
method: "POST",
|
|
8154
8521
|
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
8155
8522
|
body: new URLSearchParams({
|
|
@@ -8184,7 +8551,7 @@ async function exchangeAuthorizationCode2(code, verifier, redirectUri = REDIRECT
|
|
|
8184
8551
|
}
|
|
8185
8552
|
async function refreshAccessToken(refreshToken) {
|
|
8186
8553
|
try {
|
|
8187
|
-
const response = await fetch(
|
|
8554
|
+
const response = await fetch(TOKEN_URL3, {
|
|
8188
8555
|
method: "POST",
|
|
8189
8556
|
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
8190
8557
|
body: new URLSearchParams({
|
|
@@ -8224,10 +8591,10 @@ async function refreshAccessToken(refreshToken) {
|
|
|
8224
8591
|
async function createAuthorizationFlow(originator = "pi") {
|
|
8225
8592
|
const { verifier, challenge } = await generatePKCE();
|
|
8226
8593
|
const state = createState();
|
|
8227
|
-
const url2 = new URL(
|
|
8594
|
+
const url2 = new URL(AUTHORIZE_URL3);
|
|
8228
8595
|
url2.searchParams.set("response_type", "code");
|
|
8229
8596
|
url2.searchParams.set("client_id", CLIENT_ID3);
|
|
8230
|
-
url2.searchParams.set("redirect_uri",
|
|
8597
|
+
url2.searchParams.set("redirect_uri", REDIRECT_URI3);
|
|
8231
8598
|
url2.searchParams.set("scope", SCOPE);
|
|
8232
8599
|
url2.searchParams.set("code_challenge", challenge);
|
|
8233
8600
|
url2.searchParams.set("code_challenge_method", "S256");
|
|
@@ -8283,7 +8650,7 @@ function startLocalOAuthServer(state) {
|
|
|
8283
8650
|
}
|
|
8284
8651
|
});
|
|
8285
8652
|
return new Promise((resolve21) => {
|
|
8286
|
-
server.listen(1455,
|
|
8653
|
+
server.listen(1455, CALLBACK_HOST3, () => {
|
|
8287
8654
|
resolve21({
|
|
8288
8655
|
close: () => server.close(),
|
|
8289
8656
|
cancelWait: () => {
|
|
@@ -8336,7 +8703,7 @@ async function loginOpenAICodex(options) {
|
|
|
8336
8703
|
if (result?.code) {
|
|
8337
8704
|
code = result.code;
|
|
8338
8705
|
} else if (manualCode) {
|
|
8339
|
-
const parsed =
|
|
8706
|
+
const parsed = parseAuthorizationInput3(manualCode);
|
|
8340
8707
|
if (parsed.state && parsed.state !== state) {
|
|
8341
8708
|
throw new Error("State mismatch");
|
|
8342
8709
|
}
|
|
@@ -8348,7 +8715,7 @@ async function loginOpenAICodex(options) {
|
|
|
8348
8715
|
throw manualError;
|
|
8349
8716
|
}
|
|
8350
8717
|
if (manualCode) {
|
|
8351
|
-
const parsed =
|
|
8718
|
+
const parsed = parseAuthorizationInput3(manualCode);
|
|
8352
8719
|
if (parsed.state && parsed.state !== state) {
|
|
8353
8720
|
throw new Error("State mismatch");
|
|
8354
8721
|
}
|
|
@@ -8365,7 +8732,7 @@ async function loginOpenAICodex(options) {
|
|
|
8365
8732
|
const input = await options.onPrompt({
|
|
8366
8733
|
message: "Paste the authorization code (or full redirect URL):"
|
|
8367
8734
|
});
|
|
8368
|
-
const parsed =
|
|
8735
|
+
const parsed = parseAuthorizationInput3(input);
|
|
8369
8736
|
if (parsed.state && parsed.state !== state) {
|
|
8370
8737
|
throw new Error("State mismatch");
|
|
8371
8738
|
}
|
|
@@ -8374,7 +8741,7 @@ async function loginOpenAICodex(options) {
|
|
|
8374
8741
|
if (!code) {
|
|
8375
8742
|
throw new Error("Missing authorization code");
|
|
8376
8743
|
}
|
|
8377
|
-
const tokenResult = await
|
|
8744
|
+
const tokenResult = await exchangeAuthorizationCode3(code, verifier);
|
|
8378
8745
|
if (tokenResult.type !== "success") {
|
|
8379
8746
|
throw new Error(tokenResult.message);
|
|
8380
8747
|
}
|
|
@@ -8432,13 +8799,14 @@ var openaiCodexOAuthProvider = {
|
|
|
8432
8799
|
var BUILT_IN_OAUTH_PROVIDERS = [
|
|
8433
8800
|
anthropicOAuthProvider,
|
|
8434
8801
|
githubCopilotOAuthProvider,
|
|
8802
|
+
geminiOAuthProvider,
|
|
8435
8803
|
openaiCodexOAuthProvider
|
|
8436
8804
|
];
|
|
8437
8805
|
var oauthProviderRegistry = new Map(
|
|
8438
8806
|
BUILT_IN_OAUTH_PROVIDERS.map((provider) => [provider.id, provider])
|
|
8439
8807
|
);
|
|
8440
8808
|
function getOAuthProvider(id) {
|
|
8441
|
-
return oauthProviderRegistry.get(id);
|
|
8809
|
+
return oauthProviderRegistry.get(id) ?? (id === "gemini" ? oauthProviderRegistry.get("google") : void 0);
|
|
8442
8810
|
}
|
|
8443
8811
|
function registerOAuthProvider(provider) {
|
|
8444
8812
|
oauthProviderRegistry.set(provider.id, provider);
|
|
@@ -8495,12 +8863,12 @@ async function getOAuthApiKey(providerId, credentials) {
|
|
|
8495
8863
|
}
|
|
8496
8864
|
|
|
8497
8865
|
// ../ai/src/mcp/oauth.ts
|
|
8498
|
-
var
|
|
8866
|
+
var CALLBACK_HOST4 = process.env.PI_OAUTH_CALLBACK_HOST || "127.0.0.1";
|
|
8499
8867
|
var CALLBACK_PORT_BASE = Number(process.env.PI_MCP_OAUTH_CALLBACK_PORT || 53700);
|
|
8500
8868
|
var CALLBACK_PORT_COUNT = 10;
|
|
8501
|
-
var
|
|
8869
|
+
var CALLBACK_PATH3 = "/callback";
|
|
8502
8870
|
var CALLBACK_PORTS = Array.from({ length: CALLBACK_PORT_COUNT }, (_2, i) => CALLBACK_PORT_BASE + i);
|
|
8503
|
-
var redirectUriFor = (port) => `http://localhost:${port}${
|
|
8871
|
+
var redirectUriFor = (port) => `http://localhost:${port}${CALLBACK_PATH3}`;
|
|
8504
8872
|
var ALL_REDIRECT_URIS = CALLBACK_PORTS.map(redirectUriFor);
|
|
8505
8873
|
var TOKEN_EXPIRY_BUFFER_MS = 5 * 60 * 1e3;
|
|
8506
8874
|
function validatedHttpsUrl(value, name) {
|
|
@@ -8659,7 +9027,7 @@ async function registerClient(registrationEndpoint, label) {
|
|
|
8659
9027
|
}
|
|
8660
9028
|
return data.client_id;
|
|
8661
9029
|
}
|
|
8662
|
-
async function
|
|
9030
|
+
async function startCallbackServer3(label) {
|
|
8663
9031
|
const { createServer: createServer3 } = await import("node:http");
|
|
8664
9032
|
let settle;
|
|
8665
9033
|
const waitPromise = new Promise((resolve21) => {
|
|
@@ -8673,7 +9041,7 @@ async function startCallbackServer2(label) {
|
|
|
8673
9041
|
});
|
|
8674
9042
|
const handler = (req, res) => {
|
|
8675
9043
|
const url2 = new URL(req.url || "", "http://localhost");
|
|
8676
|
-
if (url2.pathname !==
|
|
9044
|
+
if (url2.pathname !== CALLBACK_PATH3) {
|
|
8677
9045
|
res.writeHead(404, { "Content-Type": "text/html; charset=utf-8" });
|
|
8678
9046
|
res.end(oauthErrorHtml("Callback route not found."));
|
|
8679
9047
|
return;
|
|
@@ -8703,7 +9071,7 @@ async function startCallbackServer2(label) {
|
|
|
8703
9071
|
try {
|
|
8704
9072
|
const bound = await new Promise((resolve21) => {
|
|
8705
9073
|
bindErr = () => resolve21(false);
|
|
8706
|
-
server.listen(port,
|
|
9074
|
+
server.listen(port, CALLBACK_HOST4, () => {
|
|
8707
9075
|
bindErr = void 0;
|
|
8708
9076
|
resolve21(true);
|
|
8709
9077
|
});
|
|
@@ -8810,7 +9178,7 @@ function createMcpOAuthProvider(config) {
|
|
|
8810
9178
|
const { verifier, challenge } = await generatePKCE();
|
|
8811
9179
|
const state = randomState();
|
|
8812
9180
|
const scope = config.scopes ?? meta.scopes_supported?.join(" ");
|
|
8813
|
-
const cb = await
|
|
9181
|
+
const cb = await startCallbackServer3(label);
|
|
8814
9182
|
try {
|
|
8815
9183
|
const authParams = new URLSearchParams({
|
|
8816
9184
|
client_id: clientId,
|
|
@@ -9821,18 +10189,22 @@ import { createHash } from "node:crypto";
|
|
|
9821
10189
|
var oauth_exports = {};
|
|
9822
10190
|
__export(oauth_exports, {
|
|
9823
10191
|
anthropicOAuthProvider: () => anthropicOAuthProvider,
|
|
10192
|
+
geminiOAuthProvider: () => geminiOAuthProvider,
|
|
9824
10193
|
getGitHubCopilotBaseUrl: () => getGitHubCopilotBaseUrl,
|
|
9825
10194
|
getOAuthApiKey: () => getOAuthApiKey,
|
|
9826
10195
|
getOAuthProvider: () => getOAuthProvider,
|
|
9827
10196
|
getOAuthProviderInfoList: () => getOAuthProviderInfoList,
|
|
9828
10197
|
getOAuthProviders: () => getOAuthProviders,
|
|
9829
10198
|
githubCopilotOAuthProvider: () => githubCopilotOAuthProvider,
|
|
10199
|
+
googleOAuthProvider: () => googleOAuthProvider,
|
|
9830
10200
|
loginAnthropic: () => loginAnthropic,
|
|
10201
|
+
loginGemini: () => loginGemini,
|
|
9831
10202
|
loginGitHubCopilot: () => loginGitHubCopilot,
|
|
9832
10203
|
loginOpenAICodex: () => loginOpenAICodex,
|
|
9833
10204
|
normalizeDomain: () => normalizeDomain,
|
|
9834
10205
|
openaiCodexOAuthProvider: () => openaiCodexOAuthProvider,
|
|
9835
10206
|
refreshAnthropicToken: () => refreshAnthropicToken,
|
|
10207
|
+
refreshGeminiToken: () => refreshGeminiToken,
|
|
9836
10208
|
refreshGitHubCopilotToken: () => refreshGitHubCopilotToken,
|
|
9837
10209
|
refreshOAuthToken: () => refreshOAuthToken,
|
|
9838
10210
|
refreshOpenAICodexToken: () => refreshOpenAICodexToken,
|
|
@@ -10523,7 +10895,7 @@ var AuthStorage = class _AuthStorage {
|
|
|
10523
10895
|
};
|
|
10524
10896
|
}
|
|
10525
10897
|
getStoredAuthCandidate(provider, options) {
|
|
10526
|
-
const credential = this.data[provider];
|
|
10898
|
+
const credential = this.data[provider] ?? (provider === "google" ? this.data.gemini : provider === "gemini" ? this.data.google : void 0);
|
|
10527
10899
|
if (!credential) {
|
|
10528
10900
|
return void 0;
|
|
10529
10901
|
}
|
|
@@ -10747,7 +11119,14 @@ var AuthStorage = class _AuthStorage {
|
|
|
10747
11119
|
* Get credential for a provider.
|
|
10748
11120
|
*/
|
|
10749
11121
|
get(provider) {
|
|
10750
|
-
|
|
11122
|
+
const direct = this.data[provider];
|
|
11123
|
+
if (direct)
|
|
11124
|
+
return direct;
|
|
11125
|
+
if (provider === "google")
|
|
11126
|
+
return this.data.gemini;
|
|
11127
|
+
if (provider === "gemini")
|
|
11128
|
+
return this.data.google;
|
|
11129
|
+
return void 0;
|
|
10751
11130
|
}
|
|
10752
11131
|
/**
|
|
10753
11132
|
* Set credential for a provider.
|
|
@@ -10793,7 +11172,7 @@ var AuthStorage = class _AuthStorage {
|
|
|
10793
11172
|
* Check if credentials exist for a provider in auth.json.
|
|
10794
11173
|
*/
|
|
10795
11174
|
has(provider) {
|
|
10796
|
-
return provider in this.data;
|
|
11175
|
+
return provider in this.data || provider === "google" && "gemini" in this.data || provider === "gemini" && "google" in this.data;
|
|
10797
11176
|
}
|
|
10798
11177
|
/**
|
|
10799
11178
|
* Check if any form of auth is configured for a provider.
|
|
@@ -10858,7 +11237,8 @@ var AuthStorage = class _AuthStorage {
|
|
|
10858
11237
|
const currentData = this.parseStorageData(current);
|
|
10859
11238
|
this.data = currentData;
|
|
10860
11239
|
this.loadError = null;
|
|
10861
|
-
const
|
|
11240
|
+
const storageKey = currentData[providerId] ? providerId : providerId === "google" && currentData.gemini ? "gemini" : providerId === "gemini" && currentData.google ? "google" : providerId;
|
|
11241
|
+
const cred = currentData[storageKey];
|
|
10862
11242
|
if (cred?.type !== "oauth") {
|
|
10863
11243
|
return { result: null };
|
|
10864
11244
|
}
|
|
@@ -10920,7 +11300,7 @@ var AuthStorage = class _AuthStorage {
|
|
|
10920
11300
|
};
|
|
10921
11301
|
}
|
|
10922
11302
|
}
|
|
10923
|
-
const cred = this.
|
|
11303
|
+
const cred = this.get(providerId);
|
|
10924
11304
|
if (cred?.type === "api_key") {
|
|
10925
11305
|
const storedCandidate = this.getStoredAuthCandidate(providerId);
|
|
10926
11306
|
if (storedCandidate && !this.isAuthSourceStale(providerId, storedCandidate)) {
|
|
@@ -25325,6 +25705,7 @@ var BUILT_IN_PROVIDER_DISPLAY_NAMES = {
|
|
|
25325
25705
|
deepseek: "DeepSeek",
|
|
25326
25706
|
fireworks: "Fireworks",
|
|
25327
25707
|
google: "Google Gemini",
|
|
25708
|
+
gemini: "Google Gemini",
|
|
25328
25709
|
"google-vertex": "Google Vertex AI",
|
|
25329
25710
|
groq: "Groq",
|
|
25330
25711
|
huggingface: "Hugging Face",
|
|
@@ -26068,7 +26449,7 @@ File: ${modelsJsonPath}`);
|
|
|
26068
26449
|
* Find a model by provider and ID.
|
|
26069
26450
|
*/
|
|
26070
26451
|
find(provider, modelId) {
|
|
26071
|
-
return this.models.find((m) => m.provider === provider && m.id === modelId);
|
|
26452
|
+
return this.models.find((m) => m.provider === provider && m.id === modelId) ?? (provider === "gemini" ? this.models.find((m) => m.provider === "google" && m.id === modelId) : void 0);
|
|
26072
26453
|
}
|
|
26073
26454
|
/**
|
|
26074
26455
|
* Get API key for a model.
|
|
@@ -26346,6 +26727,14 @@ File: ${modelsJsonPath}`);
|
|
|
26346
26727
|
this.setLastProviderAuthSourceToken(provider, authStorageAuth.sourceToken);
|
|
26347
26728
|
return authStorageAuth.apiKey;
|
|
26348
26729
|
}
|
|
26730
|
+
if (provider === "google" || provider === "gemini") {
|
|
26731
|
+
const altProvider = provider === "google" ? "gemini" : "google";
|
|
26732
|
+
const altAuth = await this.authStorage.getApiKeyWithSourceToken(altProvider, { includeFallback: false });
|
|
26733
|
+
if (altAuth.apiKey !== void 0) {
|
|
26734
|
+
this.setLastProviderAuthSourceToken(provider, altAuth.sourceToken);
|
|
26735
|
+
return altAuth.apiKey;
|
|
26736
|
+
}
|
|
26737
|
+
}
|
|
26349
26738
|
const providerApiKey = this.providerRequestConfigs.get(provider)?.apiKey;
|
|
26350
26739
|
if (!providerApiKey) {
|
|
26351
26740
|
this.setLastProviderAuthSourceToken(provider, void 0);
|