@anthonyhaussman/opencode-agy-auth 1.2.3-alpha.3 → 1.2.3-alpha.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/dist/index.js
CHANGED
|
@@ -104,6 +104,8 @@ function updateStaticModelsWithPricing(staticModels) {
|
|
|
104
104
|
|
|
105
105
|
// src/constants.ts
|
|
106
106
|
var AGY_PROVIDER_ID = "google-agy";
|
|
107
|
+
var AGY_AUTH_URL = "https://accounts.google.com/o/oauth2/auth";
|
|
108
|
+
var AGY_TOKEN_URL = "https://oauth2.googleapis.com/token";
|
|
107
109
|
var AGY_CLIENT_ID = "1071006060591-tmhssin2h21lcre235vtolojh4g403ep.apps.googleusercontent.com";
|
|
108
110
|
var AGY_CLIENT_SECRET = "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";
|
|
109
111
|
var AGY_SCOPES = [
|
|
@@ -20664,6 +20666,9 @@ function defineOpenCodeV2Plugin(def) {
|
|
|
20664
20666
|
}
|
|
20665
20667
|
|
|
20666
20668
|
// src/plugin/v2.ts
|
|
20669
|
+
import { homedir as homedir4 } from "os";
|
|
20670
|
+
import { join as join6 } from "path";
|
|
20671
|
+
import { existsSync as existsSync6, readFileSync as readFileSync5 } from "fs";
|
|
20667
20672
|
var AGY_V2_QUOTA_COMMAND = "agy-quota";
|
|
20668
20673
|
var AGY_V2_QUOTA_SUMMARY_COMMAND = "agy-quota-summary";
|
|
20669
20674
|
var AGY_V2_QUOTA_COMMAND_TEMPLATE = `Retrieve Agy Code Assist quota usage for the current authenticated account.
|
|
@@ -20676,6 +20681,203 @@ var AGY_V2_QUOTA_SUMMARY_COMMAND_TEMPLATE = `Retrieve Agy Code Assist quota summ
|
|
|
20676
20681
|
Immediately call \`${AGY_QUOTA_SUMMARY_TOOL_NAME}\` with no arguments and return its output verbatim.
|
|
20677
20682
|
Do not call other tools.
|
|
20678
20683
|
`;
|
|
20684
|
+
function getSafeHeader2(headers, key) {
|
|
20685
|
+
if (!headers) {
|
|
20686
|
+
return void 0;
|
|
20687
|
+
}
|
|
20688
|
+
const targetKey = key.toLowerCase();
|
|
20689
|
+
if (typeof headers.get === "function") {
|
|
20690
|
+
try {
|
|
20691
|
+
return headers.get(targetKey) || void 0;
|
|
20692
|
+
} catch {
|
|
20693
|
+
}
|
|
20694
|
+
}
|
|
20695
|
+
if (Array.isArray(headers)) {
|
|
20696
|
+
const found = headers.find((item) => {
|
|
20697
|
+
if (Array.isArray(item) && typeof item[0] === "string") {
|
|
20698
|
+
return item[0].toLowerCase() === targetKey;
|
|
20699
|
+
}
|
|
20700
|
+
return false;
|
|
20701
|
+
});
|
|
20702
|
+
return found ? String(found[1]) : void 0;
|
|
20703
|
+
}
|
|
20704
|
+
if (typeof headers === "object") {
|
|
20705
|
+
const foundKey = Object.keys(headers).find((k) => k.toLowerCase() === targetKey);
|
|
20706
|
+
return foundKey ? headers[foundKey] !== void 0 ? String(headers[foundKey]) : void 0 : void 0;
|
|
20707
|
+
}
|
|
20708
|
+
return void 0;
|
|
20709
|
+
}
|
|
20710
|
+
function setSafeHeaders2(initHeaders, newHeaders) {
|
|
20711
|
+
if (typeof globalThis.Headers !== "undefined") {
|
|
20712
|
+
const headers = new globalThis.Headers(initHeaders ?? {});
|
|
20713
|
+
for (const [k, v] of Object.entries(newHeaders)) {
|
|
20714
|
+
headers.set(k, v);
|
|
20715
|
+
}
|
|
20716
|
+
return headers;
|
|
20717
|
+
}
|
|
20718
|
+
if (Array.isArray(initHeaders)) {
|
|
20719
|
+
const nextHeaders2 = [...initHeaders];
|
|
20720
|
+
for (const [k, v] of Object.entries(newHeaders)) {
|
|
20721
|
+
const idx = nextHeaders2.findIndex((item) => Array.isArray(item) && typeof item[0] === "string" && item[0].toLowerCase() === k.toLowerCase());
|
|
20722
|
+
if (idx !== -1) {
|
|
20723
|
+
nextHeaders2[idx] = [k, v];
|
|
20724
|
+
} else {
|
|
20725
|
+
nextHeaders2.push([k, v]);
|
|
20726
|
+
}
|
|
20727
|
+
}
|
|
20728
|
+
return nextHeaders2;
|
|
20729
|
+
}
|
|
20730
|
+
const nextHeaders = {};
|
|
20731
|
+
if (initHeaders && typeof initHeaders === "object") {
|
|
20732
|
+
for (const [k, v] of Object.entries(initHeaders)) {
|
|
20733
|
+
nextHeaders[k] = String(v);
|
|
20734
|
+
}
|
|
20735
|
+
}
|
|
20736
|
+
for (const [k, v] of Object.entries(newHeaders)) {
|
|
20737
|
+
const existingKey = Object.keys(nextHeaders).find((key) => key.toLowerCase() === k.toLowerCase());
|
|
20738
|
+
if (existingKey) {
|
|
20739
|
+
nextHeaders[existingKey] = v;
|
|
20740
|
+
} else {
|
|
20741
|
+
nextHeaders[k] = v;
|
|
20742
|
+
}
|
|
20743
|
+
}
|
|
20744
|
+
return nextHeaders;
|
|
20745
|
+
}
|
|
20746
|
+
function toUrlString2(value) {
|
|
20747
|
+
if (typeof value === "string") {
|
|
20748
|
+
return value;
|
|
20749
|
+
}
|
|
20750
|
+
const candidate = value.url;
|
|
20751
|
+
if (candidate) {
|
|
20752
|
+
return candidate;
|
|
20753
|
+
}
|
|
20754
|
+
return value.toString();
|
|
20755
|
+
}
|
|
20756
|
+
function resolveModelTier2(baseModelId, init) {
|
|
20757
|
+
const parts = baseModelId.split("@");
|
|
20758
|
+
const base = parts[0] || "";
|
|
20759
|
+
const suffixTier = parts[1]?.toLowerCase();
|
|
20760
|
+
const mapping = TIER_MAPPING[base];
|
|
20761
|
+
if (!mapping) {
|
|
20762
|
+
return baseModelId;
|
|
20763
|
+
}
|
|
20764
|
+
const headerTier = getSafeHeader2(init?.headers, "x-agy-tier")?.toLowerCase() || null;
|
|
20765
|
+
const requestedTier = headerTier || suffixTier;
|
|
20766
|
+
if (requestedTier && Object.prototype.hasOwnProperty.call(mapping, requestedTier)) {
|
|
20767
|
+
return mapping[requestedTier] || baseModelId;
|
|
20768
|
+
}
|
|
20769
|
+
return mapping["medium"] ?? mapping["high"];
|
|
20770
|
+
}
|
|
20771
|
+
function loadStoredAuthFromJson() {
|
|
20772
|
+
const authPath = join6(homedir4(), ".local", "share", "opencode", "auth.json");
|
|
20773
|
+
try {
|
|
20774
|
+
if (existsSync6(authPath)) {
|
|
20775
|
+
const content = readFileSync5(authPath, "utf8");
|
|
20776
|
+
const data = JSON.parse(content);
|
|
20777
|
+
return data?.[AGY_PROVIDER_ID];
|
|
20778
|
+
}
|
|
20779
|
+
} catch {
|
|
20780
|
+
}
|
|
20781
|
+
return void 0;
|
|
20782
|
+
}
|
|
20783
|
+
function createV2FetchInterceptor(getAuthSnapshot) {
|
|
20784
|
+
return async function agyV2Fetch(input, init) {
|
|
20785
|
+
const isGL = isGenerativeLanguageRequest(input);
|
|
20786
|
+
const isInternal = toUrlString2(input).includes("cloudcode-pa.googleapis.com");
|
|
20787
|
+
if (!isGL && !isInternal) {
|
|
20788
|
+
return agyFetch(input, init);
|
|
20789
|
+
}
|
|
20790
|
+
let rawAuth = getAuthSnapshot ? await getAuthSnapshot() : void 0;
|
|
20791
|
+
if (!rawAuth) {
|
|
20792
|
+
rawAuth = loadStoredAuthFromJson();
|
|
20793
|
+
}
|
|
20794
|
+
if (!rawAuth || !isOAuthAuth(rawAuth)) {
|
|
20795
|
+
return agyFetch(input, init);
|
|
20796
|
+
}
|
|
20797
|
+
let authRecord = resolveCachedAuth(rawAuth);
|
|
20798
|
+
if (accessTokenExpired(authRecord)) {
|
|
20799
|
+
const refreshed = await refreshAccessToken(authRecord, { auth: { set: async () => {
|
|
20800
|
+
} } });
|
|
20801
|
+
if (refreshed) {
|
|
20802
|
+
authRecord = refreshed;
|
|
20803
|
+
}
|
|
20804
|
+
}
|
|
20805
|
+
if (!authRecord.access) {
|
|
20806
|
+
return agyFetch(input, init);
|
|
20807
|
+
}
|
|
20808
|
+
if (isInternal) {
|
|
20809
|
+
const hasAuth = getSafeHeader2(init?.headers, "Authorization") !== void 0;
|
|
20810
|
+
if (hasAuth) {
|
|
20811
|
+
return agyFetch(input, init);
|
|
20812
|
+
}
|
|
20813
|
+
const userAgent = buildAgyCliUserAgent();
|
|
20814
|
+
const headers = setSafeHeaders2(init?.headers, {
|
|
20815
|
+
Authorization: `Bearer ${authRecord.access}`,
|
|
20816
|
+
"User-Agent": userAgent
|
|
20817
|
+
});
|
|
20818
|
+
return agyFetch(input, {
|
|
20819
|
+
...init,
|
|
20820
|
+
headers
|
|
20821
|
+
});
|
|
20822
|
+
}
|
|
20823
|
+
const requestTarget = parseGenerativeLanguageRequest(input);
|
|
20824
|
+
const requestUserAgentModel = requestTarget?.effectiveModel;
|
|
20825
|
+
let projectContext;
|
|
20826
|
+
try {
|
|
20827
|
+
projectContext = await ensureProjectContext(
|
|
20828
|
+
authRecord,
|
|
20829
|
+
{ auth: { set: async () => {
|
|
20830
|
+
} } },
|
|
20831
|
+
void 0,
|
|
20832
|
+
requestUserAgentModel
|
|
20833
|
+
);
|
|
20834
|
+
} catch {
|
|
20835
|
+
projectContext = {
|
|
20836
|
+
effectiveProjectId: parseRefreshParts(authRecord.refresh).projectId || "antigravity",
|
|
20837
|
+
auth: authRecord
|
|
20838
|
+
};
|
|
20839
|
+
}
|
|
20840
|
+
const originalRequestedModel = parseGenerativeLanguageRequest(input)?.effectiveModel;
|
|
20841
|
+
let modifiedInput = input;
|
|
20842
|
+
if (isGL && originalRequestedModel) {
|
|
20843
|
+
const originalBase = originalRequestedModel.replace("google-agy/", "");
|
|
20844
|
+
const resolvedBase = resolveModelTier2(originalBase, init);
|
|
20845
|
+
if (originalBase !== resolvedBase) {
|
|
20846
|
+
if (typeof modifiedInput === "string") {
|
|
20847
|
+
modifiedInput = modifiedInput.replace(`models/${originalBase}`, `models/${resolvedBase}`);
|
|
20848
|
+
} else if (typeof Request !== "undefined" && modifiedInput instanceof Request) {
|
|
20849
|
+
const newUrl = modifiedInput.url.replace(`models/${originalBase}`, `models/${resolvedBase}`);
|
|
20850
|
+
modifiedInput = new Request(newUrl, modifiedInput);
|
|
20851
|
+
}
|
|
20852
|
+
}
|
|
20853
|
+
}
|
|
20854
|
+
const transformed = prepareAgyRequest(
|
|
20855
|
+
modifiedInput,
|
|
20856
|
+
init,
|
|
20857
|
+
authRecord.access,
|
|
20858
|
+
projectContext.effectiveProjectId,
|
|
20859
|
+
void 0
|
|
20860
|
+
);
|
|
20861
|
+
const chatLogger = createChatLogger();
|
|
20862
|
+
if (chatLogger) {
|
|
20863
|
+
chatLogger.logRequest(
|
|
20864
|
+
toUrlString2(transformed.request),
|
|
20865
|
+
transformed.init.method || "GET",
|
|
20866
|
+
transformed.init.headers,
|
|
20867
|
+
transformed.init.body
|
|
20868
|
+
);
|
|
20869
|
+
}
|
|
20870
|
+
const response = await fetchWithRetry(transformed.request, transformed.init);
|
|
20871
|
+
return transformAgyResponse(
|
|
20872
|
+
response,
|
|
20873
|
+
transformed.streaming,
|
|
20874
|
+
null,
|
|
20875
|
+
transformed.requestedModel,
|
|
20876
|
+
transformed.sessionId,
|
|
20877
|
+
chatLogger
|
|
20878
|
+
);
|
|
20879
|
+
};
|
|
20880
|
+
}
|
|
20679
20881
|
async function setupOpenCodeV2(ctx) {
|
|
20680
20882
|
ctx.catalog.transform(async (editor) => {
|
|
20681
20883
|
if (!editor) return;
|
|
@@ -20853,14 +21055,85 @@ async function setupOpenCodeV2(ctx) {
|
|
|
20853
21055
|
label: "Antigravity CLI (OAuth)"
|
|
20854
21056
|
},
|
|
20855
21057
|
authorize: async () => {
|
|
21058
|
+
const authUrl = new URL(AGY_AUTH_URL);
|
|
21059
|
+
authUrl.searchParams.set("client_id", AGY_CLIENT_ID);
|
|
21060
|
+
authUrl.searchParams.set("response_type", "code");
|
|
21061
|
+
authUrl.searchParams.set("redirect_uri", "http://localhost");
|
|
21062
|
+
authUrl.searchParams.set("scope", AGY_SCOPES.join(" "));
|
|
21063
|
+
authUrl.searchParams.set("access_type", "offline");
|
|
21064
|
+
authUrl.searchParams.set("prompt", "consent");
|
|
20856
21065
|
return {
|
|
20857
|
-
mode: "
|
|
20858
|
-
url:
|
|
20859
|
-
instructions: "
|
|
21066
|
+
mode: "code",
|
|
21067
|
+
url: authUrl.toString(),
|
|
21068
|
+
instructions: "Please complete Google account authorization in your browser. After authorization, copy the full redirect URL or code and paste it below:",
|
|
21069
|
+
callback: async (code) => {
|
|
21070
|
+
const trimmed = code.trim();
|
|
21071
|
+
const parsed = parseOAuthCallbackInput(trimmed);
|
|
21072
|
+
const authCode = parsed.code || trimmed;
|
|
21073
|
+
if (!authCode) {
|
|
21074
|
+
return { type: "failed", error: "Missing authorization code in callback input" };
|
|
21075
|
+
}
|
|
21076
|
+
const tokenResponse = await agyFetch(AGY_TOKEN_URL, {
|
|
21077
|
+
method: "POST",
|
|
21078
|
+
headers: {
|
|
21079
|
+
"Content-Type": "application/x-www-form-urlencoded"
|
|
21080
|
+
},
|
|
21081
|
+
body: new URLSearchParams({
|
|
21082
|
+
client_id: AGY_CLIENT_ID,
|
|
21083
|
+
client_secret: AGY_CLIENT_SECRET,
|
|
21084
|
+
code: authCode,
|
|
21085
|
+
grant_type: "authorization_code",
|
|
21086
|
+
redirect_uri: "http://localhost"
|
|
21087
|
+
})
|
|
21088
|
+
});
|
|
21089
|
+
if (!tokenResponse.ok) {
|
|
21090
|
+
const errorText = await tokenResponse.text();
|
|
21091
|
+
return { type: "failed", error: errorText };
|
|
21092
|
+
}
|
|
21093
|
+
const tokenPayload = await tokenResponse.json();
|
|
21094
|
+
if (!tokenPayload.refresh_token) {
|
|
21095
|
+
return { type: "failed", error: "Missing refresh token in response" };
|
|
21096
|
+
}
|
|
21097
|
+
const initialRefresh = formatRefreshParts({
|
|
21098
|
+
refreshToken: tokenPayload.refresh_token
|
|
21099
|
+
});
|
|
21100
|
+
let authRecord = {
|
|
21101
|
+
type: "oauth",
|
|
21102
|
+
refresh: initialRefresh,
|
|
21103
|
+
access: tokenPayload.access_token,
|
|
21104
|
+
expires: Date.now() + tokenPayload.expires_in * 1e3
|
|
21105
|
+
};
|
|
21106
|
+
try {
|
|
21107
|
+
const projectContext = await ensureProjectContext(
|
|
21108
|
+
authRecord,
|
|
21109
|
+
{ auth: { set: async () => {
|
|
21110
|
+
} } }
|
|
21111
|
+
);
|
|
21112
|
+
authRecord = {
|
|
21113
|
+
...authRecord,
|
|
21114
|
+
refresh: projectContext.auth.refresh
|
|
21115
|
+
};
|
|
21116
|
+
} catch {
|
|
21117
|
+
}
|
|
21118
|
+
return {
|
|
21119
|
+
type: "success",
|
|
21120
|
+
refresh: authRecord.refresh,
|
|
21121
|
+
access: authRecord.access,
|
|
21122
|
+
expires: authRecord.expires
|
|
21123
|
+
};
|
|
21124
|
+
}
|
|
20860
21125
|
};
|
|
20861
21126
|
}
|
|
20862
21127
|
});
|
|
20863
21128
|
});
|
|
21129
|
+
ctx.aisdk?.hook("sdk", async (event) => {
|
|
21130
|
+
if (!event) return;
|
|
21131
|
+
const isMatchingProvider = event.providerID === AGY_PROVIDER_ID || event.model?.providerID === AGY_PROVIDER_ID;
|
|
21132
|
+
if (!isMatchingProvider) return;
|
|
21133
|
+
event.options = event.options || {};
|
|
21134
|
+
event.options.apiKey = "dummy";
|
|
21135
|
+
event.options.fetch = createV2FetchInterceptor();
|
|
21136
|
+
});
|
|
20864
21137
|
ctx.session.hook(
|
|
20865
21138
|
"http.request",
|
|
20866
21139
|
async (event) => {
|