@anthonyhaussman/opencode-agy-auth 1.2.3-alpha.7 → 1.2.3-alpha.9

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
@@ -20694,7 +20694,7 @@ function defineOpenCodeV2Plugin(def) {
20694
20694
  // src/plugin/v2.ts
20695
20695
  import { homedir as homedir4 } from "os";
20696
20696
  import { join as join6 } from "path";
20697
- import { existsSync as existsSync6, readFileSync as readFileSync5 } from "fs";
20697
+ import { existsSync as existsSync6, mkdirSync as mkdirSync5, readFileSync as readFileSync5, writeFileSync as writeFileSync5 } from "fs";
20698
20698
  import "http";
20699
20699
  var AGY_V2_QUOTA_COMMAND = "agy-quota";
20700
20700
  var AGY_V2_QUOTA_SUMMARY_COMMAND = "agy-quota-summary";
@@ -20811,6 +20811,34 @@ function loadStoredAuthFromJson() {
20811
20811
  }
20812
20812
  return void 0;
20813
20813
  }
20814
+ function saveStoredAuthToJson(authRecord) {
20815
+ if (process.env.NODE_ENV === "test" || process.env.VITEST || storedAuthOverrideForTesting !== void 0) {
20816
+ return;
20817
+ }
20818
+ try {
20819
+ const dirPath = join6(homedir4(), ".local", "share", "opencode");
20820
+ if (!existsSync6(dirPath)) {
20821
+ mkdirSync5(dirPath, { recursive: true });
20822
+ }
20823
+ const authPath = join6(dirPath, "auth.json");
20824
+ let data = {};
20825
+ if (existsSync6(authPath)) {
20826
+ try {
20827
+ data = JSON.parse(readFileSync5(authPath, "utf8")) || {};
20828
+ } catch {
20829
+ data = {};
20830
+ }
20831
+ }
20832
+ data[AGY_PROVIDER_ID] = {
20833
+ type: "oauth",
20834
+ refresh: authRecord.refresh,
20835
+ access: authRecord.access,
20836
+ expires: authRecord.expires
20837
+ };
20838
+ writeFileSync5(authPath, JSON.stringify(data, null, 2), "utf8");
20839
+ } catch {
20840
+ }
20841
+ }
20814
20842
  function createV2FetchInterceptor(getAuthSnapshot) {
20815
20843
  return async function agyV2Fetch(input, init) {
20816
20844
  const isGL = isGenerativeLanguageRequest(input);
@@ -21126,8 +21154,10 @@ async function setupOpenCodeV2(ctx) {
21126
21154
  };
21127
21155
  } catch {
21128
21156
  }
21157
+ saveStoredAuthToJson(authRecord);
21129
21158
  return {
21130
- type: "success",
21159
+ type: "oauth",
21160
+ methodID: "oauth",
21131
21161
  refresh: authRecord.refresh,
21132
21162
  access: authRecord.access,
21133
21163
  expires: authRecord.expires
@@ -21145,6 +21175,7 @@ async function setupOpenCodeV2(ctx) {
21145
21175
  event.options.apiKey = "dummy";
21146
21176
  event.options.fetch = createV2FetchInterceptor();
21147
21177
  });
21178
+ let lastInterceptedModel;
21148
21179
  ctx.session.hook(
21149
21180
  "http.request",
21150
21181
  async (event) => {
@@ -21157,9 +21188,31 @@ async function setupOpenCodeV2(ctx) {
21157
21188
  }
21158
21189
  event.headers = event.headers || {};
21159
21190
  let modelName;
21191
+ let rawAuth = event.auth;
21192
+ if (rawAuth && !rawAuth.type) {
21193
+ const tokenVal = rawAuth.access || rawAuth.token;
21194
+ if (tokenVal || rawAuth.refresh) {
21195
+ rawAuth = { type: "oauth", access: tokenVal, ...rawAuth };
21196
+ }
21197
+ }
21198
+ if (!rawAuth || !isOAuthAuth(rawAuth)) {
21199
+ rawAuth = loadStoredAuthFromJson();
21200
+ }
21201
+ let authRecord = rawAuth && isOAuthAuth(rawAuth) ? resolveCachedAuth(rawAuth) : void 0;
21202
+ if (authRecord && accessTokenExpired(authRecord)) {
21203
+ const refreshed = await refreshAccessToken(authRecord, { auth: { set: async () => {
21204
+ } } });
21205
+ if (refreshed) {
21206
+ authRecord = refreshed;
21207
+ saveStoredAuthToJson(refreshed);
21208
+ }
21209
+ }
21160
21210
  if (isGL) {
21161
21211
  const parsed = parseGenerativeLanguageRequest(rawUrl);
21162
21212
  modelName = parsed?.effectiveModel;
21213
+ if (modelName) {
21214
+ lastInterceptedModel = modelName;
21215
+ }
21163
21216
  if (typeof event.headers.delete === "function") {
21164
21217
  event.headers.delete("x-goog-api-key");
21165
21218
  event.headers.delete("api-key");
@@ -21184,6 +21237,7 @@ async function setupOpenCodeV2(ctx) {
21184
21237
  }
21185
21238
  }
21186
21239
  }
21240
+ let cleanUrl = rawUrl;
21187
21241
  try {
21188
21242
  const parsedUrl = new URL(rawUrl);
21189
21243
  let urlChanged = false;
@@ -21194,63 +21248,187 @@ async function setupOpenCodeV2(ctx) {
21194
21248
  }
21195
21249
  }
21196
21250
  if (urlChanged) {
21197
- const cleanedUrl = parsedUrl.toString();
21198
- if (typeof event.url === "string") {
21199
- event.url = cleanedUrl;
21251
+ cleanUrl = parsedUrl.toString();
21252
+ }
21253
+ } catch {
21254
+ }
21255
+ if (authRecord && authRecord.access) {
21256
+ let projectContext;
21257
+ try {
21258
+ projectContext = await ensureProjectContext(
21259
+ authRecord,
21260
+ { auth: { set: async () => {
21261
+ } } },
21262
+ void 0,
21263
+ modelName
21264
+ );
21265
+ } catch {
21266
+ projectContext = {
21267
+ effectiveProjectId: parseRefreshParts(authRecord.refresh).projectId || "antigravity",
21268
+ auth: authRecord
21269
+ };
21270
+ }
21271
+ const originalRequestedModel = modelName;
21272
+ let modifiedUrl = cleanUrl;
21273
+ if (originalRequestedModel) {
21274
+ const originalBase = originalRequestedModel.replace("google-agy/", "");
21275
+ const initHeaders = event.headers instanceof Headers ? event.headers : event.request?.headers;
21276
+ const resolvedBase = resolveModelTier2(originalBase, { headers: initHeaders });
21277
+ if (originalBase !== resolvedBase) {
21278
+ modifiedUrl = modifiedUrl.replace(`models/${originalBase}`, `models/${resolvedBase}`);
21200
21279
  }
21201
- if (event.request && typeof event.request === "object") {
21202
- if (typeof event.request.url === "string") {
21203
- event.request.url = cleanedUrl;
21280
+ }
21281
+ let bodyPayload = event.body;
21282
+ if (bodyPayload === void 0 && event.request) {
21283
+ if (typeof event.request.clone === "function") {
21284
+ try {
21285
+ bodyPayload = await event.request.clone().text();
21286
+ } catch {
21204
21287
  }
21288
+ } else if (event.request.body !== void 0) {
21289
+ bodyPayload = event.request.body;
21205
21290
  }
21206
21291
  }
21207
- } catch {
21208
- }
21209
- const hasAuth = typeof event.headers?.get === "function" ? !!event.headers.get("Authorization") : event.headers && Object.keys(event.headers).some((k) => k.toLowerCase() === "authorization");
21210
- if (!hasAuth) {
21211
- let token;
21212
- if (typeof event.auth?.access === "string" && event.auth.access) {
21213
- token = event.auth.access;
21214
- } else if (typeof event.auth?.token === "string" && event.auth.token) {
21215
- token = event.auth.token;
21216
- } else {
21217
- const storedAuth = loadStoredAuthFromJson();
21218
- if (storedAuth && isOAuthAuth(storedAuth)) {
21219
- const resolved = resolveCachedAuth(storedAuth);
21220
- token = resolved.access;
21292
+ let preExistingUserAgent;
21293
+ if (typeof event.headers?.get === "function") {
21294
+ preExistingUserAgent = event.headers.get("user-agent") || event.headers.get("User-Agent") || void 0;
21295
+ } else if (event.headers && typeof event.headers === "object") {
21296
+ preExistingUserAgent = event.headers["user-agent"] || event.headers["User-Agent"] || void 0;
21297
+ }
21298
+ if (!preExistingUserAgent && typeof event.request?.headers?.get === "function") {
21299
+ preExistingUserAgent = event.request.headers.get("user-agent") || event.request.headers.get("User-Agent") || void 0;
21300
+ } else if (!preExistingUserAgent && event.request?.headers && typeof event.request.headers === "object") {
21301
+ preExistingUserAgent = event.request.headers["user-agent"] || event.request.headers["User-Agent"] || void 0;
21302
+ }
21303
+ const method = event.method || event.request?.method || "POST";
21304
+ const requestHeaders = event.headers || event.request?.headers;
21305
+ const transformed = prepareAgyRequest(
21306
+ modifiedUrl,
21307
+ {
21308
+ method,
21309
+ headers: requestHeaders,
21310
+ body: bodyPayload
21311
+ },
21312
+ authRecord.access,
21313
+ projectContext.effectiveProjectId
21314
+ );
21315
+ const targetUrl = toUrlString2(transformed.request);
21316
+ if (typeof event.url === "string") {
21317
+ event.url = targetUrl;
21318
+ }
21319
+ if (event.request && typeof event.request === "object") {
21320
+ if (typeof Request !== "undefined" && event.request instanceof Request) {
21321
+ event.request = new Request(targetUrl, {
21322
+ method: transformed.init.method,
21323
+ headers: transformed.init.headers,
21324
+ body: transformed.init.body
21325
+ });
21326
+ } else if (typeof event.request.url === "string") {
21327
+ try {
21328
+ event.request.url = targetUrl;
21329
+ } catch {
21330
+ }
21221
21331
  }
21222
21332
  }
21223
- if (token) {
21333
+ const headerEntries = transformed.init.headers instanceof Headers ? Array.from(transformed.init.headers.entries()) : Object.entries(transformed.init.headers || {});
21334
+ for (const [k, v] of headerEntries) {
21335
+ const lowerK = k.toLowerCase();
21336
+ if (lowerK === "user-agent") {
21337
+ if (preExistingUserAgent) {
21338
+ continue;
21339
+ }
21340
+ if (typeof event.headers?.set === "function") {
21341
+ event.headers.set("User-Agent", v);
21342
+ } else if (event.headers) {
21343
+ event.headers["User-Agent"] = v;
21344
+ }
21345
+ if (event.request?.headers && typeof event.request.headers.set === "function") {
21346
+ event.request.headers.set("User-Agent", v);
21347
+ } else if (event.request?.headers && typeof event.request.headers === "object") {
21348
+ event.request.headers["User-Agent"] = v;
21349
+ }
21350
+ continue;
21351
+ }
21224
21352
  if (typeof event.headers?.set === "function") {
21225
- event.headers.set("Authorization", `Bearer ${token}`);
21353
+ event.headers.set(k, v);
21226
21354
  } else if (event.headers) {
21227
- event.headers["Authorization"] = `Bearer ${token}`;
21355
+ event.headers[k] = v;
21228
21356
  }
21229
21357
  if (event.request?.headers && typeof event.request.headers.set === "function") {
21230
- event.request.headers.set("Authorization", `Bearer ${token}`);
21358
+ event.request.headers.set(k, v);
21359
+ } else if (event.request?.headers && typeof event.request.headers === "object") {
21360
+ event.request.headers[k] = v;
21231
21361
  }
21232
21362
  }
21363
+ if (transformed.init.body !== void 0) {
21364
+ event.body = transformed.init.body;
21365
+ if (event.request && typeof event.request === "object" && !(event.request instanceof Request)) {
21366
+ event.request.body = transformed.init.body;
21367
+ }
21368
+ }
21369
+ } else {
21370
+ if (typeof event.url === "string") {
21371
+ event.url = cleanUrl;
21372
+ }
21373
+ if (event.request && typeof event.request === "object") {
21374
+ if (typeof event.request.url === "string") {
21375
+ event.request.url = cleanUrl;
21376
+ }
21377
+ }
21378
+ }
21379
+ }
21380
+ if (authRecord && authRecord.access) {
21381
+ if (typeof event.headers?.set === "function") {
21382
+ event.headers.set("Authorization", `Bearer ${authRecord.access}`);
21383
+ } else if (event.headers) {
21384
+ event.headers["Authorization"] = `Bearer ${authRecord.access}`;
21385
+ }
21386
+ if (event.request?.headers && typeof event.request.headers.set === "function") {
21387
+ event.request.headers.set("Authorization", `Bearer ${authRecord.access}`);
21388
+ } else if (event.request?.headers && typeof event.request.headers === "object") {
21389
+ event.request.headers["Authorization"] = `Bearer ${authRecord.access}`;
21233
21390
  }
21234
21391
  }
21235
21392
  const userAgent = buildAgyCliUserAgent(modelName);
21236
- if (typeof event.headers.set === "function") {
21237
- if (!event.headers.get("User-Agent")) {
21393
+ if (typeof event.headers?.set === "function") {
21394
+ if (!event.headers.get("User-Agent") && !event.headers.get("user-agent")) {
21238
21395
  event.headers.set("User-Agent", userAgent);
21239
21396
  }
21240
- } else {
21397
+ } else if (event.headers) {
21241
21398
  if (!event.headers["User-Agent"] && !event.headers["user-agent"]) {
21242
21399
  event.headers["User-Agent"] = userAgent;
21243
21400
  }
21244
21401
  }
21402
+ if (event.request?.headers && typeof event.request.headers.set === "function") {
21403
+ if (!event.request.headers.get("User-Agent") && !event.request.headers.get("user-agent")) {
21404
+ event.request.headers.set("User-Agent", userAgent);
21405
+ }
21406
+ } else if (event.request?.headers && typeof event.request.headers === "object") {
21407
+ if (!event.request.headers["User-Agent"] && !event.request.headers["user-agent"]) {
21408
+ event.request.headers["User-Agent"] = userAgent;
21409
+ }
21410
+ }
21245
21411
  },
21246
21412
  { providerID: AGY_PROVIDER_ID }
21247
21413
  );
21248
21414
  ctx.session.hook(
21249
21415
  "http.response",
21250
21416
  async (event) => {
21251
- if (!event) return;
21252
- if (event.response?.status === 429) {
21253
- return;
21417
+ if (!event || !event.response) return;
21418
+ const rawUrl = typeof event.url === "string" ? event.url : event.request?.url || "";
21419
+ const isInternal = rawUrl.includes("cloudcode-pa.googleapis.com");
21420
+ if (isInternal && event.response instanceof Response) {
21421
+ const isStreaming = rawUrl.includes(":streamGenerateCode") || event.response.headers.get("content-type")?.includes("text/event-stream");
21422
+ const parsedModel = parseGenerativeLanguageRequest(rawUrl)?.effectiveModel || lastInterceptedModel;
21423
+ const transformed = await transformAgyResponse(
21424
+ event.response,
21425
+ !!isStreaming,
21426
+ null,
21427
+ parsedModel,
21428
+ void 0,
21429
+ void 0
21430
+ );
21431
+ event.response = transformed;
21254
21432
  }
21255
21433
  },
21256
21434
  { providerID: AGY_PROVIDER_ID }