dsh-github-copilot 0.4.0-alpha.29 → 0.4.0-alpha.31

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/index.js CHANGED
@@ -962,7 +962,7 @@ let SearchRoutingController = (() => {
962
962
  //#endregion
963
963
  //#region package.json
964
964
  var name$1 = "dsh-github-copilot";
965
- var version = "0.4.0-alpha.29";
965
+ var version = "0.4.0-alpha.31";
966
966
  //#endregion
967
967
  //#region lib/types/probe.js
968
968
  /**
@@ -4603,15 +4603,24 @@ function createAccountProvider(descriptors, guard, baseURL) {
4603
4603
  }));
4604
4604
  headers.authorization = `Bearer ${options.apiKey}`;
4605
4605
  headers["x-api-key"] = null;
4606
+ let unauthorized = false;
4607
+ const fetch = options.fetch ?? globalThis.fetch;
4608
+ const observeResponse = async (input, init) => {
4609
+ const response = await fetch(input, init);
4610
+ if (response.status === 401) unauthorized = true;
4611
+ return response;
4612
+ };
4606
4613
  const wireOptions = model.api === "anthropic-messages" ? {
4607
4614
  ...options,
4608
4615
  signal: lease.signal,
4609
4616
  apiKey: void 0,
4610
- headers
4617
+ headers,
4618
+ fetch: observeResponse
4611
4619
  } : {
4612
4620
  ...options,
4613
4621
  signal: lease.signal,
4614
- headers
4622
+ headers,
4623
+ fetch: observeResponse
4615
4624
  };
4616
4625
  if (!hasApi(model, "openai-responses") && !hasApi(model, "openai-completions") && !hasApi(model, "anthropic-messages")) {
4617
4626
  lease.release();
@@ -4622,6 +4631,9 @@ function createAccountProvider(descriptors, guard, baseURL) {
4622
4631
  yield* native.streamSimple(model, context, wireOptions);
4623
4632
  } finally {
4624
4633
  lease.release();
4634
+ if (unauthorized && !guard.signal.aborted && !options.signal?.aborted) try {
4635
+ guard.onUnauthorized?.();
4636
+ } catch {}
4625
4637
  }
4626
4638
  })();
4627
4639
  })
@@ -4655,7 +4667,7 @@ function active(signal) {
4655
4667
  * Bind model discovery to the existing native OAuth lifecycle. No model catalog,
4656
4668
  * login, environment fallback or separate credential record is introduced here.
4657
4669
  */
4658
- function createAccountModelAuth(credentials) {
4670
+ function createAccountModelAuth(credentials, renewRejectedCredential) {
4659
4671
  const native = githubCopilotProvider();
4660
4672
  const oauth = native.auth.oauth;
4661
4673
  if (oauth === void 0) throw new Error("COPILOT_ACCOUNT_OAUTH_UNAVAILABLE");
@@ -4686,7 +4698,13 @@ function createAccountModelAuth(credentials) {
4686
4698
  return {
4687
4699
  async resolveAuth(signal) {
4688
4700
  try {
4689
- const key = copilotAccountKey(await readGrant(signal));
4701
+ const before = await readGrant(signal);
4702
+ const key = copilotAccountKey(before);
4703
+ const rejectedAccess = renewRejectedCredential?.(before) === true ? before.access : void 0;
4704
+ const forResolution = (grant) => rejectedAccess !== void 0 && grant.access === rejectedAccess ? {
4705
+ ...grant,
4706
+ expires: 0
4707
+ } : grant;
4690
4708
  const guardedOAuth = {
4691
4709
  ...oauth,
4692
4710
  login: async () => {
@@ -4717,15 +4735,16 @@ function createAccountModelAuth(credentials) {
4717
4735
  const value = await credentials.read(provider);
4718
4736
  active(signal);
4719
4737
  if (value?.type !== "oauth") throw new Error("COPILOT_ACCOUNT_OAUTH_REQUIRED");
4720
- matches(normalizeGitHubCopilotOAuthCredential(value), key);
4721
- return value;
4738
+ const grant = normalizeGitHubCopilotOAuthCredential(value);
4739
+ matches(grant, key);
4740
+ return forResolution(grant);
4722
4741
  },
4723
4742
  list: () => credentials.list(),
4724
4743
  modify: (provider, mutate) => credentials.modify(provider, async (value) => {
4725
4744
  active(signal);
4726
4745
  if (value?.type !== "oauth") throw new Error("COPILOT_ACCOUNT_OAUTH_REQUIRED");
4727
4746
  matches(normalizeGitHubCopilotOAuthCredential(value), key);
4728
- const next = await mutate(value);
4747
+ const next = await mutate(forResolution(normalizeGitHubCopilotOAuthCredential(value)));
4729
4748
  active(signal);
4730
4749
  if (next !== void 0) matches(normalizeGitHubCopilotOAuthCredential(next), key);
4731
4750
  return next;
@@ -4746,6 +4765,7 @@ function createAccountModelAuth(credentials) {
4746
4765
  if (resolved?.auth.apiKey === void 0) throw new Error("COPILOT_ACCOUNT_OAUTH_REQUIRED");
4747
4766
  const grant = await readGrant(signal);
4748
4767
  matches(grant, key);
4768
+ if (rejectedAccess !== void 0 && grant.access === rejectedAccess) throw new Error("COPILOT_ACCOUNT_TOKEN_REJECTED");
4749
4769
  const auth = {
4750
4770
  apiKey: resolved.auth.apiKey,
4751
4771
  baseURL: trustedGitHubCopilotBaseUrl(resolved.auth.baseUrl, grant),
@@ -5890,7 +5910,21 @@ function apply$1(ctx, config = {}) {
5890
5910
  const budgetSettings = requestBudgetSettings ?? (() => requestBudget ?? {});
5891
5911
  resolveRequestBudgetPolicy(budgetSettings());
5892
5912
  const store = createGitHubCopilotCredentialStore(ctx, GITHUB_COPILOT_PREVIEW_PROVIDER_ID);
5893
- const nativeAuth = createAccountModelAuth(createGitHubCopilotCredentialStore(ctx));
5913
+ let rejectedAuth;
5914
+ let authRecovery;
5915
+ const nativeAuth = createAccountModelAuth(createGitHubCopilotCredentialStore(ctx), (grant) => {
5916
+ const accountKey = copilotAccountKey(grant);
5917
+ if (rejectedAuth?.accountKey !== accountKey || rejectedAuth.tokenFingerprint !== tokenFingerprint(grant.access)) return false;
5918
+ const now = Date.now();
5919
+ const cooldown = Math.max(1e3, cacheSettings().accountModelFailureCooldownMs ?? 3e5);
5920
+ const age = authRecovery === void 0 ? void 0 : now - authRecovery.at;
5921
+ if (!Number.isFinite(now) || authRecovery?.accountKey === accountKey && (age === void 0 || !Number.isFinite(age) || age < cooldown)) throw failure("COPILOT_PREVIEW_AUTH_RECOVERY_COOLDOWN");
5922
+ authRecovery = {
5923
+ accountKey,
5924
+ at: now
5925
+ };
5926
+ return true;
5927
+ });
5894
5928
  const nativeModels = getBuiltinModels("github-copilot");
5895
5929
  const nativeApis = new Map(nativeModels.map((model) => [model.id, model.api]));
5896
5930
  let lastValidatedProof;
@@ -6086,7 +6120,15 @@ function apply$1(ctx, config = {}) {
6086
6120
  const optionsFor = (lease, inspectRequest) => {
6087
6121
  const guard = {
6088
6122
  ...lifetime.guard(lease),
6089
- ...inspectRequest === void 0 ? {} : { inspectRequest }
6123
+ ...inspectRequest === void 0 ? {} : { inspectRequest },
6124
+ onUnauthorized() {
6125
+ if (lease === void 0 || !lifetime.isCurrent(lease.revision) || source.readDisplaySnapshot() !== lease.snapshot || provenSnapshot !== lease.snapshot || snapshotProof !== lease.proof) return;
6126
+ rejectedAuth = lease.proof;
6127
+ lifetime.change();
6128
+ provenSnapshot = void 0;
6129
+ snapshotProof = void 0;
6130
+ lastValidatedProof = void 0;
6131
+ }
6090
6132
  };
6091
6133
  const { provider } = createAccountProvider(lease?.snapshot.models ?? [], guard, lease?.proof.baseURL ?? "https://api.individual.githubcopilot.com");
6092
6134
  const profile = Object.freeze({
@@ -11,5 +11,5 @@ export declare function copilotEntitlementKey(grant: Pick<GitHubCopilotOAuthCred
11
11
  * Bind model discovery to the existing native OAuth lifecycle. No model catalog,
12
12
  * login, environment fallback or separate credential record is introduced here.
13
13
  */
14
- export declare function createAccountModelAuth(credentials: CredentialStore): Pick<AccountModelSourceDependencies, 'resolveAuth' | 'assertAuthCurrent'>;
14
+ export declare function createAccountModelAuth(credentials: CredentialStore, renewRejectedCredential?: (grant: GitHubCopilotOAuthCredential) => boolean): Pick<AccountModelSourceDependencies, 'resolveAuth' | 'assertAuthCurrent'>;
15
15
  //# sourceMappingURL=account-model-auth.d.ts.map
@@ -11,6 +11,8 @@ export interface PreviewProviderGuard {
11
11
  signal: AbortSignal;
12
12
  release(): void;
13
13
  }>;
14
+ /** Actual model HTTP 401 only; called after release, without replaying the request. */
15
+ onUnauthorized?(): void;
14
16
  }
15
17
  /** Guard for one selected model in an account-bound descriptor snapshot. */
16
18
  export interface AccountProviderGuard extends PreviewProviderGuard {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "dsh-github-copilot",
3
3
  "description": "DSH companion for GitHub Copilot sign-in, account-aware model profiles, tool compatibility, and provider-hosted search.",
4
- "version": "0.4.0-alpha.29",
4
+ "version": "0.4.0-alpha.31",
5
5
  "publishConfig": {
6
6
  "access": "public",
7
7
  "registry": "https://registry.npmjs.org/",