copillm 0.3.0-beta.3 → 0.3.0-beta.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.
@@ -1,7 +1,7 @@
1
1
  import { createRequire } from "node:module";
2
2
  const FALLBACK_PACKAGE_INFO = {
3
3
  name: "copillm",
4
- version: "0.3.0-beta.3"
4
+ version: "0.3.0-beta.4"
5
5
  };
6
6
  export function getPackageInfo() {
7
7
  const envName = cleanPackageValue(process.env.COPILLM_PACKAGE_NAME);
@@ -1,9 +1,18 @@
1
1
  import { setTimeout as defaultSleep } from "node:timers/promises";
2
+ import { createHash } from "node:crypto";
2
3
  import { githubUserUrl } from "../config/upstream.js";
3
4
  import { isRetryableStatus, isRetryableTransportError, retryDelayMs } from "./upstream/retryPolicy.js";
4
5
  const CACHE_TTL_MS = 5 * 60 * 1_000;
5
6
  const DEFAULT_MAX_ATTEMPTS = 3;
6
- let cached = null;
7
+ // Cache keyed by a hash of the GitHub token. It MUST be per-token: different
8
+ // tokens identify different GitHub accounts, and a token-blind cache returns
9
+ // one account's identity for another's — which silently broke multi-account
10
+ // `auth login` (a second login appeared to be the same account and overwrote
11
+ // the first). Hashing avoids retaining raw tokens as map keys.
12
+ const cache = new Map();
13
+ function cacheKey(token) {
14
+ return createHash("sha256").update(token).digest("hex");
15
+ }
7
16
  /**
8
17
  * Fetch the GitHub user summary with bounded retries on transient failures.
9
18
  *
@@ -20,8 +29,10 @@ let cached = null;
20
29
  */
21
30
  export async function getGithubUserSummary(githubToken, options = {}) {
22
31
  const now = Date.now();
23
- if (cached && now - cached.fetchedAt < CACHE_TTL_MS) {
24
- return cached.summary;
32
+ const key = cacheKey(githubToken);
33
+ const hit = cache.get(key);
34
+ if (hit && now - hit.fetchedAt < CACHE_TTL_MS) {
35
+ return hit.summary;
25
36
  }
26
37
  const fetchImpl = options.fetchImpl ?? ((input, init) => fetch(input, init));
27
38
  const sleepImpl = options.sleepImpl ?? ((ms) => defaultSleep(ms));
@@ -60,7 +71,7 @@ export async function getGithubUserSummary(githubToken, options = {}) {
60
71
  html_url: typeof payload.html_url === "string" ? payload.html_url : null,
61
72
  plan_name: typeof payload.plan?.name === "string" ? payload.plan.name : null
62
73
  };
63
- cached = { fetchedAt: Date.now(), summary };
74
+ cache.set(key, { fetchedAt: Date.now(), summary });
64
75
  return summary;
65
76
  }
66
77
  // Non-OK. 401/403/404 are terminal — fast-fail. Other retryable statuses
@@ -79,7 +90,7 @@ export async function getGithubUserSummary(githubToken, options = {}) {
79
90
  throw lastError ?? new Error("GitHub user lookup exhausted retries without error context.");
80
91
  }
81
92
  export function clearGithubUserCache() {
82
- cached = null;
93
+ cache.clear();
83
94
  }
84
95
  export class GithubUserFetchError extends Error {
85
96
  status;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "copillm",
3
- "version": "0.3.0-beta.3",
3
+ "version": "0.3.0-beta.4",
4
4
  "description": "Local Copilot proxy CLI (OpenAI/Anthropic-compatible)",
5
5
  "license": "MIT",
6
6
  "type": "module",