@nick3/copilot-api 1.7.1 → 1.9.2

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/README.md CHANGED
@@ -829,6 +829,7 @@ Here is an example `.claude/settings.json` file:
829
829
  "CLAUDE_CODE_ATTRIBUTION_HEADER": "0",
830
830
  "CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION": "false",
831
831
  "CLAUDE_CODE_DISABLE_TERMINAL_TITLE": "true",
832
+ "CLAUDE_CODE_ENABLE_AWAY_SUMMARY": "0",
832
833
  "CLAUDE_PLUGIN_ENABLE_QUESTION_RULES": "true"
833
834
  },
834
835
  "permissions": {
@@ -842,9 +843,9 @@ Here is an example `.claude/settings.json` file:
842
843
 
843
844
  - Replace `ANTHROPIC_MODEL`, `ANTHROPIC_DEFAULT_OPUS_MODEL`, `ANTHROPIC_DEFAULT_SONNET_MODEL`, and `ANTHROPIC_DEFAULT_HAIKU_MODEL` according to your needs. After configuration, please install the claude code plugin [Plugin Integrations](#plugin-integrations). If configuring the claude model, it is recommended to set all model configurations the same, so as to remain consistent with github-copilot claude agent behavior.
844
845
  - Setting CLAUDE_CODE_ATTRIBUTION_HEADER to 0 can prevent Claude code from adding billing and version information in system prompts, thereby avoiding prompt cache invalidation.
845
- - Turning off CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION can prevent quota from being consumed unnecessarily.
846
- - If you want to disable Claude Code WebSearch, deny `WebSearch` in permissions or set `useResponsesApiWebSearch` to `false` in `config.json`. When enabled, `/v1/responses` can forward `web_search` tools upstream, but actual support still depends on the selected model and Copilot behavior.
847
- - Please do not enable `ENABLE_TOOL_SEARCH`, as the current Claude Code uses the client tool search mode. In this mode, loading defer tools requires an additional request each time, and cache hit rates are affected, so it does not necessarily save tokens. Only server tool search mode can save tokens. The current project has compatibility issues with client tool search mode, which can also cause errors when used.
846
+ - Turning off `CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION` and `CLAUDE_CODE_ENABLE_AWAY_SUMMARY` can prevent quota from being consumed unnecessarily.
847
+ - Permissions deny `WebSearch` because the GitHub Copilot API does not currently support native web search in this project. You can keep `WebSearch` denied in Claude Code permissions or set `useResponsesApiWebSearch` to `false` in `config.json`. If you need search, use an alternative tool such as `mcp_server_fetch`.
848
+ - Please do not enable `ENABLE_TOOL_SEARCH`, as the current Claude Code uses the client tool search mode. In this mode, loading deferred tools requires an additional request each time, cache hit rates are affected, and it does not necessarily save tokens. Only server-side tool search can potentially save tokens. The current project still has compatibility issues with client tool search mode, which can also cause errors when used.
848
849
 
849
850
  ### CLAUDE.md or AGENTS.md Recommended Content
850
851
 
package/README.zh-CN.md CHANGED
@@ -836,6 +836,7 @@ npx @nick3/copilot-api@latest start --claude-code
836
836
  "CLAUDE_CODE_ATTRIBUTION_HEADER": "0",
837
837
  "CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION": "false",
838
838
  "CLAUDE_CODE_DISABLE_TERMINAL_TITLE": "true",
839
+ "CLAUDE_CODE_ENABLE_AWAY_SUMMARY": "0",
839
840
  "CLAUDE_PLUGIN_ENABLE_QUESTION_RULES": "true"
840
841
  },
841
842
  "permissions": {
@@ -849,9 +850,9 @@ npx @nick3/copilot-api@latest start --claude-code
849
850
 
850
851
  - 请根据需要替换 `ANTHROPIC_MODEL`、`ANTHROPIC_DEFAULT_OPUS_MODEL`、`ANTHROPIC_DEFAULT_SONNET_MODEL` 和 `ANTHROPIC_DEFAULT_HAIKU_MODEL`。配置完成后,请安装 Claude Code 插件,见 [插件集成](#plugin-integrations)。如果你配置的是 Claude 模型,建议把这些模型配置尽量设为一致,以保持与 GitHub Copilot Claude agent 行为一致。
851
852
  - 将 `CLAUDE_CODE_ATTRIBUTION_HEADER` 设为 `0` 可以阻止 Claude Code 在 system prompt 中附加计费和版本信息,从而避免 prompt cache 失效。
852
- - 关闭 `CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION` 可以避免不必要地消耗额度。
853
- - 如果你想禁用 Claude Code 的 WebSearch,可以在 `permissions` 中拒绝 `WebSearch`,或在 `config.json` 中将 `useResponsesApiWebSearch` 设为 `false`。开启后,`/v1/responses` 仍可以向上游转发 `web_search` 工具,但实际是否可用仍取决于所选模型与 Copilot 上游行为。
854
- - 请不要启用 `ENABLE_TOOL_SEARCH`。Claude Code 当前使用的是客户端 tool search 模式,在该模式下每次加载 defer tools 都需要额外请求一次,缓存命中率也会受到影响,因此不一定真的省 token。只有服务端 tool search 模式才有节省 token 的空间,而本项目目前与客户端 tool search 模式仍存在兼容性问题,启用后也可能引发错误。
853
+ - 关闭 `CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION` 和 `CLAUDE_CODE_ENABLE_AWAY_SUMMARY` 可以避免不必要地消耗额度。
854
+ - `permissions` 中默认禁止 `WebSearch`,因为当前项目下 GitHub Copilot API 还不支持原生 web search。你可以继续在 Claude Code 的 `permissions` 中拒绝 `WebSearch`,或在 `config.json` 中将 `useResponsesApiWebSearch` 设为 `false`。如果需要搜索能力,建议使用 `mcp_server_fetch` 等替代工具。
855
+ - 请不要启用 `ENABLE_TOOL_SEARCH`。Claude Code 当前使用的是客户端 tool search 模式;每次加载 deferred tools 都需要额外请求,会影响缓存命中率,而且本项目目前与该模式仍存在兼容性问题,启用后也可能引发错误。
855
856
 
856
857
  <a id="claudemd-or-agentsmd-recommended-content"></a>
857
858
 
@@ -1,4 +1,4 @@
1
- import { w as normalizeDomain } from "./poll-access-token-c2IYJJHM.js";
1
+ import { w as normalizeDomain } from "./poll-access-token-Dvk6Ho0R.js";
2
2
  import { n as accountTokenPath, t as PATHS } from "./paths-DGlr310R.js";
3
3
  import fs from "node:fs/promises";
4
4
  import { z } from "zod";
@@ -367,4 +367,4 @@ function parseAccountType(value) {
367
367
 
368
368
  //#endregion
369
369
  export { DEFAULT_IDENTITY_ENTERPRISE_DOMAIN as _, getAccountClientIdentityByLoginAndApp as a, getCurrentIdentityEnvironment as b, isAccountEnabled as c, loadRegistry as d, readLegacyToken as f, saveRegistry as g, saveAccountToken as h, ensureAccountClientIdentity as i, listAccountsFromRegistry as l, removeAccountToken as m, parseAccountType as n, hasLegacyToken as o, removeAccountFromRegistry as p, addAccountToRegistry as r, hasRegistry as s, isAccountType as t, loadAccountToken as u, buildIdentityKey as v, createAccountSessionId as y };
370
- //# sourceMappingURL=account-B4EBsn8H.js.map
370
+ //# sourceMappingURL=account-MllYSdRC.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"account-B4EBsn8H.js","names":["registryLock: Promise<void>","releaseLock!: () => void","parsed: unknown","registry: AccountRegistry","index: number","ACCOUNT_TYPE_VALUES: ReadonlyArray<AccountType>"],"sources":["../src/lib/account-client-identity.ts","../src/lib/accounts-registry.ts","../src/lib/types/account.ts"],"sourcesContent":["import { createHash, randomUUID } from \"node:crypto\"\n\nimport { normalizeDomain } from \"./api-config\"\n\nexport const DEFAULT_IDENTITY_OAUTH_APP = \"default\"\nexport const DEFAULT_IDENTITY_ENTERPRISE_DOMAIN = \"public\"\n\nexport interface AccountIdentityEnvironment {\n oauthApp: string\n enterpriseDomain: string\n}\n\nexport const getCurrentIdentityEnvironment = (): AccountIdentityEnvironment => {\n const rawOauthApp = process.env.COPILOT_API_OAUTH_APP?.trim().toLowerCase()\n const rawEnterpriseDomain = process.env.COPILOT_API_ENTERPRISE_URL?.trim()\n\n return {\n oauthApp: rawOauthApp || DEFAULT_IDENTITY_OAUTH_APP,\n enterpriseDomain:\n rawEnterpriseDomain ?\n normalizeDomain(rawEnterpriseDomain).toLowerCase()\n : DEFAULT_IDENTITY_ENTERPRISE_DOMAIN,\n }\n}\n\nexport const buildIdentityKey = ({\n login,\n oauthApp,\n enterpriseDomain,\n}: {\n login: string\n oauthApp: string\n enterpriseDomain: string\n}): string => `${enterpriseDomain}:${oauthApp}:${login}`\n\nexport const createAccountDeviceId = (): string => randomUUID().toLowerCase()\n\nexport const createAccountMachineId = (): string =>\n createHash(\"sha256\").update(randomUUID(), \"utf8\").digest(\"hex\")\n\nexport const createAccountSessionId = (): string =>\n randomUUID() + Date.now().toString()\n","import fs from \"node:fs/promises\"\nimport { z } from \"zod\"\n\nimport type {\n AccountClientIdentity,\n AccountMeta,\n AccountRegistry,\n} from \"~/lib/types/account\"\n\nimport {\n DEFAULT_IDENTITY_ENTERPRISE_DOMAIN,\n buildIdentityKey,\n createAccountDeviceId,\n createAccountMachineId,\n getCurrentIdentityEnvironment,\n} from \"~/lib/account-client-identity\"\nimport { accountTokenPath, PATHS } from \"~/lib/paths\"\n\n/**\n * Validate account ID (GitHub login).\n * Rules:\n * - Only alphanumeric characters or single hyphens\n * - 1-39 chars\n * - Cannot begin or end with a hyphen\n * - No consecutive hyphens\n */\nexport function validateAccountId(id: string): boolean {\n if (id.length === 0 || id.length > 39) return false\n if (!/^[a-z0-9-]+$/i.test(id)) return false\n if (id.startsWith(\"-\") || id.endsWith(\"-\")) return false\n if (id.includes(\"--\")) return false\n return true\n}\n\nconst accountMetaSchema = z.object({\n id: z.string().refine(validateAccountId, {\n message:\n \"Invalid account id. Expected a GitHub login (1-39 chars, alphanumeric or single hyphens, no leading/trailing hyphen, no consecutive hyphens).\",\n }),\n accountType: z.enum([\"individual\", \"business\", \"enterprise\"]),\n addedAt: z.number(),\n enabled: z.boolean().optional(),\n})\n\n/**\n * Check whether an account is enabled for request routing.\n * Treats `undefined` and `true` as enabled (backward compatible).\n */\nexport function isAccountEnabled(meta: AccountMeta): boolean {\n return meta.enabled !== false\n}\n\nconst accountClientIdentitySchema = z.object({\n login: z.string().refine(validateAccountId, {\n message:\n \"Invalid client identity login. Expected a GitHub login (1-39 chars, alphanumeric or single hyphens, no leading/trailing hyphen, no consecutive hyphens).\",\n }),\n oauthApp: z.string().min(1),\n enterpriseDomain: z.string().min(1),\n deviceId: z\n .string()\n .regex(\n /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/u,\n \"Invalid device ID format. Expected a lowercase UUID.\",\n ),\n machineId: z\n .string()\n .regex(\n /^[0-9a-f]{64}$/u,\n \"Invalid machine ID format. Expected 64 lowercase hexadecimal characters.\",\n ),\n createdAt: z.number(),\n})\n\nconst accountRegistryV1Schema = z.object({\n version: z.literal(1),\n accounts: z.array(accountMetaSchema),\n})\n\nconst accountRegistryV2Schema = z.object({\n version: z.literal(2),\n accounts: z.array(accountMetaSchema),\n clientIdentities: z.record(z.string(), accountClientIdentitySchema),\n})\n\nconst identityLocks = new Map<string, Promise<AccountClientIdentity>>()\nlet registryLock: Promise<void> = Promise.resolve()\n\nconst runWithRegistryLock = async <T>(\n operation: () => Promise<T>,\n): Promise<T> => {\n const previousLock = registryLock\n let releaseLock!: () => void\n registryLock = new Promise<void>((resolve) => {\n releaseLock = resolve\n })\n\n await previousLock\n\n try {\n return await operation()\n } finally {\n releaseLock()\n }\n}\n\n/**\n * Create an empty registry with the current schema version.\n */\nfunction createEmptyRegistry(): AccountRegistry {\n return {\n version: 2,\n accounts: [],\n clientIdentities: {},\n }\n}\n\nconst createClientIdentity = ({\n login,\n oauthApp,\n enterpriseDomain,\n}: {\n login: string\n oauthApp: string\n enterpriseDomain: string\n}): AccountClientIdentity => ({\n login,\n oauthApp,\n enterpriseDomain,\n deviceId: createAccountDeviceId(),\n machineId: createAccountMachineId(),\n createdAt: Date.now(),\n})\n\nconst ensureRegistryIdentity = (\n registry: AccountRegistry,\n {\n login,\n oauthApp,\n enterpriseDomain,\n }: {\n login: string\n oauthApp: string\n enterpriseDomain: string\n },\n): AccountClientIdentity => {\n const identityKey = buildIdentityKey({ login, oauthApp, enterpriseDomain })\n const existing = registry.clientIdentities[identityKey]\n if (existing) {\n return existing\n }\n\n const created = createClientIdentity({\n login,\n oauthApp,\n enterpriseDomain,\n })\n registry.clientIdentities[identityKey] = created\n return created\n}\n\nconst ensureClientIdentitiesForAccounts = (\n registry: AccountRegistry,\n): boolean => {\n const { oauthApp, enterpriseDomain } = getCurrentIdentityEnvironment()\n const countBefore = Object.keys(registry.clientIdentities).length\n\n for (const account of registry.accounts) {\n ensureRegistryIdentity(registry, {\n login: account.id,\n oauthApp,\n enterpriseDomain,\n })\n }\n\n return Object.keys(registry.clientIdentities).length !== countBefore\n}\n\nconst assertNoDuplicateAccounts = (registry: {\n accounts: Array<AccountMeta>\n}) => {\n const seen = new Set<string>()\n for (const account of registry.accounts) {\n if (seen.has(account.id)) {\n throw new Error(\n `Invalid accounts registry at ${PATHS.ACCOUNTS_REGISTRY_PATH}: duplicate account id \"${account.id}\"`,\n )\n }\n seen.add(account.id)\n }\n}\n\nconst loadRegistrySnapshot = async (): Promise<{\n registry: AccountRegistry\n shouldPersist: boolean\n}> => {\n try {\n const content = await fs.readFile(PATHS.ACCOUNTS_REGISTRY_PATH, \"utf8\")\n if (!content.trim()) {\n return {\n registry: createEmptyRegistry(),\n shouldPersist: false,\n }\n }\n\n let parsed: unknown\n try {\n parsed = JSON.parse(content) as unknown\n } catch (error) {\n throw new Error(\n `Invalid accounts registry JSON at ${PATHS.ACCOUNTS_REGISTRY_PATH}: ${\n error instanceof Error ? error.message : String(error)\n }`,\n )\n }\n\n const isVersion2Record =\n typeof parsed === \"object\"\n && parsed !== null\n && \"version\" in parsed\n && parsed.version === 2\n const result =\n isVersion2Record ?\n accountRegistryV2Schema.safeParse(parsed)\n : accountRegistryV1Schema.safeParse(parsed)\n if (!result.success) {\n const issues = result.error.issues\n .map((issue) => `${issue.path.join(\".\")}: ${issue.message}`)\n .join(\"; \")\n\n throw new Error(\n `Invalid accounts registry at ${PATHS.ACCOUNTS_REGISTRY_PATH}: ${issues}`,\n )\n }\n\n const parsedRegistry = result.data\n const registry: AccountRegistry =\n parsedRegistry.version === 2 ?\n parsedRegistry\n : {\n version: 2,\n accounts: parsedRegistry.accounts,\n clientIdentities: {},\n }\n\n assertNoDuplicateAccounts(registry)\n\n const identitiesBackfilled = ensureClientIdentitiesForAccounts(registry)\n\n return {\n registry,\n shouldPersist: parsedRegistry.version !== 2 || identitiesBackfilled,\n }\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n return {\n registry: createEmptyRegistry(),\n shouldPersist: false,\n }\n }\n throw error\n }\n}\n\nconst saveRegistryUnlocked = async (\n registry: AccountRegistry,\n): Promise<void> => {\n const content = JSON.stringify(registry, null, 2)\n await fs.writeFile(PATHS.ACCOUNTS_REGISTRY_PATH, content, { mode: 0o600 })\n}\n\n/**\n * Load the accounts registry from disk.\n * Returns an empty registry if the file doesn't exist.\n */\nexport async function loadRegistry(): Promise<AccountRegistry> {\n return runWithRegistryLock(async () => {\n const { registry, shouldPersist } = await loadRegistrySnapshot()\n if (shouldPersist) {\n await saveRegistryUnlocked(registry)\n }\n return registry\n })\n}\n\n/**\n * Save the accounts registry to disk with secure permissions.\n */\nexport async function saveRegistry(registry: AccountRegistry): Promise<void> {\n await runWithRegistryLock(async () => {\n await saveRegistryUnlocked(registry)\n })\n}\n\nexport async function getAccountClientIdentity(\n identityKey: string,\n): Promise<AccountClientIdentity | null> {\n const registry = await loadRegistry()\n return registry.clientIdentities[identityKey] ?? null\n}\n\nexport async function getAccountClientIdentityByLoginAndApp(\n login: string,\n oauthApp: string,\n): Promise<AccountClientIdentity | null> {\n const registry = await loadRegistry()\n\n const candidates = Object.values(registry.clientIdentities).filter(\n (identity): identity is AccountClientIdentity =>\n identity !== undefined\n && identity.login === login\n && identity.oauthApp === oauthApp,\n )\n\n const preferredCandidates = candidates.filter(\n (identity) =>\n identity.enterpriseDomain !== DEFAULT_IDENTITY_ENTERPRISE_DOMAIN,\n )\n const selectionPool =\n preferredCandidates.length > 0 ? preferredCandidates : candidates\n\n return selectionPool.reduce<AccountClientIdentity | null>(\n (latest, current) => {\n if (!latest || current.createdAt > latest.createdAt) return current\n return latest\n },\n null,\n )\n}\n\nexport async function ensureAccountClientIdentity({\n login,\n oauthApp,\n enterpriseDomain,\n}: {\n login: string\n oauthApp: string\n enterpriseDomain: string\n}): Promise<AccountClientIdentity> {\n if (!validateAccountId(login)) {\n throw new Error(`Invalid account ID: ${login}`)\n }\n\n const normalizedOauthApp = oauthApp.trim()\n if (!normalizedOauthApp) {\n throw new Error(\"OAuth app namespace must not be empty\")\n }\n\n const normalizedEnterpriseDomain = enterpriseDomain.trim()\n if (!normalizedEnterpriseDomain) {\n throw new Error(\"Enterprise domain namespace must not be empty\")\n }\n\n const identityKey = buildIdentityKey({\n login,\n oauthApp: normalizedOauthApp,\n enterpriseDomain: normalizedEnterpriseDomain,\n })\n const existingLock = identityLocks.get(identityKey)\n if (existingLock) {\n return existingLock\n }\n\n const identityPromise = runWithRegistryLock(\n async (): Promise<AccountClientIdentity> => {\n const { registry, shouldPersist } = await loadRegistrySnapshot()\n const existing = registry.clientIdentities[identityKey]\n if (existing) {\n if (shouldPersist) {\n await saveRegistryUnlocked(registry)\n }\n return existing\n }\n\n const created = createClientIdentity({\n login,\n oauthApp: normalizedOauthApp,\n enterpriseDomain: normalizedEnterpriseDomain,\n })\n registry.clientIdentities[identityKey] = created\n await saveRegistryUnlocked(registry)\n return created\n },\n )\n\n identityLocks.set(identityKey, identityPromise)\n\n try {\n return await identityPromise\n } finally {\n if (identityLocks.get(identityKey) === identityPromise) {\n identityLocks.delete(identityKey)\n }\n }\n}\n\n/**\n * Add an account to the registry.\n * The account is appended to the end of the list (lowest priority).\n */\nexport async function addAccountToRegistry(meta: AccountMeta): Promise<void> {\n if (!validateAccountId(meta.id)) {\n throw new Error(`Invalid account ID: ${meta.id}`)\n }\n\n await runWithRegistryLock(async () => {\n const { registry } = await loadRegistrySnapshot()\n\n // Check for duplicate\n if (registry.accounts.some((a) => a.id === meta.id)) {\n throw new Error(`Account already exists: ${meta.id}`)\n }\n\n registry.accounts.push(meta)\n const { oauthApp, enterpriseDomain } = getCurrentIdentityEnvironment()\n ensureRegistryIdentity(registry, {\n login: meta.id,\n oauthApp,\n enterpriseDomain,\n })\n await saveRegistryUnlocked(registry)\n })\n}\n\n/**\n * Remove an account from the registry by ID or index (1-based).\n * Returns the removed account metadata.\n */\nexport async function removeAccountFromRegistry(\n idOrIndex: string | number,\n): Promise<AccountMeta> {\n return runWithRegistryLock(async () => {\n const { registry } = await loadRegistrySnapshot()\n let index: number\n\n if (typeof idOrIndex === \"number\") {\n // 1-based index\n index = idOrIndex - 1\n if (index < 0 || index >= registry.accounts.length) {\n throw new Error(`Invalid account index: ${idOrIndex}`)\n }\n } else {\n index = registry.accounts.findIndex((a) => a.id === idOrIndex)\n if (index === -1) {\n throw new Error(`Account not found: ${idOrIndex}`)\n }\n }\n\n const [removed] = registry.accounts.splice(index, 1)\n await saveRegistryUnlocked(registry)\n return removed\n })\n}\n\n/**\n * List all accounts from the registry.\n */\nexport async function listAccountsFromRegistry(): Promise<Array<AccountMeta>> {\n const registry = await loadRegistry()\n return registry.accounts\n}\n\n/**\n * Load the GitHub token for a specific account.\n * Returns null if the token file doesn't exist.\n */\nexport async function loadAccountToken(id: string): Promise<string | null> {\n if (!validateAccountId(id)) {\n throw new Error(`Invalid account ID: ${id}`)\n }\n\n try {\n const tokenPath = accountTokenPath(id)\n const token = await fs.readFile(tokenPath, \"utf8\")\n return token.trim() || null\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n return null\n }\n throw error\n }\n}\n\n/**\n * Save the GitHub token for a specific account with secure permissions.\n */\nexport async function saveAccountToken(\n id: string,\n token: string,\n): Promise<void> {\n if (!validateAccountId(id)) {\n throw new Error(`Invalid account ID: ${id}`)\n }\n\n const tokenPath = accountTokenPath(id)\n await fs.writeFile(tokenPath, token, { mode: 0o600 })\n}\n\n/**\n * Remove the GitHub token file for a specific account.\n */\nexport async function removeAccountToken(id: string): Promise<void> {\n if (!validateAccountId(id)) {\n throw new Error(`Invalid account ID: ${id}`)\n }\n\n const tokenPath = accountTokenPath(id)\n try {\n await fs.unlink(tokenPath)\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") {\n throw error\n }\n // File doesn't exist, nothing to remove\n }\n}\n\n/**\n * Check if the legacy github_token file exists.\n */\nexport async function hasLegacyToken(): Promise<boolean> {\n try {\n const content = await fs.readFile(PATHS.GITHUB_TOKEN_PATH, \"utf8\")\n return content.trim().length > 0\n } catch {\n return false\n }\n}\n\n/**\n * Read the legacy github_token file.\n * Returns null if the file doesn't exist or is empty.\n */\nexport async function readLegacyToken(): Promise<string | null> {\n try {\n const content = await fs.readFile(PATHS.GITHUB_TOKEN_PATH, \"utf8\")\n return content.trim() || null\n } catch {\n return null\n }\n}\n\n/**\n * Check if the registry file exists and has accounts.\n */\nexport async function hasRegistry(): Promise<boolean> {\n const registry = await loadRegistry()\n return registry.accounts.length > 0\n}\n","import type { ModelsResponse } from \"~/services/copilot/get-models\"\n\n/**\n * Account type for GitHub Copilot subscription.\n */\nexport type AccountType = \"individual\" | \"business\" | \"enterprise\"\n\nexport const ACCOUNT_TYPE_VALUES: ReadonlyArray<AccountType> = [\n \"individual\",\n \"business\",\n \"enterprise\",\n]\n\nexport function isAccountType(value: unknown): value is AccountType {\n return (\n typeof value === \"string\"\n && (ACCOUNT_TYPE_VALUES as ReadonlyArray<string>).includes(value)\n )\n}\n\nexport function parseAccountType(value: unknown): AccountType {\n if (!isAccountType(value)) {\n throw new Error(\n `Invalid account type: ${String(value)}. Valid values: ${ACCOUNT_TYPE_VALUES.join(\n \", \",\n )}`,\n )\n }\n return value\n}\n\n/**\n * Metadata for a registered account, stored in the registry file.\n */\nexport interface AccountMeta {\n /** GitHub login (username) */\n id: string\n /** Account subscription type */\n accountType: AccountType\n /** Timestamp when the account was added */\n addedAt: number\n /** Whether the account is enabled for request routing (undefined = true) */\n enabled?: boolean\n}\n\nexport interface AccountClientIdentity {\n /** Real GitHub login */\n login: string\n /** OAuth app namespace */\n oauthApp: string\n /** Enterprise domain namespace (\"public\" for github.com) */\n enterpriseDomain: string\n /** Account-scoped upstream device identifier */\n deviceId: string\n /** Account-scoped upstream machine identifier */\n machineId: string\n /** Creation timestamp for debugging/auditing */\n createdAt: number\n}\n\n/**\n * Registry file structure for storing account metadata.\n */\nexport interface AccountRegistry {\n /** Schema version for future migrations */\n version: 2\n /** Ordered list of accounts (order = priority) */\n accounts: Array<AccountMeta>\n /** Persistent client identities keyed by logical environment + login */\n clientIdentities: Partial<Record<string, AccountClientIdentity>>\n}\n\n/**\n * Runtime state for an account, including tokens and quota information.\n */\nexport interface AccountRuntime extends AccountMeta {\n /** Real GitHub login, used to resolve account-scoped identity */\n accountLogin?: string\n /** Persistent identity key used to load/store account-scoped identifiers */\n identityKey?: string\n /** GitHub personal access token */\n githubToken: string\n /** Copilot API token (obtained from GitHub) */\n copilotToken?: string\n /** Account-specific Copilot API base URL returned by GitHub */\n copilotApiUrl?: string\n /** VS Code version for API headers */\n vsCodeVersion?: string\n /** Account-scoped device identifier sent upstream */\n clientDeviceId?: string\n /** Account-scoped machine identifier sent upstream */\n clientMachineId?: string\n /** Account-scoped session identifier sent upstream */\n clientSessionId?: string\n /** Session refresh timer reference */\n sessionRefreshTimer?: ReturnType<typeof setTimeout>\n /** Cached available models for this account */\n models?: ModelsResponse\n /** Timestamp of last models fetch */\n lastModelsFetch?: number\n /** Whether models refresh is in progress */\n isRefreshingModels?: boolean\n /** Promise for an in-flight models refresh */\n modelsRefreshPromise?: Promise<void>\n /** Total premium interactions quota entitlement */\n premiumEntitlement?: number\n /** Remaining premium interactions quota */\n premiumRemaining?: number\n /** Reserved premium interaction units for in-flight requests */\n premiumReserved?: number\n /** Internal reservation map for idempotent release */\n premiumReservations?: Map<symbol, number>\n /** Whether this account has unlimited quota */\n unlimited?: boolean\n /** Whether this account allows overage billing (enterprise feature) */\n overagePermitted?: boolean\n /** Timestamp of last quota fetch */\n lastQuotaFetch?: number\n /** Token refresh timer reference */\n refreshTimer?: ReturnType<typeof setInterval>\n /** Whether this account has failed (e.g., 401 error) */\n failed?: boolean\n /** Failure reason if failed */\n failureReason?: string\n /** Whether quota refresh is in progress (prevents concurrent refreshes) */\n isRefreshingQuota?: boolean\n /** Promise for an in-flight quota refresh (allows concurrent callers to await the same refresh) */\n quotaRefreshPromise?: Promise<void>\n}\n\n/**\n * Context required for making API calls on behalf of an account.\n * This is a subset of AccountRuntime used by service functions.\n */\nexport interface AccountContext {\n /** Real GitHub login */\n accountLogin?: string\n /** GitHub personal access token */\n githubToken: string\n /** Copilot API token */\n copilotToken?: string\n /** Account-specific Copilot API base URL */\n copilotApiUrl?: string\n /** Account subscription type */\n accountType: AccountType\n /** VS Code version for API headers */\n vsCodeVersion?: string\n /** Account-scoped device identifier */\n clientDeviceId?: string\n /** Account-scoped machine identifier */\n clientMachineId?: string\n /** Account-scoped session identifier */\n clientSessionId?: string\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"account-MllYSdRC.js","names":["registryLock: Promise<void>","releaseLock!: () => void","parsed: unknown","registry: AccountRegistry","index: number","ACCOUNT_TYPE_VALUES: ReadonlyArray<AccountType>"],"sources":["../src/lib/account-client-identity.ts","../src/lib/accounts-registry.ts","../src/lib/types/account.ts"],"sourcesContent":["import { createHash, randomUUID } from \"node:crypto\"\n\nimport { normalizeDomain } from \"./api-config\"\n\nexport const DEFAULT_IDENTITY_OAUTH_APP = \"default\"\nexport const DEFAULT_IDENTITY_ENTERPRISE_DOMAIN = \"public\"\n\nexport interface AccountIdentityEnvironment {\n oauthApp: string\n enterpriseDomain: string\n}\n\nexport const getCurrentIdentityEnvironment = (): AccountIdentityEnvironment => {\n const rawOauthApp = process.env.COPILOT_API_OAUTH_APP?.trim().toLowerCase()\n const rawEnterpriseDomain = process.env.COPILOT_API_ENTERPRISE_URL?.trim()\n\n return {\n oauthApp: rawOauthApp || DEFAULT_IDENTITY_OAUTH_APP,\n enterpriseDomain:\n rawEnterpriseDomain ?\n normalizeDomain(rawEnterpriseDomain).toLowerCase()\n : DEFAULT_IDENTITY_ENTERPRISE_DOMAIN,\n }\n}\n\nexport const buildIdentityKey = ({\n login,\n oauthApp,\n enterpriseDomain,\n}: {\n login: string\n oauthApp: string\n enterpriseDomain: string\n}): string => `${enterpriseDomain}:${oauthApp}:${login}`\n\nexport const createAccountDeviceId = (): string => randomUUID().toLowerCase()\n\nexport const createAccountMachineId = (): string =>\n createHash(\"sha256\").update(randomUUID(), \"utf8\").digest(\"hex\")\n\nexport const createAccountSessionId = (): string =>\n randomUUID() + Date.now().toString()\n","import fs from \"node:fs/promises\"\nimport { z } from \"zod\"\n\nimport type {\n AccountClientIdentity,\n AccountMeta,\n AccountRegistry,\n} from \"~/lib/types/account\"\n\nimport {\n DEFAULT_IDENTITY_ENTERPRISE_DOMAIN,\n buildIdentityKey,\n createAccountDeviceId,\n createAccountMachineId,\n getCurrentIdentityEnvironment,\n} from \"~/lib/account-client-identity\"\nimport { accountTokenPath, PATHS } from \"~/lib/paths\"\n\n/**\n * Validate account ID (GitHub login).\n * Rules:\n * - Only alphanumeric characters or single hyphens\n * - 1-39 chars\n * - Cannot begin or end with a hyphen\n * - No consecutive hyphens\n */\nexport function validateAccountId(id: string): boolean {\n if (id.length === 0 || id.length > 39) return false\n if (!/^[a-z0-9-]+$/i.test(id)) return false\n if (id.startsWith(\"-\") || id.endsWith(\"-\")) return false\n if (id.includes(\"--\")) return false\n return true\n}\n\nconst accountMetaSchema = z.object({\n id: z.string().refine(validateAccountId, {\n message:\n \"Invalid account id. Expected a GitHub login (1-39 chars, alphanumeric or single hyphens, no leading/trailing hyphen, no consecutive hyphens).\",\n }),\n accountType: z.enum([\"individual\", \"business\", \"enterprise\"]),\n addedAt: z.number(),\n enabled: z.boolean().optional(),\n})\n\n/**\n * Check whether an account is enabled for request routing.\n * Treats `undefined` and `true` as enabled (backward compatible).\n */\nexport function isAccountEnabled(meta: AccountMeta): boolean {\n return meta.enabled !== false\n}\n\nconst accountClientIdentitySchema = z.object({\n login: z.string().refine(validateAccountId, {\n message:\n \"Invalid client identity login. Expected a GitHub login (1-39 chars, alphanumeric or single hyphens, no leading/trailing hyphen, no consecutive hyphens).\",\n }),\n oauthApp: z.string().min(1),\n enterpriseDomain: z.string().min(1),\n deviceId: z\n .string()\n .regex(\n /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/u,\n \"Invalid device ID format. Expected a lowercase UUID.\",\n ),\n machineId: z\n .string()\n .regex(\n /^[0-9a-f]{64}$/u,\n \"Invalid machine ID format. Expected 64 lowercase hexadecimal characters.\",\n ),\n createdAt: z.number(),\n})\n\nconst accountRegistryV1Schema = z.object({\n version: z.literal(1),\n accounts: z.array(accountMetaSchema),\n})\n\nconst accountRegistryV2Schema = z.object({\n version: z.literal(2),\n accounts: z.array(accountMetaSchema),\n clientIdentities: z.record(z.string(), accountClientIdentitySchema),\n})\n\nconst identityLocks = new Map<string, Promise<AccountClientIdentity>>()\nlet registryLock: Promise<void> = Promise.resolve()\n\nconst runWithRegistryLock = async <T>(\n operation: () => Promise<T>,\n): Promise<T> => {\n const previousLock = registryLock\n let releaseLock!: () => void\n registryLock = new Promise<void>((resolve) => {\n releaseLock = resolve\n })\n\n await previousLock\n\n try {\n return await operation()\n } finally {\n releaseLock()\n }\n}\n\n/**\n * Create an empty registry with the current schema version.\n */\nfunction createEmptyRegistry(): AccountRegistry {\n return {\n version: 2,\n accounts: [],\n clientIdentities: {},\n }\n}\n\nconst createClientIdentity = ({\n login,\n oauthApp,\n enterpriseDomain,\n}: {\n login: string\n oauthApp: string\n enterpriseDomain: string\n}): AccountClientIdentity => ({\n login,\n oauthApp,\n enterpriseDomain,\n deviceId: createAccountDeviceId(),\n machineId: createAccountMachineId(),\n createdAt: Date.now(),\n})\n\nconst ensureRegistryIdentity = (\n registry: AccountRegistry,\n {\n login,\n oauthApp,\n enterpriseDomain,\n }: {\n login: string\n oauthApp: string\n enterpriseDomain: string\n },\n): AccountClientIdentity => {\n const identityKey = buildIdentityKey({ login, oauthApp, enterpriseDomain })\n const existing = registry.clientIdentities[identityKey]\n if (existing) {\n return existing\n }\n\n const created = createClientIdentity({\n login,\n oauthApp,\n enterpriseDomain,\n })\n registry.clientIdentities[identityKey] = created\n return created\n}\n\nconst ensureClientIdentitiesForAccounts = (\n registry: AccountRegistry,\n): boolean => {\n const { oauthApp, enterpriseDomain } = getCurrentIdentityEnvironment()\n const countBefore = Object.keys(registry.clientIdentities).length\n\n for (const account of registry.accounts) {\n ensureRegistryIdentity(registry, {\n login: account.id,\n oauthApp,\n enterpriseDomain,\n })\n }\n\n return Object.keys(registry.clientIdentities).length !== countBefore\n}\n\nconst assertNoDuplicateAccounts = (registry: {\n accounts: Array<AccountMeta>\n}) => {\n const seen = new Set<string>()\n for (const account of registry.accounts) {\n if (seen.has(account.id)) {\n throw new Error(\n `Invalid accounts registry at ${PATHS.ACCOUNTS_REGISTRY_PATH}: duplicate account id \"${account.id}\"`,\n )\n }\n seen.add(account.id)\n }\n}\n\nconst loadRegistrySnapshot = async (): Promise<{\n registry: AccountRegistry\n shouldPersist: boolean\n}> => {\n try {\n const content = await fs.readFile(PATHS.ACCOUNTS_REGISTRY_PATH, \"utf8\")\n if (!content.trim()) {\n return {\n registry: createEmptyRegistry(),\n shouldPersist: false,\n }\n }\n\n let parsed: unknown\n try {\n parsed = JSON.parse(content) as unknown\n } catch (error) {\n throw new Error(\n `Invalid accounts registry JSON at ${PATHS.ACCOUNTS_REGISTRY_PATH}: ${\n error instanceof Error ? error.message : String(error)\n }`,\n )\n }\n\n const isVersion2Record =\n typeof parsed === \"object\"\n && parsed !== null\n && \"version\" in parsed\n && parsed.version === 2\n const result =\n isVersion2Record ?\n accountRegistryV2Schema.safeParse(parsed)\n : accountRegistryV1Schema.safeParse(parsed)\n if (!result.success) {\n const issues = result.error.issues\n .map((issue) => `${issue.path.join(\".\")}: ${issue.message}`)\n .join(\"; \")\n\n throw new Error(\n `Invalid accounts registry at ${PATHS.ACCOUNTS_REGISTRY_PATH}: ${issues}`,\n )\n }\n\n const parsedRegistry = result.data\n const registry: AccountRegistry =\n parsedRegistry.version === 2 ?\n parsedRegistry\n : {\n version: 2,\n accounts: parsedRegistry.accounts,\n clientIdentities: {},\n }\n\n assertNoDuplicateAccounts(registry)\n\n const identitiesBackfilled = ensureClientIdentitiesForAccounts(registry)\n\n return {\n registry,\n shouldPersist: parsedRegistry.version !== 2 || identitiesBackfilled,\n }\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n return {\n registry: createEmptyRegistry(),\n shouldPersist: false,\n }\n }\n throw error\n }\n}\n\nconst saveRegistryUnlocked = async (\n registry: AccountRegistry,\n): Promise<void> => {\n const content = JSON.stringify(registry, null, 2)\n await fs.writeFile(PATHS.ACCOUNTS_REGISTRY_PATH, content, { mode: 0o600 })\n}\n\n/**\n * Load the accounts registry from disk.\n * Returns an empty registry if the file doesn't exist.\n */\nexport async function loadRegistry(): Promise<AccountRegistry> {\n return runWithRegistryLock(async () => {\n const { registry, shouldPersist } = await loadRegistrySnapshot()\n if (shouldPersist) {\n await saveRegistryUnlocked(registry)\n }\n return registry\n })\n}\n\n/**\n * Save the accounts registry to disk with secure permissions.\n */\nexport async function saveRegistry(registry: AccountRegistry): Promise<void> {\n await runWithRegistryLock(async () => {\n await saveRegistryUnlocked(registry)\n })\n}\n\nexport async function getAccountClientIdentity(\n identityKey: string,\n): Promise<AccountClientIdentity | null> {\n const registry = await loadRegistry()\n return registry.clientIdentities[identityKey] ?? null\n}\n\nexport async function getAccountClientIdentityByLoginAndApp(\n login: string,\n oauthApp: string,\n): Promise<AccountClientIdentity | null> {\n const registry = await loadRegistry()\n\n const candidates = Object.values(registry.clientIdentities).filter(\n (identity): identity is AccountClientIdentity =>\n identity !== undefined\n && identity.login === login\n && identity.oauthApp === oauthApp,\n )\n\n const preferredCandidates = candidates.filter(\n (identity) =>\n identity.enterpriseDomain !== DEFAULT_IDENTITY_ENTERPRISE_DOMAIN,\n )\n const selectionPool =\n preferredCandidates.length > 0 ? preferredCandidates : candidates\n\n return selectionPool.reduce<AccountClientIdentity | null>(\n (latest, current) => {\n if (!latest || current.createdAt > latest.createdAt) return current\n return latest\n },\n null,\n )\n}\n\nexport async function ensureAccountClientIdentity({\n login,\n oauthApp,\n enterpriseDomain,\n}: {\n login: string\n oauthApp: string\n enterpriseDomain: string\n}): Promise<AccountClientIdentity> {\n if (!validateAccountId(login)) {\n throw new Error(`Invalid account ID: ${login}`)\n }\n\n const normalizedOauthApp = oauthApp.trim()\n if (!normalizedOauthApp) {\n throw new Error(\"OAuth app namespace must not be empty\")\n }\n\n const normalizedEnterpriseDomain = enterpriseDomain.trim()\n if (!normalizedEnterpriseDomain) {\n throw new Error(\"Enterprise domain namespace must not be empty\")\n }\n\n const identityKey = buildIdentityKey({\n login,\n oauthApp: normalizedOauthApp,\n enterpriseDomain: normalizedEnterpriseDomain,\n })\n const existingLock = identityLocks.get(identityKey)\n if (existingLock) {\n return existingLock\n }\n\n const identityPromise = runWithRegistryLock(\n async (): Promise<AccountClientIdentity> => {\n const { registry, shouldPersist } = await loadRegistrySnapshot()\n const existing = registry.clientIdentities[identityKey]\n if (existing) {\n if (shouldPersist) {\n await saveRegistryUnlocked(registry)\n }\n return existing\n }\n\n const created = createClientIdentity({\n login,\n oauthApp: normalizedOauthApp,\n enterpriseDomain: normalizedEnterpriseDomain,\n })\n registry.clientIdentities[identityKey] = created\n await saveRegistryUnlocked(registry)\n return created\n },\n )\n\n identityLocks.set(identityKey, identityPromise)\n\n try {\n return await identityPromise\n } finally {\n if (identityLocks.get(identityKey) === identityPromise) {\n identityLocks.delete(identityKey)\n }\n }\n}\n\n/**\n * Add an account to the registry.\n * The account is appended to the end of the list (lowest priority).\n */\nexport async function addAccountToRegistry(meta: AccountMeta): Promise<void> {\n if (!validateAccountId(meta.id)) {\n throw new Error(`Invalid account ID: ${meta.id}`)\n }\n\n await runWithRegistryLock(async () => {\n const { registry } = await loadRegistrySnapshot()\n\n // Check for duplicate\n if (registry.accounts.some((a) => a.id === meta.id)) {\n throw new Error(`Account already exists: ${meta.id}`)\n }\n\n registry.accounts.push(meta)\n const { oauthApp, enterpriseDomain } = getCurrentIdentityEnvironment()\n ensureRegistryIdentity(registry, {\n login: meta.id,\n oauthApp,\n enterpriseDomain,\n })\n await saveRegistryUnlocked(registry)\n })\n}\n\n/**\n * Remove an account from the registry by ID or index (1-based).\n * Returns the removed account metadata.\n */\nexport async function removeAccountFromRegistry(\n idOrIndex: string | number,\n): Promise<AccountMeta> {\n return runWithRegistryLock(async () => {\n const { registry } = await loadRegistrySnapshot()\n let index: number\n\n if (typeof idOrIndex === \"number\") {\n // 1-based index\n index = idOrIndex - 1\n if (index < 0 || index >= registry.accounts.length) {\n throw new Error(`Invalid account index: ${idOrIndex}`)\n }\n } else {\n index = registry.accounts.findIndex((a) => a.id === idOrIndex)\n if (index === -1) {\n throw new Error(`Account not found: ${idOrIndex}`)\n }\n }\n\n const [removed] = registry.accounts.splice(index, 1)\n await saveRegistryUnlocked(registry)\n return removed\n })\n}\n\n/**\n * List all accounts from the registry.\n */\nexport async function listAccountsFromRegistry(): Promise<Array<AccountMeta>> {\n const registry = await loadRegistry()\n return registry.accounts\n}\n\n/**\n * Load the GitHub token for a specific account.\n * Returns null if the token file doesn't exist.\n */\nexport async function loadAccountToken(id: string): Promise<string | null> {\n if (!validateAccountId(id)) {\n throw new Error(`Invalid account ID: ${id}`)\n }\n\n try {\n const tokenPath = accountTokenPath(id)\n const token = await fs.readFile(tokenPath, \"utf8\")\n return token.trim() || null\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n return null\n }\n throw error\n }\n}\n\n/**\n * Save the GitHub token for a specific account with secure permissions.\n */\nexport async function saveAccountToken(\n id: string,\n token: string,\n): Promise<void> {\n if (!validateAccountId(id)) {\n throw new Error(`Invalid account ID: ${id}`)\n }\n\n const tokenPath = accountTokenPath(id)\n await fs.writeFile(tokenPath, token, { mode: 0o600 })\n}\n\n/**\n * Remove the GitHub token file for a specific account.\n */\nexport async function removeAccountToken(id: string): Promise<void> {\n if (!validateAccountId(id)) {\n throw new Error(`Invalid account ID: ${id}`)\n }\n\n const tokenPath = accountTokenPath(id)\n try {\n await fs.unlink(tokenPath)\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") {\n throw error\n }\n // File doesn't exist, nothing to remove\n }\n}\n\n/**\n * Check if the legacy github_token file exists.\n */\nexport async function hasLegacyToken(): Promise<boolean> {\n try {\n const content = await fs.readFile(PATHS.GITHUB_TOKEN_PATH, \"utf8\")\n return content.trim().length > 0\n } catch {\n return false\n }\n}\n\n/**\n * Read the legacy github_token file.\n * Returns null if the file doesn't exist or is empty.\n */\nexport async function readLegacyToken(): Promise<string | null> {\n try {\n const content = await fs.readFile(PATHS.GITHUB_TOKEN_PATH, \"utf8\")\n return content.trim() || null\n } catch {\n return null\n }\n}\n\n/**\n * Check if the registry file exists and has accounts.\n */\nexport async function hasRegistry(): Promise<boolean> {\n const registry = await loadRegistry()\n return registry.accounts.length > 0\n}\n","import type { ModelsResponse } from \"~/services/copilot/get-models\"\n\n/**\n * Account type for GitHub Copilot subscription.\n */\nexport type AccountType = \"individual\" | \"business\" | \"enterprise\"\n\nexport const ACCOUNT_TYPE_VALUES: ReadonlyArray<AccountType> = [\n \"individual\",\n \"business\",\n \"enterprise\",\n]\n\nexport function isAccountType(value: unknown): value is AccountType {\n return (\n typeof value === \"string\"\n && (ACCOUNT_TYPE_VALUES as ReadonlyArray<string>).includes(value)\n )\n}\n\nexport function parseAccountType(value: unknown): AccountType {\n if (!isAccountType(value)) {\n throw new Error(\n `Invalid account type: ${String(value)}. Valid values: ${ACCOUNT_TYPE_VALUES.join(\n \", \",\n )}`,\n )\n }\n return value\n}\n\n/**\n * Metadata for a registered account, stored in the registry file.\n */\nexport interface AccountMeta {\n /** GitHub login (username) */\n id: string\n /** Account subscription type */\n accountType: AccountType\n /** Timestamp when the account was added */\n addedAt: number\n /** Whether the account is enabled for request routing (undefined = true) */\n enabled?: boolean\n}\n\nexport interface AccountClientIdentity {\n /** Real GitHub login */\n login: string\n /** OAuth app namespace */\n oauthApp: string\n /** Enterprise domain namespace (\"public\" for github.com) */\n enterpriseDomain: string\n /** Account-scoped upstream device identifier */\n deviceId: string\n /** Account-scoped upstream machine identifier */\n machineId: string\n /** Creation timestamp for debugging/auditing */\n createdAt: number\n}\n\n/**\n * Registry file structure for storing account metadata.\n */\nexport interface AccountRegistry {\n /** Schema version for future migrations */\n version: 2\n /** Ordered list of accounts (order = priority) */\n accounts: Array<AccountMeta>\n /** Persistent client identities keyed by logical environment + login */\n clientIdentities: Partial<Record<string, AccountClientIdentity>>\n}\n\n/**\n * Runtime state for an account, including tokens and quota information.\n */\nexport interface AccountRuntime extends AccountMeta {\n /** Real GitHub login, used to resolve account-scoped identity */\n accountLogin?: string\n /** Persistent identity key used to load/store account-scoped identifiers */\n identityKey?: string\n /** GitHub personal access token */\n githubToken: string\n /** Copilot API token (obtained from GitHub) */\n copilotToken?: string\n /** Account-specific Copilot API base URL returned by GitHub */\n copilotApiUrl?: string\n /** VS Code version for API headers */\n vsCodeVersion?: string\n /** Account-scoped device identifier sent upstream */\n clientDeviceId?: string\n /** Account-scoped machine identifier sent upstream */\n clientMachineId?: string\n /** Account-scoped session identifier sent upstream */\n clientSessionId?: string\n /** Session refresh timer reference */\n sessionRefreshTimer?: ReturnType<typeof setTimeout>\n /** Cached available models for this account */\n models?: ModelsResponse\n /** Timestamp of last models fetch */\n lastModelsFetch?: number\n /** Whether models refresh is in progress */\n isRefreshingModels?: boolean\n /** Promise for an in-flight models refresh */\n modelsRefreshPromise?: Promise<void>\n /** Total premium interactions quota entitlement */\n premiumEntitlement?: number\n /** Remaining premium interactions quota */\n premiumRemaining?: number\n /** Reserved premium interaction units for in-flight requests */\n premiumReserved?: number\n /** Internal reservation map for idempotent release */\n premiumReservations?: Map<symbol, number>\n /** Whether this account has unlimited quota */\n unlimited?: boolean\n /** Whether this account allows overage billing (enterprise feature) */\n overagePermitted?: boolean\n /** Timestamp of last quota fetch */\n lastQuotaFetch?: number\n /** Token refresh timer reference */\n refreshTimer?: ReturnType<typeof setInterval>\n /** Whether this account has failed (e.g., 401 error) */\n failed?: boolean\n /** Failure reason if failed */\n failureReason?: string\n /** Whether quota refresh is in progress (prevents concurrent refreshes) */\n isRefreshingQuota?: boolean\n /** Promise for an in-flight quota refresh (allows concurrent callers to await the same refresh) */\n quotaRefreshPromise?: Promise<void>\n}\n\n/**\n * Context required for making API calls on behalf of an account.\n * This is a subset of AccountRuntime used by service functions.\n */\nexport interface AccountContext {\n /** Real GitHub login */\n accountLogin?: string\n /** GitHub personal access token */\n githubToken: string\n /** Copilot API token */\n copilotToken?: string\n /** Account-specific Copilot API base URL */\n copilotApiUrl?: string\n /** Account subscription type */\n accountType: AccountType\n /** VS Code version for API headers */\n vsCodeVersion?: string\n /** Account-scoped device identifier */\n clientDeviceId?: string\n /** Account-scoped machine identifier */\n clientMachineId?: string\n /** Account-scoped session identifier */\n clientSessionId?: string\n}\n"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
- import { O as accountFromState, _ as HTTPError, g as getCopilotUsage, j as consumeOutboundHeadersSnapshot, m as getGitHubUser, x as copilotModelsHeaders, y as copilotBaseUrl } from "./poll-access-token-c2IYJJHM.js";
2
- import { b as getCurrentIdentityEnvironment, c as isAccountEnabled, f as readLegacyToken, h as saveAccountToken, i as ensureAccountClientIdentity, l as listAccountsFromRegistry, o as hasLegacyToken, r as addAccountToRegistry, s as hasRegistry, u as loadAccountToken, v as buildIdentityKey, y as createAccountSessionId } from "./account-B4EBsn8H.js";
1
+ import { O as accountFromState, _ as HTTPError, g as getCopilotUsage, j as consumeOutboundHeadersSnapshot, m as getGitHubUser, x as copilotModelsHeaders, y as copilotBaseUrl } from "./poll-access-token-Dvk6Ho0R.js";
2
+ import { b as getCurrentIdentityEnvironment, c as isAccountEnabled, f as readLegacyToken, h as saveAccountToken, i as ensureAccountClientIdentity, l as listAccountsFromRegistry, o as hasLegacyToken, r as addAccountToRegistry, s as hasRegistry, u as loadAccountToken, v as buildIdentityKey, y as createAccountSessionId } from "./account-MllYSdRC.js";
3
3
  import { t as PATHS } from "./paths-DGlr310R.js";
4
- import { t as getCopilotToken } from "./get-copilot-token-COIPGosP.js";
4
+ import { t as getCopilotToken } from "./get-copilot-token-4mCKt94e.js";
5
5
  import { c as getAdminDbUserVersion, i as getRequestOutboundStore, o as getAdminDb, s as getAdminDbPath } from "./request-outbound-qyTeXbzy.js";
6
6
  import consola, { consola as consola$1 } from "consola";
7
7
  import fs from "node:fs/promises";
@@ -2871,4 +2871,4 @@ const accountsManager = new AccountsManager({ persistentAffinityStore: getShared
2871
2871
 
2872
2872
  //#endregion
2873
2873
  export { isMessageStartInputTokensFallbackEnabled as A, getModelAliasesInfo as C, getSmallModel as D, getReasoningEffortForModel as E, resolveModelAlias as F, shouldCompactUseSmallModel as I, isResponsesApiContextManagementModel as M, isResponsesApiWebSearchEnabled as N, isAccountAffinityEnabled as O, mergeConfigWithDefaults as P, getModelAliases as S, getProviderConfig as T, getAnthropicApiKey as _, getClientIpInfo as a, getExtraPromptForModel as b, normalizeChatCompletionsUsage as c, toLocalDateString as d, copilotFetch as f, getAliasTargetSet as g, PROVIDER_TYPE_ANTHROPIC as h, extractResponsesUsageFromStreamEvent as i, isMessagesApiEnabled as j, isForceAgentEnabled as k, normalizeEmbeddingsUsage as l, isDevModeEnabled as m, applySharedSessionAffinityRetention as n, getRequestHistoryStore as o, flushPendingCapture as p, extractResponsesUsageFromResult as r, getStatsStore as s, accountsManager as t, normalizeMessagesUsage as u, getClaudeTokenMultiplier as v, getModelRefreshIntervalMs as w, getLogLevel as x, getConfig as y };
2874
- //# sourceMappingURL=accounts-manager-Ca9IG0Fv.js.map
2874
+ //# sourceMappingURL=accounts-manager-BM66oT38.js.map