@rynfar/meridian 1.71.1 → 1.73.0
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 +115 -162
- package/assets/desktop-dashboard.jpg +0 -0
- package/assets/trayTemplate.png +0 -0
- package/assets/trayTemplate@2x.png +0 -0
- package/assets/trayTemplate@3x.png +0 -0
- package/dist/cli-1jstkdj9.js +30 -0
- package/dist/{cli-9e5cxp89.js → cli-2h3w5n6g.js} +163 -65
- package/dist/cli-3zwfvexc.js +56 -0
- package/dist/{cli-hxxy0m1z.js → cli-82e2m44k.js} +2 -1
- package/dist/cli-8sw5wr9j.js +136 -0
- package/dist/{cli-khhjyk04.js → cli-chsp880k.js} +214 -21
- package/dist/cli-dh0a1bw4.js +619 -0
- package/dist/cli-eehk3052.js +57 -0
- package/dist/cli-grfp0s1j.js +330 -0
- package/dist/{cli-ryt69ryf.js → cli-p5zbk952.js} +2185 -358
- package/dist/{cli-8yp89fan.js → cli-p9ca4p13.js} +17 -2
- package/dist/cli-qpfky8wy.js +133 -0
- package/dist/cli.js +47 -12
- package/dist/cliDashboard-c0dvkj4y.js +325 -0
- package/dist/configDir.d.ts +30 -0
- package/dist/configDir.d.ts.map +1 -0
- package/dist/organizationName-90f0atkn.js +29 -0
- package/dist/{pluginPage-n3gdtbmj.js → pluginPage-3kxsrdpj.js} +1 -1
- package/dist/{profileCli-1eecbmgk.js → profileCli-1bfgc05h.js} +13 -3
- package/dist/{profilePage-vfj2dbhn.js → profilePage-etxqg3vn.js} +252 -60
- package/dist/profileRename-4a4km6g8.js +22 -0
- package/dist/{profiles-wch9h234.js → profiles-0mp32ek9.js} +16 -3
- package/dist/proxy/adapterInstances.d.ts +1 -1
- package/dist/proxy/adapterInstances.d.ts.map +1 -1
- package/dist/proxy/adapters/claudecode.d.ts.map +1 -1
- package/dist/proxy/adapters/droid.d.ts.map +1 -1
- package/dist/proxy/authDiscovery.d.ts +52 -0
- package/dist/proxy/authDiscovery.d.ts.map +1 -0
- package/dist/proxy/credentialsMode.d.ts +77 -0
- package/dist/proxy/credentialsMode.d.ts.map +1 -0
- package/dist/proxy/design.d.ts.map +1 -1
- package/dist/proxy/errors.d.ts.map +1 -1
- package/dist/proxy/followActive.d.ts +262 -0
- package/dist/proxy/followActive.d.ts.map +1 -0
- package/dist/proxy/limitDetection.d.ts +110 -0
- package/dist/proxy/limitDetection.d.ts.map +1 -0
- package/dist/proxy/models.d.ts.map +1 -1
- package/dist/proxy/oauthPlan.d.ts +63 -0
- package/dist/proxy/oauthPlan.d.ts.map +1 -0
- package/dist/proxy/oauthUsage.d.ts +65 -2
- package/dist/proxy/oauthUsage.d.ts.map +1 -1
- package/dist/proxy/openai.d.ts +4 -2
- package/dist/proxy/openai.d.ts.map +1 -1
- package/dist/proxy/organizationName.d.ts +71 -0
- package/dist/proxy/organizationName.d.ts.map +1 -0
- package/dist/proxy/passthroughEarlyStop.d.ts +10 -0
- package/dist/proxy/passthroughEarlyStop.d.ts.map +1 -1
- package/dist/proxy/planAllowance.d.ts +75 -0
- package/dist/proxy/planAllowance.d.ts.map +1 -0
- package/dist/proxy/probes.d.ts +85 -0
- package/dist/proxy/probes.d.ts.map +1 -0
- package/dist/proxy/profileCli.d.ts +53 -1
- package/dist/proxy/profileCli.d.ts.map +1 -1
- package/dist/proxy/profileHealth.d.ts +127 -0
- package/dist/proxy/profileHealth.d.ts.map +1 -0
- package/dist/proxy/profileRename.d.ts +83 -0
- package/dist/proxy/profileRename.d.ts.map +1 -0
- package/dist/proxy/profiles.d.ts +72 -6
- package/dist/proxy/profiles.d.ts.map +1 -1
- package/dist/proxy/query.d.ts +7 -0
- package/dist/proxy/query.d.ts.map +1 -1
- package/dist/proxy/routing.d.ts +59 -1
- package/dist/proxy/routing.d.ts.map +1 -1
- package/dist/proxy/sdkFeatures.d.ts +1 -1
- package/dist/proxy/sdkFeatures.d.ts.map +1 -1
- package/dist/proxy/server.d.ts.map +1 -1
- package/dist/proxy/session/fingerprint.d.ts +5 -0
- package/dist/proxy/session/fingerprint.d.ts.map +1 -1
- package/dist/proxy/session/lineage.d.ts.map +1 -1
- package/dist/proxy/session/processIncarnation.d.ts +7 -0
- package/dist/proxy/session/processIncarnation.d.ts.map +1 -1
- package/dist/proxy/sessionLifecycle.d.ts +8 -1
- package/dist/proxy/sessionLifecycle.d.ts.map +1 -1
- package/dist/proxy/sessionStore.d.ts.map +1 -1
- package/dist/proxy/setup.d.ts.map +1 -1
- package/dist/proxy/supervision.d.ts +41 -0
- package/dist/proxy/supervision.d.ts.map +1 -0
- package/dist/proxy/tokenRefresh.d.ts +38 -4
- package/dist/proxy/tokenRefresh.d.ts.map +1 -1
- package/dist/server.js +11 -7
- package/dist/settings.d.ts +83 -0
- package/dist/settings.d.ts.map +1 -0
- package/dist/{setup-ndmjpy23.js → setup-7fr49z92.js} +1 -1
- package/dist/statusProbe-9x9q261e.js +151 -0
- package/dist/telemetry/dashboard.d.ts.map +1 -1
- package/dist/telemetry/index.d.ts +20 -2
- package/dist/telemetry/index.d.ts.map +1 -1
- package/dist/telemetry/landing.d.ts +1 -1
- package/dist/telemetry/landing.d.ts.map +1 -1
- package/dist/telemetry/logStore.d.ts +11 -0
- package/dist/telemetry/logStore.d.ts.map +1 -1
- package/dist/telemetry/pricingStore.d.ts +2 -2
- package/dist/telemetry/pricingStore.d.ts.map +1 -1
- package/dist/telemetry/profileBar.d.ts +10 -2
- package/dist/telemetry/profileBar.d.ts.map +1 -1
- package/dist/telemetry/profileFacts.d.ts +17 -0
- package/dist/telemetry/profileFacts.d.ts.map +1 -0
- package/dist/telemetry/profileOrder.d.ts +68 -0
- package/dist/telemetry/profileOrder.d.ts.map +1 -0
- package/dist/telemetry/profilePage.d.ts.map +1 -1
- package/dist/telemetry/profileSort.d.ts +35 -0
- package/dist/telemetry/profileSort.d.ts.map +1 -0
- package/dist/telemetry/profileSpent.d.ts +68 -0
- package/dist/telemetry/profileSpent.d.ts.map +1 -0
- package/dist/telemetry/routeChain.d.ts +32 -0
- package/dist/telemetry/routeChain.d.ts.map +1 -0
- package/dist/telemetry/routes.d.ts.map +1 -1
- package/dist/telemetry/settingsPage.d.ts +1 -1
- package/dist/telemetry/settingsPage.d.ts.map +1 -1
- package/dist/telemetry/sqlite.d.ts.map +1 -1
- package/dist/telemetry/store.d.ts +6 -1
- package/dist/telemetry/store.d.ts.map +1 -1
- package/dist/telemetry/types.d.ts +132 -2
- package/dist/telemetry/types.d.ts.map +1 -1
- package/dist/{tokenRefresh-kzz08kea.js → tokenRefresh-eg9h83wd.js} +6 -1
- package/package.json +2 -1
- package/dist/cli-5jxyma6z.js +0 -277
- package/dist/cli-vj9cv18n.js +0 -38
- package/dist/proxy/settings.d.ts +0 -30
- package/dist/proxy/settings.d.ts.map +0 -1
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
import {
|
|
2
|
+
envBool,
|
|
3
|
+
init_env
|
|
4
|
+
} from "./cli-1jstkdj9.js";
|
|
5
|
+
|
|
1
6
|
// src/proxy/tokenRefresh.ts
|
|
2
7
|
import { execFile as execFileCb } from "node:child_process";
|
|
3
8
|
import { createHash } from "node:crypto";
|
|
@@ -68,6 +73,141 @@ var claudeLog = (event, extra) => {
|
|
|
68
73
|
console.debug(`[opencode-claude-code-provider] ${JSON.stringify(payload)}`);
|
|
69
74
|
};
|
|
70
75
|
|
|
76
|
+
// src/proxy/credentialsMode.ts
|
|
77
|
+
init_env();
|
|
78
|
+
function isCredentialsReadOnly() {
|
|
79
|
+
return envBool("CREDENTIALS_READONLY");
|
|
80
|
+
}
|
|
81
|
+
function refuseCredentialWrite(operation, target) {
|
|
82
|
+
console.error(`[PROXY] REFUSED credential write (${operation} → ${target}): ` + `MERIDIAN_CREDENTIALS_READONLY is set, so this instance must not modify credentials. ` + `If this is unexpected, the calling code path is missing a read-only guard.`);
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
var bannerLogged = false;
|
|
86
|
+
function logCredentialsModeBanner() {
|
|
87
|
+
if (bannerLogged || !isCredentialsReadOnly())
|
|
88
|
+
return;
|
|
89
|
+
bannerLogged = true;
|
|
90
|
+
console.warn(`[PROXY] CREDENTIALS READ-ONLY MODE (MERIDIAN_CREDENTIALS_READONLY): ` + `this instance will not refresh or write OAuth credentials. ` + `Token rotation is another instance's job; credentials are re-read from disk.`);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// src/proxy/authDiscovery.ts
|
|
94
|
+
var SAFE_AUTH_STRING_KEYS = new Set([
|
|
95
|
+
"token_type",
|
|
96
|
+
"expires_at",
|
|
97
|
+
"expires_in",
|
|
98
|
+
"refresh_token_expires_at",
|
|
99
|
+
"refresh_token_expires_in",
|
|
100
|
+
"scope",
|
|
101
|
+
"scopes",
|
|
102
|
+
"organization_type",
|
|
103
|
+
"rate_limit_tier",
|
|
104
|
+
"billing_type",
|
|
105
|
+
"subscriptionType",
|
|
106
|
+
"rateLimitTier",
|
|
107
|
+
"seat_tier",
|
|
108
|
+
"seatTier"
|
|
109
|
+
]);
|
|
110
|
+
function describeValue(key, value) {
|
|
111
|
+
if (value === null || value === undefined)
|
|
112
|
+
return value;
|
|
113
|
+
if (typeof value === "string") {
|
|
114
|
+
return SAFE_AUTH_STRING_KEYS.has(key) ? value : `[string len=${value.length}]`;
|
|
115
|
+
}
|
|
116
|
+
if (typeof value === "number" || typeof value === "boolean")
|
|
117
|
+
return value;
|
|
118
|
+
if (Array.isArray(value))
|
|
119
|
+
return value.map((item) => describeValue(key, item));
|
|
120
|
+
if (typeof value === "object") {
|
|
121
|
+
const out = {};
|
|
122
|
+
for (const [k, v] of Object.entries(value)) {
|
|
123
|
+
out[k] = describeValue(k, v);
|
|
124
|
+
}
|
|
125
|
+
return out;
|
|
126
|
+
}
|
|
127
|
+
return `[${typeof value}]`;
|
|
128
|
+
}
|
|
129
|
+
function describeAuthFields(payload) {
|
|
130
|
+
return describeValue("", payload);
|
|
131
|
+
}
|
|
132
|
+
function authFieldPaths(payload, prefix = "") {
|
|
133
|
+
if (!payload || typeof payload !== "object" || Array.isArray(payload))
|
|
134
|
+
return [];
|
|
135
|
+
const paths = [];
|
|
136
|
+
for (const [key, value] of Object.entries(payload)) {
|
|
137
|
+
const path = prefix ? `${prefix}.${key}` : key;
|
|
138
|
+
paths.push(path);
|
|
139
|
+
paths.push(...authFieldPaths(value, path));
|
|
140
|
+
}
|
|
141
|
+
return paths;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// src/proxy/oauthPlan.ts
|
|
145
|
+
var OAUTH_PROFILE_URL = "https://api.anthropic.com/api/oauth/profile";
|
|
146
|
+
function subscriptionTypeFromOrganizationType(organizationType) {
|
|
147
|
+
switch (organizationType) {
|
|
148
|
+
case "claude_max":
|
|
149
|
+
return "max";
|
|
150
|
+
case "claude_pro":
|
|
151
|
+
return "pro";
|
|
152
|
+
case "claude_team":
|
|
153
|
+
return "team";
|
|
154
|
+
case "claude_enterprise":
|
|
155
|
+
return "enterprise";
|
|
156
|
+
default:
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
function extractPlanFields(profile) {
|
|
161
|
+
const subscriptionType = subscriptionTypeFromOrganizationType(profile?.organization?.organization_type);
|
|
162
|
+
const rateLimitTier = profile?.organization?.rate_limit_tier;
|
|
163
|
+
const seatTier = profile?.organization?.seat_tier;
|
|
164
|
+
return {
|
|
165
|
+
...subscriptionType ? { subscriptionType } : {},
|
|
166
|
+
...rateLimitTier ? { rateLimitTier } : {},
|
|
167
|
+
...seatTier ? { seatTier } : {}
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
function planFieldsMissing(fields) {
|
|
171
|
+
return !fields?.subscriptionType || !fields?.rateLimitTier && !fields?.seatTier;
|
|
172
|
+
}
|
|
173
|
+
async function fetchOAuthPlanFields(accessToken) {
|
|
174
|
+
let response;
|
|
175
|
+
try {
|
|
176
|
+
response = await fetch(OAUTH_PROFILE_URL, {
|
|
177
|
+
headers: {
|
|
178
|
+
Authorization: `Bearer ${accessToken}`,
|
|
179
|
+
"Content-Type": "application/json",
|
|
180
|
+
"Cache-Control": "no-cache"
|
|
181
|
+
},
|
|
182
|
+
signal: AbortSignal.timeout(1e4)
|
|
183
|
+
});
|
|
184
|
+
} catch (err) {
|
|
185
|
+
claudeLog("auth.profile_request_failed", { error: String(err) });
|
|
186
|
+
console.warn(`[meridian] Could not read the account plan: ${err instanceof Error ? err.message : err}`);
|
|
187
|
+
return {};
|
|
188
|
+
}
|
|
189
|
+
if (!response.ok) {
|
|
190
|
+
claudeLog("auth.profile_bad_response", { status: response.status });
|
|
191
|
+
console.warn(`[meridian] Could not read the account plan (${response.status}).`);
|
|
192
|
+
return {};
|
|
193
|
+
}
|
|
194
|
+
let profile;
|
|
195
|
+
try {
|
|
196
|
+
profile = await response.json();
|
|
197
|
+
} catch (err) {
|
|
198
|
+
claudeLog("auth.profile_parse_failed", { error: String(err) });
|
|
199
|
+
console.warn(`[meridian] Account plan response was not valid JSON: ${err instanceof Error ? err.message : err}`);
|
|
200
|
+
return {};
|
|
201
|
+
}
|
|
202
|
+
const plan = extractPlanFields(profile);
|
|
203
|
+
claudeLog("auth.profile_discovered", {
|
|
204
|
+
fields: authFieldPaths(profile),
|
|
205
|
+
payload: describeAuthFields(profile),
|
|
206
|
+
plan
|
|
207
|
+
});
|
|
208
|
+
return plan;
|
|
209
|
+
}
|
|
210
|
+
|
|
71
211
|
// src/proxy/tokenRefresh.ts
|
|
72
212
|
var execFile = promisify(execFileCb);
|
|
73
213
|
var OAUTH_TOKEN_URL = "https://platform.claude.com/v1/oauth/token";
|
|
@@ -85,6 +225,17 @@ function configDirToKeychainService(claudeConfigDir) {
|
|
|
85
225
|
function configDirToCredentialsFile(claudeConfigDir) {
|
|
86
226
|
return join(resolve(claudeConfigDir), ".credentials.json");
|
|
87
227
|
}
|
|
228
|
+
function guardCredentialWrites(store) {
|
|
229
|
+
return {
|
|
230
|
+
...store,
|
|
231
|
+
async write(credentials) {
|
|
232
|
+
if (isCredentialsReadOnly()) {
|
|
233
|
+
return refuseCredentialWrite("credential-store", store.refreshKey ?? "unknown-store");
|
|
234
|
+
}
|
|
235
|
+
return store.write(credentials);
|
|
236
|
+
}
|
|
237
|
+
};
|
|
238
|
+
}
|
|
88
239
|
function serializeCredentials(credentials) {
|
|
89
240
|
return JSON.stringify(credentials);
|
|
90
241
|
}
|
|
@@ -101,7 +252,7 @@ function parseKeychainValue(raw) {
|
|
|
101
252
|
}
|
|
102
253
|
var keychainWasHexByService = new Map;
|
|
103
254
|
function buildMacosStore(serviceName) {
|
|
104
|
-
return {
|
|
255
|
+
return guardCredentialWrites({
|
|
105
256
|
refreshKey: `keychain:${serviceName}`,
|
|
106
257
|
async read() {
|
|
107
258
|
try {
|
|
@@ -128,12 +279,12 @@ function buildMacosStore(serviceName) {
|
|
|
128
279
|
return false;
|
|
129
280
|
}
|
|
130
281
|
}
|
|
131
|
-
};
|
|
282
|
+
});
|
|
132
283
|
}
|
|
133
284
|
var macosStore = buildMacosStore(KEYCHAIN_SERVICE);
|
|
134
285
|
function buildFileStore(filePath) {
|
|
135
286
|
const absPath = resolve(filePath);
|
|
136
|
-
return {
|
|
287
|
+
return guardCredentialWrites({
|
|
137
288
|
refreshKey: `file:${absPath}`,
|
|
138
289
|
async read() {
|
|
139
290
|
try {
|
|
@@ -155,7 +306,7 @@ function buildFileStore(filePath) {
|
|
|
155
306
|
return false;
|
|
156
307
|
}
|
|
157
308
|
}
|
|
158
|
-
};
|
|
309
|
+
});
|
|
159
310
|
}
|
|
160
311
|
var fileStore = buildFileStore(CREDENTIALS_FILE);
|
|
161
312
|
function createPlatformCredentialStore(opts) {
|
|
@@ -170,10 +321,25 @@ function createPlatformCredentialStore(opts) {
|
|
|
170
321
|
function credentialsFilePathForProfile(claudeConfigDir) {
|
|
171
322
|
return claudeConfigDir ? configDirToCredentialsFile(claudeConfigDir) : CREDENTIALS_FILE;
|
|
172
323
|
}
|
|
324
|
+
async function readStoredCredentialPresence(store) {
|
|
325
|
+
let credentials;
|
|
326
|
+
try {
|
|
327
|
+
credentials = await store.read();
|
|
328
|
+
} catch {
|
|
329
|
+
return "unknown";
|
|
330
|
+
}
|
|
331
|
+
if (!credentials)
|
|
332
|
+
return "unknown";
|
|
333
|
+
const accessToken = credentials.claudeAiOauth?.accessToken;
|
|
334
|
+
return typeof accessToken === "string" && accessToken.length > 0 ? "present" : "absent";
|
|
335
|
+
}
|
|
173
336
|
var inflightRefreshByKey = new Map;
|
|
174
337
|
var inflightRefreshByStore = new WeakMap;
|
|
175
338
|
async function refreshOAuthToken(store) {
|
|
176
339
|
const s = store ?? createPlatformCredentialStore();
|
|
340
|
+
if (isCredentialsReadOnly()) {
|
|
341
|
+
return refuseCredentialWrite("oauth-refresh", s.refreshKey ?? "unknown-store");
|
|
342
|
+
}
|
|
177
343
|
const refreshKey = s.refreshKey;
|
|
178
344
|
if (refreshKey) {
|
|
179
345
|
const inflight2 = inflightRefreshByKey.get(refreshKey);
|
|
@@ -244,10 +410,18 @@ async function doRefresh(store) {
|
|
|
244
410
|
expiresAt,
|
|
245
411
|
...refreshTokenExpiresAt ? { refreshTokenExpiresAt } : {}
|
|
246
412
|
};
|
|
413
|
+
const backfilled = planFieldsMissing(credentials.claudeAiOauth) ? await fetchOAuthPlanFields(tokenData.access_token) : {};
|
|
414
|
+
if (backfilled.subscriptionType || backfilled.rateLimitTier) {
|
|
415
|
+
credentials.claudeAiOauth = { ...backfilled, ...credentials.claudeAiOauth };
|
|
416
|
+
}
|
|
247
417
|
const written = await store.write(credentials);
|
|
248
418
|
if (!written)
|
|
249
419
|
return false;
|
|
250
|
-
claudeLog("token_refresh.success", {
|
|
420
|
+
claudeLog("token_refresh.success", {
|
|
421
|
+
expiresAt,
|
|
422
|
+
refreshTokenExpiresAt,
|
|
423
|
+
backfilledPlan: Object.keys(backfilled)
|
|
424
|
+
});
|
|
251
425
|
return true;
|
|
252
426
|
}
|
|
253
427
|
async function ensureFreshToken(store, bufferMs = 5 * 60 * 1000) {
|
|
@@ -258,6 +432,8 @@ async function ensureFreshToken(store, bufferMs = 5 * 60 * 1000) {
|
|
|
258
432
|
return false;
|
|
259
433
|
if (expiresAt - Date.now() > bufferMs)
|
|
260
434
|
return true;
|
|
435
|
+
if (isCredentialsReadOnly())
|
|
436
|
+
return false;
|
|
261
437
|
return refreshOAuthToken(s);
|
|
262
438
|
}
|
|
263
439
|
var DEFAULT_RENEWAL_WARN_DAYS = 3;
|
|
@@ -265,20 +441,20 @@ function resolveRenewalWarnDays(raw) {
|
|
|
265
441
|
const parsed = raw ? Number(raw) : NaN;
|
|
266
442
|
return Number.isFinite(parsed) && parsed >= 0 ? parsed : DEFAULT_RENEWAL_WARN_DAYS;
|
|
267
443
|
}
|
|
268
|
-
var
|
|
269
|
-
var
|
|
270
|
-
var
|
|
444
|
+
var CREDENTIAL_FACTS_TTL_MS = 5 * 60000;
|
|
445
|
+
var credentialFactsCache = new Map;
|
|
446
|
+
var credentialFactsInflight = new Map;
|
|
271
447
|
function resetAuthRenewalCache() {
|
|
272
|
-
|
|
273
|
-
|
|
448
|
+
credentialFactsCache.clear();
|
|
449
|
+
credentialFactsInflight.clear();
|
|
274
450
|
}
|
|
275
|
-
async function
|
|
451
|
+
async function readCredentialFacts(s) {
|
|
276
452
|
const key = s.refreshKey;
|
|
277
453
|
if (key) {
|
|
278
|
-
const cached =
|
|
279
|
-
if (cached && Date.now() - cached.at <
|
|
454
|
+
const cached = credentialFactsCache.get(key);
|
|
455
|
+
if (cached && Date.now() - cached.at < CREDENTIAL_FACTS_TTL_MS)
|
|
280
456
|
return cached.value;
|
|
281
|
-
const inflight =
|
|
457
|
+
const inflight = credentialFactsInflight.get(key);
|
|
282
458
|
if (inflight)
|
|
283
459
|
return inflight;
|
|
284
460
|
}
|
|
@@ -287,25 +463,40 @@ async function readRefreshTokenExpiry(s) {
|
|
|
287
463
|
try {
|
|
288
464
|
credentials = await s.read();
|
|
289
465
|
} catch {
|
|
290
|
-
return;
|
|
466
|
+
return {};
|
|
291
467
|
}
|
|
292
|
-
const
|
|
468
|
+
const oauth = credentials?.claudeAiOauth;
|
|
469
|
+
const value = {
|
|
470
|
+
refreshTokenExpiresAt: oauth?.refreshTokenExpiresAt,
|
|
471
|
+
subscriptionType: oauth?.subscriptionType,
|
|
472
|
+
rateLimitTier: oauth?.rateLimitTier,
|
|
473
|
+
seatTier: oauth?.seatTier
|
|
474
|
+
};
|
|
293
475
|
if (key)
|
|
294
|
-
|
|
476
|
+
credentialFactsCache.set(key, { value, at: Date.now() });
|
|
295
477
|
return value;
|
|
296
478
|
})();
|
|
297
479
|
if (!key)
|
|
298
480
|
return read;
|
|
299
|
-
|
|
481
|
+
credentialFactsInflight.set(key, read);
|
|
300
482
|
try {
|
|
301
483
|
return await read;
|
|
302
484
|
} finally {
|
|
303
|
-
|
|
485
|
+
credentialFactsInflight.delete(key);
|
|
304
486
|
}
|
|
305
487
|
}
|
|
488
|
+
async function getStoredPlanFields(store) {
|
|
489
|
+
const s = store ?? createPlatformCredentialStore();
|
|
490
|
+
const { subscriptionType, rateLimitTier, seatTier } = await readCredentialFacts(s);
|
|
491
|
+
return {
|
|
492
|
+
...subscriptionType ? { subscriptionType } : {},
|
|
493
|
+
...rateLimitTier ? { rateLimitTier } : {},
|
|
494
|
+
...seatTier ? { seatTier } : {}
|
|
495
|
+
};
|
|
496
|
+
}
|
|
306
497
|
async function getAuthRenewalStatus(store, warnDays = DEFAULT_RENEWAL_WARN_DAYS) {
|
|
307
498
|
const s = store ?? createPlatformCredentialStore();
|
|
308
|
-
const refreshTokenExpiresAt = await
|
|
499
|
+
const { refreshTokenExpiresAt } = await readCredentialFacts(s);
|
|
309
500
|
if (!refreshTokenExpiresAt)
|
|
310
501
|
return { renewalRequiredSoon: false };
|
|
311
502
|
const msRemaining = refreshTokenExpiresAt - Date.now();
|
|
@@ -320,6 +511,8 @@ var scheduledRefreshTimer = null;
|
|
|
320
511
|
var scheduledRefreshActive = false;
|
|
321
512
|
var scheduledRefreshGeneration = 0;
|
|
322
513
|
function startBackgroundRefresh(store, bufferMs = 5 * 60 * 1000, failureRetryMs = 5 * 60 * 1000) {
|
|
514
|
+
if (isCredentialsReadOnly())
|
|
515
|
+
return;
|
|
323
516
|
if (scheduledRefreshActive)
|
|
324
517
|
return;
|
|
325
518
|
scheduledRefreshActive = true;
|
|
@@ -374,4 +567,4 @@ function resetInflightRefresh() {
|
|
|
374
567
|
inflightRefreshByKey.clear();
|
|
375
568
|
}
|
|
376
569
|
|
|
377
|
-
export { withClaudeLogContext, claudeLog, configDirToKeychainService, configDirToCredentialsFile, serializeCredentials, createPlatformCredentialStore, credentialsFilePathForProfile, refreshOAuthToken, ensureFreshToken, DEFAULT_RENEWAL_WARN_DAYS, resolveRenewalWarnDays, resetAuthRenewalCache, getAuthRenewalStatus, startBackgroundRefresh, stopBackgroundRefresh, isBackgroundRefreshActive, resetInflightRefresh };
|
|
570
|
+
export { withClaudeLogContext, claudeLog, isCredentialsReadOnly, refuseCredentialWrite, logCredentialsModeBanner, describeAuthFields, authFieldPaths, fetchOAuthPlanFields, configDirToKeychainService, configDirToCredentialsFile, serializeCredentials, createPlatformCredentialStore, credentialsFilePathForProfile, readStoredCredentialPresence, refreshOAuthToken, ensureFreshToken, DEFAULT_RENEWAL_WARN_DAYS, resolveRenewalWarnDays, resetAuthRenewalCache, getStoredPlanFields, getAuthRenewalStatus, startBackgroundRefresh, stopBackgroundRefresh, isBackgroundRefreshActive, resetInflightRefresh };
|