codex-multi-auth 2.0.2 → 2.1.1

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.
Files changed (122) hide show
  1. package/README.md +17 -5
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +91 -1
  4. package/dist/index.js.map +1 -1
  5. package/dist/lib/account-policy.d.ts +22 -0
  6. package/dist/lib/account-policy.d.ts.map +1 -0
  7. package/dist/lib/account-policy.js +159 -0
  8. package/dist/lib/account-policy.js.map +1 -0
  9. package/dist/lib/accounts.d.ts.map +1 -1
  10. package/dist/lib/accounts.js +2 -1
  11. package/dist/lib/accounts.js.map +1 -1
  12. package/dist/lib/budget-guard.d.ts +39 -0
  13. package/dist/lib/budget-guard.d.ts.map +1 -0
  14. package/dist/lib/budget-guard.js +201 -0
  15. package/dist/lib/budget-guard.js.map +1 -0
  16. package/dist/lib/codex-manager/commands/account.d.ts +13 -0
  17. package/dist/lib/codex-manager/commands/account.d.ts.map +1 -0
  18. package/dist/lib/codex-manager/commands/account.js +156 -0
  19. package/dist/lib/codex-manager/commands/account.js.map +1 -0
  20. package/dist/lib/codex-manager/commands/bridge.d.ts +6 -0
  21. package/dist/lib/codex-manager/commands/bridge.d.ts.map +1 -0
  22. package/dist/lib/codex-manager/commands/bridge.js +167 -0
  23. package/dist/lib/codex-manager/commands/bridge.js.map +1 -0
  24. package/dist/lib/codex-manager/commands/budget.d.ts +12 -0
  25. package/dist/lib/codex-manager/commands/budget.d.ts.map +1 -0
  26. package/dist/lib/codex-manager/commands/budget.js +123 -0
  27. package/dist/lib/codex-manager/commands/budget.js.map +1 -0
  28. package/dist/lib/codex-manager/commands/integrations.d.ts +6 -0
  29. package/dist/lib/codex-manager/commands/integrations.d.ts.map +1 -0
  30. package/dist/lib/codex-manager/commands/integrations.js +78 -0
  31. package/dist/lib/codex-manager/commands/integrations.js.map +1 -0
  32. package/dist/lib/codex-manager/commands/models.d.ts +14 -0
  33. package/dist/lib/codex-manager/commands/models.d.ts.map +1 -0
  34. package/dist/lib/codex-manager/commands/models.js +74 -0
  35. package/dist/lib/codex-manager/commands/models.js.map +1 -0
  36. package/dist/lib/codex-manager/commands/monitor.d.ts +22 -0
  37. package/dist/lib/codex-manager/commands/monitor.d.ts.map +1 -0
  38. package/dist/lib/codex-manager/commands/monitor.js +94 -0
  39. package/dist/lib/codex-manager/commands/monitor.js.map +1 -0
  40. package/dist/lib/codex-manager/commands/rotation.d.ts +1 -0
  41. package/dist/lib/codex-manager/commands/rotation.d.ts.map +1 -1
  42. package/dist/lib/codex-manager/commands/rotation.js +293 -10
  43. package/dist/lib/codex-manager/commands/rotation.js.map +1 -1
  44. package/dist/lib/codex-manager/commands/usage.d.ts +13 -0
  45. package/dist/lib/codex-manager/commands/usage.d.ts.map +1 -0
  46. package/dist/lib/codex-manager/commands/usage.js +347 -0
  47. package/dist/lib/codex-manager/commands/usage.js.map +1 -0
  48. package/dist/lib/codex-manager/help.d.ts.map +1 -1
  49. package/dist/lib/codex-manager/help.js +8 -0
  50. package/dist/lib/codex-manager/help.js.map +1 -1
  51. package/dist/lib/codex-manager.d.ts.map +1 -1
  52. package/dist/lib/codex-manager.js +42 -2
  53. package/dist/lib/codex-manager.js.map +1 -1
  54. package/dist/lib/config.d.ts.map +1 -1
  55. package/dist/lib/config.js +2 -22
  56. package/dist/lib/config.js.map +1 -1
  57. package/dist/lib/constants.d.ts +1 -0
  58. package/dist/lib/constants.d.ts.map +1 -1
  59. package/dist/lib/constants.js +1 -0
  60. package/dist/lib/constants.js.map +1 -1
  61. package/dist/lib/env-parsing.d.ts +21 -0
  62. package/dist/lib/env-parsing.d.ts.map +1 -0
  63. package/dist/lib/env-parsing.js +34 -0
  64. package/dist/lib/env-parsing.js.map +1 -0
  65. package/dist/lib/index.d.ts +9 -0
  66. package/dist/lib/index.d.ts.map +1 -1
  67. package/dist/lib/index.js +9 -0
  68. package/dist/lib/index.js.map +1 -1
  69. package/dist/lib/integration-generators.d.ts +14 -0
  70. package/dist/lib/integration-generators.d.ts.map +1 -0
  71. package/dist/lib/integration-generators.js +93 -0
  72. package/dist/lib/integration-generators.js.map +1 -0
  73. package/dist/lib/local-bridge.d.ts +17 -0
  74. package/dist/lib/local-bridge.d.ts.map +1 -0
  75. package/dist/lib/local-bridge.js +249 -0
  76. package/dist/lib/local-bridge.js.map +1 -0
  77. package/dist/lib/local-client-tokens.d.ts +37 -0
  78. package/dist/lib/local-client-tokens.d.ts.map +1 -0
  79. package/dist/lib/local-client-tokens.js +200 -0
  80. package/dist/lib/local-client-tokens.js.map +1 -0
  81. package/dist/lib/model-capability-matrix.d.ts +38 -0
  82. package/dist/lib/model-capability-matrix.d.ts.map +1 -0
  83. package/dist/lib/model-capability-matrix.js +89 -0
  84. package/dist/lib/model-capability-matrix.js.map +1 -0
  85. package/dist/lib/policy/runtime-policy.d.ts +59 -0
  86. package/dist/lib/policy/runtime-policy.d.ts.map +1 -0
  87. package/dist/lib/policy/runtime-policy.js +156 -0
  88. package/dist/lib/policy/runtime-policy.js.map +1 -0
  89. package/dist/lib/proactive-refresh.js +4 -4
  90. package/dist/lib/proactive-refresh.js.map +1 -1
  91. package/dist/lib/refresh-lease.d.ts.map +1 -1
  92. package/dist/lib/refresh-lease.js +1 -10
  93. package/dist/lib/refresh-lease.js.map +1 -1
  94. package/dist/lib/routing-profiles.d.ts +36 -0
  95. package/dist/lib/routing-profiles.d.ts.map +1 -0
  96. package/dist/lib/routing-profiles.js +203 -0
  97. package/dist/lib/routing-profiles.js.map +1 -0
  98. package/dist/lib/runtime-rotation-proxy.d.ts.map +1 -1
  99. package/dist/lib/runtime-rotation-proxy.js +96 -6
  100. package/dist/lib/runtime-rotation-proxy.js.map +1 -1
  101. package/dist/lib/usage/index.d.ts +5 -0
  102. package/dist/lib/usage/index.d.ts.map +1 -0
  103. package/dist/lib/usage/index.js +5 -0
  104. package/dist/lib/usage/index.js.map +1 -0
  105. package/dist/lib/usage/ledger.d.ts +12 -0
  106. package/dist/lib/usage/ledger.d.ts.map +1 -0
  107. package/dist/lib/usage/ledger.js +493 -0
  108. package/dist/lib/usage/ledger.js.map +1 -0
  109. package/dist/lib/usage/pricing.d.ts +11 -0
  110. package/dist/lib/usage/pricing.d.ts.map +1 -0
  111. package/dist/lib/usage/pricing.js +67 -0
  112. package/dist/lib/usage/pricing.js.map +1 -0
  113. package/dist/lib/usage/redaction.d.ts +10 -0
  114. package/dist/lib/usage/redaction.d.ts.map +1 -0
  115. package/dist/lib/usage/redaction.js +129 -0
  116. package/dist/lib/usage/redaction.js.map +1 -0
  117. package/dist/lib/usage/types.d.ts +89 -0
  118. package/dist/lib/usage/types.d.ts.map +1 -0
  119. package/dist/lib/usage/types.js +2 -0
  120. package/dist/lib/usage/types.js.map +1 -0
  121. package/package.json +1 -1
  122. package/scripts/codex-routing.js +19 -12
@@ -0,0 +1,249 @@
1
+ import { createServer } from "node:http";
2
+ import { Hono } from "hono";
3
+ import { fetch as undiciFetch } from "undici";
4
+ import { verifyLocalClientBearerToken } from "./local-client-tokens.js";
5
+ import { appendUsageLedgerRow } from "./usage/index.js";
6
+ const DEFAULT_HOST = "127.0.0.1";
7
+ const HOP_BY_HOP_HEADERS = new Set([
8
+ "connection",
9
+ "content-length",
10
+ "expect",
11
+ "keep-alive",
12
+ "proxy-authenticate",
13
+ "proxy-authorization",
14
+ "te",
15
+ "trailer",
16
+ "transfer-encoding",
17
+ "upgrade",
18
+ ]);
19
+ const DECODED_UPSTREAM_RESPONSE_HEADERS = new Set(["content-encoding"]);
20
+ function isLoopbackHost(host) {
21
+ const normalized = host.trim().toLowerCase();
22
+ return normalized === "127.0.0.1" || normalized === "localhost" || normalized === "::1";
23
+ }
24
+ function responseHeadersForClient(headers) {
25
+ const result = new Headers();
26
+ for (const [key, value] of headers.entries()) {
27
+ if (HOP_BY_HOP_HEADERS.has(key.toLowerCase()))
28
+ continue;
29
+ if (DECODED_UPSTREAM_RESPONSE_HEADERS.has(key.toLowerCase()))
30
+ continue;
31
+ result.set(key, value);
32
+ }
33
+ return result;
34
+ }
35
+ function forwardHeaders(headers) {
36
+ const result = new Headers(headers);
37
+ for (const key of HOP_BY_HOP_HEADERS) {
38
+ result.delete(key);
39
+ }
40
+ result.delete("host");
41
+ return result;
42
+ }
43
+ async function streamToArrayBuffer(stream) {
44
+ if (!stream)
45
+ return null;
46
+ const response = new Response(stream);
47
+ return response.arrayBuffer();
48
+ }
49
+ async function closeServer(server, sockets) {
50
+ if (!server.listening)
51
+ return;
52
+ const closed = new Promise((resolve, reject) => {
53
+ server.close((error) => {
54
+ if (error) {
55
+ reject(error);
56
+ return;
57
+ }
58
+ resolve();
59
+ });
60
+ });
61
+ server.closeIdleConnections?.();
62
+ for (const socket of sockets) {
63
+ socket.destroy();
64
+ }
65
+ await closed;
66
+ }
67
+ async function toWebRequest(req, host, port) {
68
+ const url = new URL(req.url ?? "/", `http://${host}:${port}`);
69
+ const headers = new Headers();
70
+ for (const [key, value] of Object.entries(req.headers)) {
71
+ if (value === undefined)
72
+ continue;
73
+ if (Array.isArray(value)) {
74
+ for (const item of value)
75
+ headers.append(key, item);
76
+ }
77
+ else {
78
+ headers.set(key, value);
79
+ }
80
+ }
81
+ const method = req.method ?? "GET";
82
+ const body = method === "GET" || method === "HEAD"
83
+ ? undefined
84
+ : await new Response(req).arrayBuffer();
85
+ return new Request(url, { method, headers, body });
86
+ }
87
+ function writeWebResponse(res, response) {
88
+ res.writeHead(response.status, Object.fromEntries(response.headers.entries()));
89
+ if (!response.body) {
90
+ res.end();
91
+ return;
92
+ }
93
+ const reader = response.body.getReader();
94
+ const pump = async () => {
95
+ while (true) {
96
+ const { done, value } = await reader.read();
97
+ if (done)
98
+ break;
99
+ if (value)
100
+ res.write(Buffer.from(value));
101
+ }
102
+ res.end();
103
+ };
104
+ void pump().catch((error) => {
105
+ if (!res.destroyed) {
106
+ res.destroy(error instanceof Error ? error : undefined);
107
+ }
108
+ });
109
+ }
110
+ export async function startLocalBridge(options) {
111
+ const host = options.host ?? DEFAULT_HOST;
112
+ if (!isLoopbackHost(host)) {
113
+ throw new Error("Local bridge only supports loopback hosts.");
114
+ }
115
+ const runtimeBaseUrl = options.runtimeBaseUrl.trim().replace(/\/+$/, "");
116
+ if (!runtimeBaseUrl) {
117
+ throw new Error("Local bridge requires a runtimeBaseUrl.");
118
+ }
119
+ const port = options.port ?? 0;
120
+ const fetchImpl = options.fetchImpl ?? undiciFetch;
121
+ const requireAuth = options.requireAuth ?? true;
122
+ const verifyBearerToken = options.verifyBearerToken ?? verifyLocalClientBearerToken;
123
+ const app = new Hono();
124
+ app.get("/health", (context) => context.json({
125
+ ok: true,
126
+ service: "codex-multi-auth-local-bridge",
127
+ runtimeBaseUrl,
128
+ }));
129
+ const forward = async (request, targetPath) => {
130
+ const startedAt = Date.now();
131
+ if (requireAuth) {
132
+ const token = await verifyBearerToken(request.headers.get("authorization"), startedAt);
133
+ if (!token) {
134
+ return new Response(JSON.stringify({
135
+ error: {
136
+ message: "Local bridge rejected an unauthenticated request.",
137
+ code: "local_bridge_unauthorized",
138
+ },
139
+ }), {
140
+ status: 401,
141
+ headers: { "content-type": "application/json; charset=utf-8" },
142
+ });
143
+ }
144
+ }
145
+ const targetUrl = `${runtimeBaseUrl}${targetPath}`;
146
+ let upstream;
147
+ try {
148
+ upstream = await fetchImpl(targetUrl, {
149
+ method: request.method,
150
+ headers: forwardHeaders(request.headers),
151
+ body: request.method === "GET" || request.method === "HEAD"
152
+ ? undefined
153
+ : await streamToArrayBuffer(request.body),
154
+ });
155
+ }
156
+ catch {
157
+ await appendUsageLedgerRow({
158
+ source: "local-bridge",
159
+ operation: targetPath === "/v1/models" ? "models" : "responses",
160
+ outcome: "failure",
161
+ statusCode: 502,
162
+ errorCode: "local_bridge_upstream_error",
163
+ durationMs: Date.now() - startedAt,
164
+ }).catch(() => undefined);
165
+ return new Response(JSON.stringify({
166
+ error: {
167
+ message: "Local bridge failed to reach the runtime proxy.",
168
+ code: "local_bridge_upstream_error",
169
+ },
170
+ }), {
171
+ status: 502,
172
+ headers: { "content-type": "application/json; charset=utf-8" },
173
+ });
174
+ }
175
+ await appendUsageLedgerRow({
176
+ source: "local-bridge",
177
+ operation: targetPath === "/v1/models" ? "models" : "responses",
178
+ outcome: upstream.ok ? "success" : "failure",
179
+ statusCode: upstream.status,
180
+ durationMs: Date.now() - startedAt,
181
+ }).catch(() => undefined);
182
+ return new Response(upstream.body, {
183
+ status: upstream.status,
184
+ statusText: upstream.statusText,
185
+ headers: responseHeadersForClient(upstream.headers),
186
+ });
187
+ };
188
+ app.get("/v1/models", (context) => forward(context.req.raw, "/v1/models"));
189
+ app.post("/v1/responses", (context) => forward(context.req.raw, "/v1/responses"));
190
+ app.all("*", (context) => context.json({
191
+ error: {
192
+ message: "Local bridge only accepts /health, /v1/models, and /v1/responses.",
193
+ code: "local_bridge_not_found",
194
+ },
195
+ }, 404));
196
+ const server = createServer((req, res) => {
197
+ void (async () => {
198
+ try {
199
+ const webRequest = await toWebRequest(req, host, resolvedPort);
200
+ writeWebResponse(res, await app.fetch(webRequest));
201
+ }
202
+ catch (error) {
203
+ if (!res.headersSent) {
204
+ res.writeHead(500, { "content-type": "application/json; charset=utf-8" });
205
+ res.end(`${JSON.stringify({
206
+ error: {
207
+ message: "Local bridge failed before forwarding the request.",
208
+ code: "local_bridge_error",
209
+ },
210
+ })}\n`);
211
+ }
212
+ else if (!res.destroyed) {
213
+ res.destroy(error instanceof Error ? error : undefined);
214
+ }
215
+ }
216
+ })();
217
+ });
218
+ const sockets = new Set();
219
+ server.on("connection", (socket) => {
220
+ sockets.add(socket);
221
+ socket.once("close", () => sockets.delete(socket));
222
+ });
223
+ let resolvedPort = port;
224
+ await new Promise((resolve, reject) => {
225
+ const onError = (error) => {
226
+ server.off("listening", onListening);
227
+ reject(error);
228
+ };
229
+ const onListening = () => {
230
+ server.off("error", onError);
231
+ const address = server.address();
232
+ resolvedPort =
233
+ typeof address === "object" && address ? address.port : port;
234
+ resolve();
235
+ };
236
+ server.once("error", onError);
237
+ server.once("listening", onListening);
238
+ server.listen(port, host);
239
+ });
240
+ return {
241
+ host,
242
+ port: resolvedPort,
243
+ baseUrl: `http://${host}:${resolvedPort}`,
244
+ close: async () => {
245
+ await closeServer(server, sockets);
246
+ },
247
+ };
248
+ }
249
+ //# sourceMappingURL=local-bridge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-bridge.js","sourceRoot":"","sources":["../../lib/local-bridge.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ export interface LocalClientTokenRecord {
2
+ id: string;
3
+ label: string;
4
+ prefix: string;
5
+ tokenHash: string;
6
+ createdAt: number;
7
+ lastUsedAt: number | null;
8
+ revokedAt: number | null;
9
+ }
10
+ export interface LocalClientTokenStore {
11
+ version: 1;
12
+ tokens: LocalClientTokenRecord[];
13
+ }
14
+ export interface CreatedLocalClientToken {
15
+ plainToken: string;
16
+ record: LocalClientTokenRecord;
17
+ }
18
+ export declare function getLocalClientTokenPath(): string;
19
+ export declare function loadLocalClientTokenStore(): Promise<LocalClientTokenStore>;
20
+ export declare function saveLocalClientTokenStore(store: LocalClientTokenStore): Promise<void>;
21
+ export declare function createLocalClientTokenRecord(input?: {
22
+ label?: string;
23
+ now?: number;
24
+ }): CreatedLocalClientToken;
25
+ export declare function addLocalClientToken(input?: {
26
+ label?: string;
27
+ now?: number;
28
+ }): Promise<CreatedLocalClientToken>;
29
+ export declare function rotateLocalClientToken(input: {
30
+ id: string;
31
+ label?: string;
32
+ now?: number;
33
+ }): Promise<CreatedLocalClientToken | null>;
34
+ export declare function revokeLocalClientToken(id: string, now?: number): Promise<boolean>;
35
+ export declare function verifyLocalClientBearerToken(authorizationHeader: string | null, now?: number): Promise<LocalClientTokenRecord | null>;
36
+ export declare function resetLocalClientTokenWriteQueueForTests(): void;
37
+ //# sourceMappingURL=local-client-tokens.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-client-tokens.d.ts","sourceRoot":"","sources":["../../lib/local-client-tokens.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,sBAAsB;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,MAAM,WAAW,qBAAqB;IACrC,OAAO,EAAE,CAAC,CAAC;IACX,MAAM,EAAE,sBAAsB,EAAE,CAAC;CACjC;AAED,MAAM,WAAW,uBAAuB;IACvC,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,sBAAsB,CAAC;CAC/B;AA0FD,wBAAgB,uBAAuB,IAAI,MAAM,CAEhD;AAED,wBAAsB,yBAAyB,IAAI,OAAO,CAAC,qBAAqB,CAAC,CAahF;AAED,wBAAsB,yBAAyB,CAC9C,KAAK,EAAE,qBAAqB,GAC1B,OAAO,CAAC,IAAI,CAAC,CAsCf;AAED,wBAAgB,4BAA4B,CAAC,KAAK,GAAE;IACnD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;CACR,GAAG,uBAAuB,CAY/B;AAED,wBAAsB,mBAAmB,CAAC,KAAK,GAAE;IAChD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;CACR,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAMxC;AAED,wBAAsB,sBAAsB,CAAC,KAAK,EAAE;IACnD,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;CACb,GAAG,OAAO,CAAC,uBAAuB,GAAG,IAAI,CAAC,CAa1C;AAED,wBAAsB,sBAAsB,CAC3C,EAAE,EAAE,MAAM,EACV,GAAG,SAAa,GACd,OAAO,CAAC,OAAO,CAAC,CAOlB;AAED,wBAAsB,4BAA4B,CACjD,mBAAmB,EAAE,MAAM,GAAG,IAAI,EAClC,GAAG,SAAa,GACd,OAAO,CAAC,sBAAsB,GAAG,IAAI,CAAC,CAaxC;AAED,wBAAgB,uCAAuC,IAAI,IAAI,CAE9D"}
@@ -0,0 +1,200 @@
1
+ import { createHash, randomBytes, randomUUID } from "node:crypto";
2
+ import { existsSync, promises as fs } from "node:fs";
3
+ import { basename, join } from "node:path";
4
+ import { logWarn } from "./logger.js";
5
+ import { getCodexMultiAuthDir } from "./runtime-paths.js";
6
+ import { isRecord, sleep } from "./utils.js";
7
+ const TOKEN_FILE_NAME = "local-client-tokens.json";
8
+ const TOKEN_PREFIX = "cma_local";
9
+ const RETRYABLE_FS_CODES = new Set(["EBUSY", "EPERM"]);
10
+ let writeQueue = Promise.resolve();
11
+ function isRetryableFsError(error) {
12
+ const code = error?.code;
13
+ return typeof code === "string" && RETRYABLE_FS_CODES.has(code);
14
+ }
15
+ function normalizeLabel(value) {
16
+ const trimmed = value?.trim();
17
+ return trimmed && trimmed.length > 0 ? trimmed.slice(0, 80) : "local-client";
18
+ }
19
+ function hashToken(token) {
20
+ return `sha256:${createHash("sha256").update(token).digest("hex")}`;
21
+ }
22
+ function createPlainToken() {
23
+ return `${TOKEN_PREFIX}_${randomBytes(32).toString("base64url")}`;
24
+ }
25
+ function tokenPrefix(token) {
26
+ return token.slice(0, 18);
27
+ }
28
+ function emptyStore() {
29
+ return { version: 1, tokens: [] };
30
+ }
31
+ function normalizeRecord(value) {
32
+ if (!isRecord(value))
33
+ return null;
34
+ if (typeof value.id !== "string" || value.id.trim().length === 0)
35
+ return null;
36
+ if (typeof value.tokenHash !== "string" ||
37
+ !value.tokenHash.startsWith("sha256:")) {
38
+ return null;
39
+ }
40
+ return {
41
+ id: value.id.trim(),
42
+ label: normalizeLabel(typeof value.label === "string" ? value.label : undefined),
43
+ prefix: typeof value.prefix === "string" ? value.prefix.slice(0, 32) : "",
44
+ tokenHash: value.tokenHash,
45
+ createdAt: typeof value.createdAt === "number" && Number.isFinite(value.createdAt)
46
+ ? value.createdAt
47
+ : 0,
48
+ lastUsedAt: typeof value.lastUsedAt === "number" && Number.isFinite(value.lastUsedAt)
49
+ ? value.lastUsedAt
50
+ : null,
51
+ revokedAt: typeof value.revokedAt === "number" && Number.isFinite(value.revokedAt)
52
+ ? value.revokedAt
53
+ : null,
54
+ };
55
+ }
56
+ function normalizeStore(value) {
57
+ if (!isRecord(value) || value.version !== 1 || !Array.isArray(value.tokens)) {
58
+ return emptyStore();
59
+ }
60
+ return {
61
+ version: 1,
62
+ tokens: value.tokens
63
+ .map((entry) => normalizeRecord(entry))
64
+ .filter((entry) => entry !== null),
65
+ };
66
+ }
67
+ async function readFileWithRetry(path) {
68
+ let lastError;
69
+ for (let attempt = 0; attempt < 5; attempt += 1) {
70
+ try {
71
+ return await fs.readFile(path, "utf8");
72
+ }
73
+ catch (error) {
74
+ lastError = error;
75
+ if (!isRetryableFsError(error) || attempt >= 4)
76
+ throw error;
77
+ await sleep(10 * 2 ** attempt);
78
+ }
79
+ }
80
+ throw lastError instanceof Error
81
+ ? lastError
82
+ : new Error("local client token read retry exhausted");
83
+ }
84
+ export function getLocalClientTokenPath() {
85
+ return join(getCodexMultiAuthDir(), TOKEN_FILE_NAME);
86
+ }
87
+ export async function loadLocalClientTokenStore() {
88
+ const path = getLocalClientTokenPath();
89
+ if (!existsSync(path))
90
+ return emptyStore();
91
+ try {
92
+ return normalizeStore(JSON.parse(await readFileWithRetry(path)));
93
+ }
94
+ catch (error) {
95
+ logWarn(`Failed to load local client tokens from ${basename(path)}: ${error instanceof Error ? error.message : String(error)}`);
96
+ return emptyStore();
97
+ }
98
+ }
99
+ export async function saveLocalClientTokenStore(store) {
100
+ const path = getLocalClientTokenPath();
101
+ const payload = normalizeStore(store);
102
+ const task = async () => {
103
+ await fs.mkdir(getCodexMultiAuthDir(), { recursive: true, mode: 0o700 });
104
+ const tempPath = `${path}.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2, 8)}.tmp`;
105
+ let moved = false;
106
+ try {
107
+ await fs.writeFile(tempPath, `${JSON.stringify(payload, null, 2)}\n`, {
108
+ encoding: "utf8",
109
+ mode: 0o600,
110
+ });
111
+ for (let attempt = 0; attempt < 5; attempt += 1) {
112
+ try {
113
+ await fs.rename(tempPath, path);
114
+ moved = true;
115
+ return;
116
+ }
117
+ catch (error) {
118
+ if (!isRetryableFsError(error) || attempt >= 4)
119
+ throw error;
120
+ await sleep(10 * 2 ** attempt);
121
+ }
122
+ }
123
+ }
124
+ finally {
125
+ if (!moved) {
126
+ try {
127
+ await fs.unlink(tempPath);
128
+ }
129
+ catch {
130
+ // Best-effort temp cleanup.
131
+ }
132
+ }
133
+ }
134
+ };
135
+ const queued = writeQueue.catch(() => undefined).then(task);
136
+ writeQueue = queued.then(() => undefined, () => undefined);
137
+ await queued;
138
+ }
139
+ export function createLocalClientTokenRecord(input = {}) {
140
+ const plainToken = createPlainToken();
141
+ const record = {
142
+ id: randomUUID(),
143
+ label: normalizeLabel(input.label),
144
+ prefix: tokenPrefix(plainToken),
145
+ tokenHash: hashToken(plainToken),
146
+ createdAt: input.now ?? Date.now(),
147
+ lastUsedAt: null,
148
+ revokedAt: null,
149
+ };
150
+ return { plainToken, record };
151
+ }
152
+ export async function addLocalClientToken(input = {}) {
153
+ const store = await loadLocalClientTokenStore();
154
+ const created = createLocalClientTokenRecord(input);
155
+ store.tokens.push(created.record);
156
+ await saveLocalClientTokenStore(store);
157
+ return created;
158
+ }
159
+ export async function rotateLocalClientToken(input) {
160
+ const store = await loadLocalClientTokenStore();
161
+ const existing = store.tokens.find((record) => record.id === input.id);
162
+ if (!existing || existing.revokedAt !== null)
163
+ return null;
164
+ const now = input.now ?? Date.now();
165
+ existing.revokedAt = now;
166
+ const created = createLocalClientTokenRecord({
167
+ label: input.label ?? existing.label,
168
+ now,
169
+ });
170
+ store.tokens.push(created.record);
171
+ await saveLocalClientTokenStore(store);
172
+ return created;
173
+ }
174
+ export async function revokeLocalClientToken(id, now = Date.now()) {
175
+ const store = await loadLocalClientTokenStore();
176
+ const existing = store.tokens.find((record) => record.id === id);
177
+ if (!existing || existing.revokedAt !== null)
178
+ return false;
179
+ existing.revokedAt = now;
180
+ await saveLocalClientTokenStore(store);
181
+ return true;
182
+ }
183
+ export async function verifyLocalClientBearerToken(authorizationHeader, now = Date.now()) {
184
+ const match = authorizationHeader?.match(/^Bearer\s+(.+)$/i);
185
+ const token = match?.[1]?.trim();
186
+ if (!token)
187
+ return null;
188
+ const tokenHash = hashToken(token);
189
+ const store = await loadLocalClientTokenStore();
190
+ const record = store.tokens.find((entry) => entry.revokedAt === null && entry.tokenHash === tokenHash);
191
+ if (!record)
192
+ return null;
193
+ record.lastUsedAt = now;
194
+ await saveLocalClientTokenStore(store);
195
+ return record;
196
+ }
197
+ export function resetLocalClientTokenWriteQueueForTests() {
198
+ writeQueue = Promise.resolve();
199
+ }
200
+ //# sourceMappingURL=local-client-tokens.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-client-tokens.js","sourceRoot":"","sources":["../../lib/local-client-tokens.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,EAAE,UAAU,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACtC,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAsB7C,MAAM,eAAe,GAAG,0BAA0B,CAAC;AACnD,MAAM,YAAY,GAAG,WAAW,CAAC;AACjC,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;AACvD,IAAI,UAAU,GAAkB,OAAO,CAAC,OAAO,EAAE,CAAC;AAElD,SAAS,kBAAkB,CAAC,KAAc;IACzC,MAAM,IAAI,GAAI,KAA2C,EAAE,IAAI,CAAC;IAChE,OAAO,OAAO,IAAI,KAAK,QAAQ,IAAI,kBAAkB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACjE,CAAC;AAED,SAAS,cAAc,CAAC,KAAyB;IAChD,MAAM,OAAO,GAAG,KAAK,EAAE,IAAI,EAAE,CAAC;IAC9B,OAAO,OAAO,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC;AAC9E,CAAC;AAED,SAAS,SAAS,CAAC,KAAa;IAC/B,OAAO,UAAU,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;AACrE,CAAC;AAED,SAAS,gBAAgB;IACxB,OAAO,GAAG,YAAY,IAAI,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;AACnE,CAAC;AAED,SAAS,WAAW,CAAC,KAAa;IACjC,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAC3B,CAAC;AAED,SAAS,UAAU;IAClB,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;AACnC,CAAC;AAED,SAAS,eAAe,CAAC,KAAc;IACtC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAClC,IAAI,OAAO,KAAK,CAAC,EAAE,KAAK,QAAQ,IAAI,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAC9E,IACC,OAAO,KAAK,CAAC,SAAS,KAAK,QAAQ;QACnC,CAAC,KAAK,CAAC,SAAS,CAAC,UAAU,CAAC,SAAS,CAAC,EACrC,CAAC;QACF,OAAO,IAAI,CAAC;IACb,CAAC;IACD,OAAO;QACN,EAAE,EAAE,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE;QACnB,KAAK,EAAE,cAAc,CAAC,OAAO,KAAK,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;QAChF,MAAM,EAAE,OAAO,KAAK,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE;QACzE,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,SAAS,EACR,OAAO,KAAK,CAAC,SAAS,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC;YACtE,CAAC,CAAC,KAAK,CAAC,SAAS;YACjB,CAAC,CAAC,CAAC;QACL,UAAU,EACT,OAAO,KAAK,CAAC,UAAU,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,UAAU,CAAC;YACxE,CAAC,CAAC,KAAK,CAAC,UAAU;YAClB,CAAC,CAAC,IAAI;QACR,SAAS,EACR,OAAO,KAAK,CAAC,SAAS,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC;YACtE,CAAC,CAAC,KAAK,CAAC,SAAS;YACjB,CAAC,CAAC,IAAI;KACR,CAAC;AACH,CAAC;AAED,SAAS,cAAc,CAAC,KAAc;IACrC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;QAC7E,OAAO,UAAU,EAAE,CAAC;IACrB,CAAC;IACD,OAAO;QACN,OAAO,EAAE,CAAC;QACV,MAAM,EAAE,KAAK,CAAC,MAAM;aAClB,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;aACtC,MAAM,CAAC,CAAC,KAAK,EAAmC,EAAE,CAAC,KAAK,KAAK,IAAI,CAAC;KACpE,CAAC;AACH,CAAC;AAED,KAAK,UAAU,iBAAiB,CAAC,IAAY;IAC5C,IAAI,SAAkB,CAAC;IACvB,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,CAAC,EAAE,CAAC;QACjD,IAAI,CAAC;YACJ,OAAO,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACxC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,SAAS,GAAG,KAAK,CAAC;YAClB,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC,IAAI,OAAO,IAAI,CAAC;gBAAE,MAAM,KAAK,CAAC;YAC5D,MAAM,KAAK,CAAC,EAAE,GAAG,CAAC,IAAI,OAAO,CAAC,CAAC;QAChC,CAAC;IACF,CAAC;IACD,MAAM,SAAS,YAAY,KAAK;QAC/B,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;AACzD,CAAC;AAED,MAAM,UAAU,uBAAuB;IACtC,OAAO,IAAI,CAAC,oBAAoB,EAAE,EAAE,eAAe,CAAC,CAAC;AACtD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,yBAAyB;IAC9C,MAAM,IAAI,GAAG,uBAAuB,EAAE,CAAC;IACvC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,UAAU,EAAE,CAAC;IAC3C,IAAI,CAAC;QACJ,OAAO,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,iBAAiB,CAAC,IAAI,CAAC,CAAY,CAAC,CAAC;IAC7E,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,OAAO,CACN,2CAA2C,QAAQ,CAAC,IAAI,CAAC,KACxD,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CACtD,EAAE,CACF,CAAC;QACF,OAAO,UAAU,EAAE,CAAC;IACrB,CAAC;AACF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAC9C,KAA4B;IAE5B,MAAM,IAAI,GAAG,uBAAuB,EAAE,CAAC;IACvC,MAAM,OAAO,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;IACtC,MAAM,IAAI,GAAG,KAAK,IAAmB,EAAE;QACtC,MAAM,EAAE,CAAC,KAAK,CAAC,oBAAoB,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QACzE,MAAM,QAAQ,GAAG,GAAG,IAAI,IAAI,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC;QACtG,IAAI,KAAK,GAAG,KAAK,CAAC;QAClB,IAAI,CAAC;YACJ,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE;gBACrE,QAAQ,EAAE,MAAM;gBAChB,IAAI,EAAE,KAAK;aACX,CAAC,CAAC;YACH,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,CAAC,EAAE,CAAC;gBACjD,IAAI,CAAC;oBACJ,MAAM,EAAE,CAAC,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;oBAChC,KAAK,GAAG,IAAI,CAAC;oBACb,OAAO;gBACR,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBAChB,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC,IAAI,OAAO,IAAI,CAAC;wBAAE,MAAM,KAAK,CAAC;oBAC5D,MAAM,KAAK,CAAC,EAAE,GAAG,CAAC,IAAI,OAAO,CAAC,CAAC;gBAChC,CAAC;YACF,CAAC;QACF,CAAC;gBAAS,CAAC;YACV,IAAI,CAAC,KAAK,EAAE,CAAC;gBACZ,IAAI,CAAC;oBACJ,MAAM,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;gBAC3B,CAAC;gBAAC,MAAM,CAAC;oBACR,4BAA4B;gBAC7B,CAAC;YACF,CAAC;QACF,CAAC;IACF,CAAC,CAAC;IACF,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC5D,UAAU,GAAG,MAAM,CAAC,IAAI,CACvB,GAAG,EAAE,CAAC,SAAS,EACf,GAAG,EAAE,CAAC,SAAS,CACf,CAAC;IACF,MAAM,MAAM,CAAC;AACd,CAAC;AAED,MAAM,UAAU,4BAA4B,CAAC,QAGzC,EAAE;IACL,MAAM,UAAU,GAAG,gBAAgB,EAAE,CAAC;IACtC,MAAM,MAAM,GAA2B;QACtC,EAAE,EAAE,UAAU,EAAE;QAChB,KAAK,EAAE,cAAc,CAAC,KAAK,CAAC,KAAK,CAAC;QAClC,MAAM,EAAE,WAAW,CAAC,UAAU,CAAC;QAC/B,SAAS,EAAE,SAAS,CAAC,UAAU,CAAC;QAChC,SAAS,EAAE,KAAK,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE;QAClC,UAAU,EAAE,IAAI;QAChB,SAAS,EAAE,IAAI;KACf,CAAC;IACF,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC;AAC/B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,QAGtC,EAAE;IACL,MAAM,KAAK,GAAG,MAAM,yBAAyB,EAAE,CAAC;IAChD,MAAM,OAAO,GAAG,4BAA4B,CAAC,KAAK,CAAC,CAAC;IACpD,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAClC,MAAM,yBAAyB,CAAC,KAAK,CAAC,CAAC;IACvC,OAAO,OAAO,CAAC;AAChB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,KAI5C;IACA,MAAM,KAAK,GAAG,MAAM,yBAAyB,EAAE,CAAC;IAChD,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,KAAK,KAAK,CAAC,EAAE,CAAC,CAAC;IACvE,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,SAAS,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAC1D,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;IACpC,QAAQ,CAAC,SAAS,GAAG,GAAG,CAAC;IACzB,MAAM,OAAO,GAAG,4BAA4B,CAAC;QAC5C,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,QAAQ,CAAC,KAAK;QACpC,GAAG;KACH,CAAC,CAAC;IACH,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAClC,MAAM,yBAAyB,CAAC,KAAK,CAAC,CAAC;IACvC,OAAO,OAAO,CAAC;AAChB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC3C,EAAU,EACV,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE;IAEhB,MAAM,KAAK,GAAG,MAAM,yBAAyB,EAAE,CAAC;IAChD,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IACjE,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,SAAS,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAC3D,QAAQ,CAAC,SAAS,GAAG,GAAG,CAAC;IACzB,MAAM,yBAAyB,CAAC,KAAK,CAAC,CAAC;IACvC,OAAO,IAAI,CAAC;AACb,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,4BAA4B,CACjD,mBAAkC,EAClC,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE;IAEhB,MAAM,KAAK,GAAG,mBAAmB,EAAE,KAAK,CAAC,kBAAkB,CAAC,CAAC;IAC7D,MAAM,KAAK,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;IACjC,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,MAAM,SAAS,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;IACnC,MAAM,KAAK,GAAG,MAAM,yBAAyB,EAAE,CAAC;IAChD,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAC/B,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,SAAS,KAAK,IAAI,IAAI,KAAK,CAAC,SAAS,KAAK,SAAS,CACpE,CAAC;IACF,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IACzB,MAAM,CAAC,UAAU,GAAG,GAAG,CAAC;IACxB,MAAM,yBAAyB,CAAC,KAAK,CAAC,CAAC;IACvC,OAAO,MAAM,CAAC;AACf,CAAC;AAED,MAAM,UAAU,uCAAuC;IACtD,UAAU,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;AAChC,CAAC"}
@@ -0,0 +1,38 @@
1
+ import type { AccountStorageV3 } from "./storage.js";
2
+ import { type ModelCapabilities, type ModelReasoningEffort, type PromptModelFamily } from "./request/helpers/model-map.js";
3
+ import { type EntitlementCacheSnapshot } from "./entitlement-cache.js";
4
+ import type { CapabilityPolicySnapshot, CapabilityPolicyStore } from "./capability-policy.js";
5
+ import type { QuotaCacheData, QuotaCacheEntry } from "./quota-cache.js";
6
+ export interface ModelCapabilityMatrixEntry {
7
+ accountIndex: number;
8
+ accountLabel: string;
9
+ accountKey: string;
10
+ model: string;
11
+ normalizedModel: string;
12
+ promptFamily: PromptModelFamily;
13
+ defaultReasoningEffort: ModelReasoningEffort;
14
+ supportedReasoningEfforts: readonly ModelReasoningEffort[];
15
+ capabilities: ModelCapabilities;
16
+ entitlementBlocked: boolean;
17
+ entitlementReason: string | null;
18
+ entitlementWaitMs: number;
19
+ capabilityPolicy: CapabilityPolicySnapshot | null;
20
+ capabilityBoost: number;
21
+ quota: QuotaCacheEntry | null;
22
+ available: boolean;
23
+ reasons: string[];
24
+ }
25
+ export interface ModelCapabilityMatrix {
26
+ generatedAt: number;
27
+ models: string[];
28
+ entries: ModelCapabilityMatrixEntry[];
29
+ }
30
+ export declare function buildModelCapabilityMatrix(input: {
31
+ storage: AccountStorageV3 | null;
32
+ models?: string[];
33
+ entitlements?: EntitlementCacheSnapshot | null;
34
+ capabilityPolicy?: CapabilityPolicyStore | null;
35
+ quotaCache?: QuotaCacheData | null;
36
+ now?: number;
37
+ }): ModelCapabilityMatrix;
38
+ //# sourceMappingURL=model-capability-matrix.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-capability-matrix.d.ts","sourceRoot":"","sources":["../../lib/model-capability-matrix.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAGN,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EACzB,KAAK,iBAAiB,EACtB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAEN,KAAK,wBAAwB,EAC7B,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EACX,wBAAwB,EACxB,qBAAqB,EACrB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAGxE,MAAM,WAAW,0BAA0B;IAC1C,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,iBAAiB,CAAC;IAChC,sBAAsB,EAAE,oBAAoB,CAAC;IAC7C,yBAAyB,EAAE,SAAS,oBAAoB,EAAE,CAAC;IAC3D,YAAY,EAAE,iBAAiB,CAAC;IAChC,kBAAkB,EAAE,OAAO,CAAC;IAC5B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gBAAgB,EAAE,wBAAwB,GAAG,IAAI,CAAC;IAClD,eAAe,EAAE,MAAM,CAAC;IACxB,KAAK,EAAE,eAAe,GAAG,IAAI,CAAC;IAC9B,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,qBAAqB;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,OAAO,EAAE,0BAA0B,EAAE,CAAC;CACtC;AAsBD,wBAAgB,0BAA0B,CAAC,KAAK,EAAE;IACjD,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACjC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,YAAY,CAAC,EAAE,wBAAwB,GAAG,IAAI,CAAC;IAC/C,gBAAgB,CAAC,EAAE,qBAAqB,GAAG,IAAI,CAAC;IAChD,UAAU,CAAC,EAAE,cAAc,GAAG,IAAI,CAAC;IACnC,GAAG,CAAC,EAAE,MAAM,CAAC;CACb,GAAG,qBAAqB,CA8ExB"}
@@ -0,0 +1,89 @@
1
+ import { getAccountPolicyKey } from "./account-policy.js";
2
+ import { MODEL_PROFILES, resolveNormalizedModel, } from "./request/helpers/model-map.js";
3
+ import { resolveEntitlementAccountKey, } from "./entitlement-cache.js";
4
+ import { findQuotaCacheEntryForAccount } from "./quota-readiness.js";
5
+ function getEntitlementBlock(snapshot, accountKeys, normalizedModel, now) {
6
+ if (!snapshot)
7
+ return { blocked: false, waitMs: 0, reason: null };
8
+ for (const accountKey of accountKeys) {
9
+ const blocks = snapshot.accounts[accountKey] ?? [];
10
+ const block = blocks.find((entry) => entry.model === normalizedModel);
11
+ if (!block || block.blockedUntil <= now)
12
+ continue;
13
+ return {
14
+ blocked: true,
15
+ waitMs: Math.max(0, block.blockedUntil - now),
16
+ reason: block.reason,
17
+ };
18
+ }
19
+ return { blocked: false, waitMs: 0, reason: null };
20
+ }
21
+ export function buildModelCapabilityMatrix(input) {
22
+ const now = input.now ?? Date.now();
23
+ const models = (input.models?.length ? input.models : Object.keys(MODEL_PROFILES))
24
+ .map((model) => resolveNormalizedModel(model))
25
+ .filter((model, index, all) => all.indexOf(model) === index)
26
+ .sort();
27
+ const accounts = input.storage?.accounts ?? [];
28
+ const entries = [];
29
+ for (const [index, account] of accounts.entries()) {
30
+ const accountKey = getAccountPolicyKey(account, index);
31
+ const entitlementKeys = [
32
+ accountKey,
33
+ resolveEntitlementAccountKey({
34
+ accountId: account.accountId,
35
+ email: account.email,
36
+ index,
37
+ }),
38
+ ];
39
+ for (const model of models) {
40
+ const profile = MODEL_PROFILES[model] ?? MODEL_PROFILES[resolveNormalizedModel(model)];
41
+ if (!profile)
42
+ continue;
43
+ const entitlement = getEntitlementBlock(input.entitlements, entitlementKeys, profile.normalizedModel, now);
44
+ const capabilityPolicy = input.capabilityPolicy?.getSnapshot(accountKey, profile.normalizedModel) ??
45
+ null;
46
+ const capabilityBoost = input.capabilityPolicy?.getBoost(accountKey, profile.normalizedModel, now) ??
47
+ 0;
48
+ const quota = input.quotaCache && input.storage
49
+ ? findQuotaCacheEntryForAccount(input.quotaCache, account, input.storage.accounts)
50
+ : null;
51
+ const reasons = [];
52
+ if (account.enabled === false)
53
+ reasons.push("account disabled");
54
+ if (entitlement.blocked) {
55
+ reasons.push(`entitlement blocked: ${entitlement.reason ?? "unknown"}`);
56
+ }
57
+ if (capabilityPolicy && capabilityPolicy.unsupported > 0) {
58
+ reasons.push("capability policy has unsupported failures");
59
+ }
60
+ if (quota?.status === 429)
61
+ reasons.push("quota cache is rate-limited");
62
+ entries.push({
63
+ accountIndex: index + 1,
64
+ accountLabel: `Account ${index + 1}`,
65
+ accountKey,
66
+ model,
67
+ normalizedModel: profile.normalizedModel,
68
+ promptFamily: profile.promptFamily,
69
+ defaultReasoningEffort: profile.defaultReasoningEffort,
70
+ supportedReasoningEfforts: profile.supportedReasoningEfforts,
71
+ capabilities: profile.capabilities,
72
+ entitlementBlocked: entitlement.blocked,
73
+ entitlementReason: entitlement.reason,
74
+ entitlementWaitMs: entitlement.waitMs,
75
+ capabilityPolicy,
76
+ capabilityBoost,
77
+ quota,
78
+ available: reasons.length === 0,
79
+ reasons,
80
+ });
81
+ }
82
+ }
83
+ return {
84
+ generatedAt: now,
85
+ models,
86
+ entries,
87
+ };
88
+ }
89
+ //# sourceMappingURL=model-capability-matrix.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-capability-matrix.js","sourceRoot":"","sources":["../../lib/model-capability-matrix.ts"],"names":[],"mappings":"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"}