tokentracker-cli 1.0.6 → 1.1.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.de.md +6 -5
- package/README.ja.md +6 -5
- package/README.ko.md +6 -5
- package/README.md +9 -7
- package/README.zh-CN.md +6 -5
- package/dashboard/dist/assets/{AchievementBadge-CaAqGeBX.js → AchievementBadge-CKSLpTB6.js} +1 -1
- package/dashboard/dist/assets/{AchievementsPage-BoiTFuxp.js → AchievementsPage-r42Lu6ll.js} +2 -2
- package/dashboard/dist/assets/{AchievementsSection-CYiF0QS1.js → AchievementsSection-1L_uoCV4.js} +1 -1
- package/dashboard/dist/assets/{BadgeDetailModal-BH3jTMAq.js → BadgeDetailModal-DlYT33qj.js} +1 -1
- package/dashboard/dist/assets/{BotAnimated-BCn8ladQ.js → BotAnimated-BJilDdvD.js} +1 -1
- package/dashboard/dist/assets/{Card-Cf0-OFz3.js → Card-DfMS7eJT.js} +1 -1
- package/dashboard/dist/assets/{ClawdAnimated-B32inDYq.js → ClawdAnimated-B2IKU3oX.js} +2 -2
- package/dashboard/dist/assets/{CommandPalette-BOCXhSoJ.js → CommandPalette-BQAnKMQp.js} +1 -1
- package/dashboard/dist/assets/{CommunityStatsModal-wj3ntE0k.js → CommunityStatsModal-DrYW6eRx.js} +1 -1
- package/dashboard/dist/assets/{ConfirmModal-BtXy5Tpg.js → ConfirmModal-DzIeh5dx.js} +1 -1
- package/dashboard/dist/assets/{Controls-C6R_k_Yo.js → Controls-Ce-II3Yn.js} +1 -1
- package/dashboard/dist/assets/{DashboardPage-3YAD-Ps-.js → DashboardPage-CeQYNbXo.js} +1 -1
- package/dashboard/dist/assets/{DevicePage-oQdvRuea.js → DevicePage-DmoCLkPn.js} +1 -1
- package/dashboard/dist/assets/{DialogClose-DGg7gIgR.js → DialogClose-DhDGRv1X.js} +1 -1
- package/dashboard/dist/assets/DialogDescription-1rzvf7wG.js +1 -0
- package/dashboard/dist/assets/{DialogTitle-CRJVqO3Z.js → DialogTitle-BI2-gsHD.js} +1 -1
- package/dashboard/dist/assets/{FadeIn-Bal-Jhbn.js → FadeIn-Bm7hEdb4.js} +1 -1
- package/dashboard/dist/assets/{HeaderGithubStar-CoxP2fqd.js → HeaderGithubStar-BDAWv2_t.js} +1 -1
- package/dashboard/dist/assets/{HoverTooltip-DAQKPLQl.js → HoverTooltip-Z8xawE-X.js} +1 -1
- package/dashboard/dist/assets/{IpCheckPage-JbfQR0w5.js → IpCheckPage-BjmCHK-1.js} +1 -1
- package/dashboard/dist/assets/{LandingPage-DjKmw_W1.js → LandingPage-DPfKTaC7.js} +2 -2
- package/dashboard/dist/assets/{LeaderboardAvatar-D3jdY9hy.js → LeaderboardAvatar-Cd0_hasU.js} +1 -1
- package/dashboard/dist/assets/{LeaderboardPage-fU-M_RcC.js → LeaderboardPage-FbGCyz1h.js} +2 -2
- package/dashboard/dist/assets/{LeaderboardProfileModal-Db_AD0nx.js → LeaderboardProfileModal-CzL7x0ts.js} +3 -3
- package/dashboard/dist/assets/{LeaderboardProfilePage-CQ5kXnPL.js → LeaderboardProfilePage-CRU4_vJ_.js} +1 -1
- package/dashboard/dist/assets/{LimitsPage-DSVL32bb.js → LimitsPage-C8j3oSMF.js} +1 -1
- package/dashboard/dist/assets/{LocalOnlyNotice-LgNo6vft.js → LocalOnlyNotice-DMuYjLqc.js} +1 -1
- package/dashboard/dist/assets/{LoginCard-BwEFa4pX.js → LoginCard-BTT8hq7T.js} +1 -1
- package/dashboard/dist/assets/{LoginModal-rWVKapY3.js → LoginModal-DFyh1GeQ.js} +1 -1
- package/dashboard/dist/assets/{LoginPage-DEeIX36-.js → LoginPage-Cylxxqn4.js} +1 -1
- package/dashboard/dist/assets/{PetPage-81XOQqLW.js → PetPage-CGgadvAb.js} +1 -1
- package/dashboard/dist/assets/{PopoverPopup-nU1lNHRX.js → PopoverPopup-DiBUe7yt.js} +1 -1
- package/dashboard/dist/assets/{ProviderIcon-B-OZcL4W.js → ProviderIcon-_jz2BcWs.js} +1 -1
- package/dashboard/dist/assets/{ResetPasswordPage-CV3LLQRl.js → ResetPasswordPage-Fv4MB_xt.js} +1 -1
- package/dashboard/dist/assets/{SegmentedControl-DnXK5veD.js → SegmentedControl-yi9ALUzr.js} +1 -1
- package/dashboard/dist/assets/{Select-CyV3nxTO.js → Select-CiF8kiQJ.js} +1 -1
- package/dashboard/dist/assets/{SelectItemText-B9WQ2B5j.js → SelectItemText-Dbzv_uem.js} +1 -1
- package/dashboard/dist/assets/{ServiceStatusPage-CjfvzEOn.js → ServiceStatusPage-nIhZrGkz.js} +1 -1
- package/dashboard/dist/assets/{SessionsPage-BXTr3S8x.js → SessionsPage-BSyoUCDc.js} +1 -1
- package/dashboard/dist/assets/{SettingsPage-C-O5617w.js → SettingsPage-Cl2eEX84.js} +2 -2
- package/dashboard/dist/assets/{SkillsPage-DSc5O7u7.js → SkillsPage-Cl8kb4jo.js} +1 -1
- package/dashboard/dist/assets/{TokenGalaxy-DIbAWJfY.js → TokenGalaxy-Da8tynGB.js} +1 -1
- package/dashboard/dist/assets/{ToolbarRootContext-B7EwUsvt.js → ToolbarRootContext-IQUwRnDp.js} +1 -1
- package/dashboard/dist/assets/{TrendMonitor-CeTPoZhn.js → TrendMonitor-lpOCu-La.js} +1 -1
- package/dashboard/dist/assets/{WidgetsPage-DycR-Xy_.js → WidgetsPage-Cmby6Cw0.js} +1 -1
- package/dashboard/dist/assets/{WrappedPage-Buz1wzSM.js → WrappedPage-CE3GkR5a.js} +1 -1
- package/dashboard/dist/assets/{__vite-browser-external-_RSGXjh3.js → __vite-browser-external-dDN0mi9f.js} +3 -3
- package/dashboard/dist/assets/{agent-logos-B0aXIO3B.js → agent-logos-D9dYPUzL.js} +1 -1
- package/dashboard/dist/assets/{arrow-up-right--SGPnId4.js → arrow-up-right-DwAAGP7p.js} +1 -1
- package/dashboard/dist/assets/{check-CJRaiH3e.js → check-D1Lq-9ts.js} +1 -1
- package/dashboard/dist/assets/{composite-Bwj_AQ49.js → composite-JEjFHOYa.js} +1 -1
- package/dashboard/dist/assets/{copy-DU0cBBCj.js → copy-Cgep9txD.js} +1 -1
- package/dashboard/dist/assets/{download-1G25F1-l.js → download-BvCJfrsP.js} +1 -1
- package/dashboard/dist/assets/{external-link-BTawmHLx.js → external-link-BvrBuvDE.js} +1 -1
- package/dashboard/dist/assets/{flame-Ck7u_g0N.js → flame-CpFTS5jY.js} +1 -1
- package/dashboard/dist/assets/{format-tokens-mvtbXN0_.js → format-tokens-DMy_T00F.js} +1 -1
- package/dashboard/dist/assets/{icons-C-vySzFI.js → icons-BF-Gt_W6.js} +1 -1
- package/dashboard/dist/assets/{index-Bn1BpzgP.js → index-BV_fWDL1.js} +1 -1
- package/dashboard/dist/assets/{index-Dl_4Ap2z.js → index-CG8txBGV.js} +1 -1
- package/dashboard/dist/assets/{index-oyq0VRzp.js → index-D7gB7QU6.js} +1 -1
- package/dashboard/dist/assets/{info-nLiOCn95.js → info-DN-YTwZw.js} +1 -1
- package/dashboard/dist/assets/{link-2-DqpkQl5I.js → link-2-C5QllJZa.js} +1 -1
- package/dashboard/dist/assets/{loader-circle-D9Uwv0lk.js → loader-circle-Br6MWmXZ.js} +1 -1
- package/dashboard/dist/assets/{maximize-2-BZqFpymh.js → maximize-2-DWQUOE9I.js} +1 -1
- package/dashboard/dist/assets/{modifiers.esm-D5idO4uG.js → modifiers.esm-BW3ZY-q5.js} +1 -1
- package/dashboard/dist/assets/{monitor-smartphone-wrYSytV5.js → monitor-smartphone-C0lh9STU.js} +1 -1
- package/dashboard/dist/assets/{plus-Buu86Rru.js → plus-DGzzR4Ta.js} +1 -1
- package/dashboard/dist/assets/{provider-display-DMDSBnrj.js → provider-display-C6cpMzsX.js} +1 -1
- package/dashboard/dist/assets/{react-Bj8RUcSV.js → react-Bl3I3D1L.js} +1 -1
- package/dashboard/dist/assets/{search-C8Vcia84.js → search-C9Xi6QaM.js} +1 -1
- package/dashboard/dist/assets/{skills-api-B9V7yAcx.js → skills-api-BPqKd9uy.js} +1 -1
- package/dashboard/dist/assets/{sortable.esm-BSct19df.js → sortable.esm-CDX2JVl9.js} +1 -1
- package/dashboard/dist/assets/{store-DUbjqECL.js → store-BBp505Pu.js} +1 -1
- package/dashboard/dist/assets/{terminal-DVzgSayL.js → terminal-CS1tejfk.js} +1 -1
- package/dashboard/dist/assets/{trash-Bo7xY33E.js → trash-CBCEVUxu.js} +1 -1
- package/dashboard/dist/assets/{use-community-stats-BCBvwoBJ.js → use-community-stats-W4PO2W2z.js} +1 -1
- package/dashboard/dist/assets/{use-latest-request-guard-Drj2VWM_.js → use-latest-request-guard-DkL6VAD-.js} +1 -1
- package/dashboard/dist/assets/{use-limits-display-prefs-BGZ8e1eB.js → use-limits-display-prefs-BrBaoX2Q.js} +1 -1
- package/dashboard/dist/assets/{use-ordered-list-DskYb1p5.js → use-ordered-list-BH_LviiX.js} +1 -1
- package/dashboard/dist/assets/use-reduced-motion-CoktFwg_.js +1 -0
- package/dashboard/dist/assets/{use-session-efficiency-pref-BbpqWKhz.js → use-session-efficiency-pref-8vzPyNum.js} +1 -1
- package/dashboard/dist/assets/{use-transform-C4LDbETT.js → use-transform-ILmR4oVe.js} +1 -1
- package/dashboard/dist/assets/use-usage-limits-CeoHpc3u.js +1 -0
- package/dashboard/dist/assets/{useCurrency-fr7T9OGZ.js → useCurrency-_1mDCij1.js} +1 -1
- package/dashboard/dist/assets/{useTokenFormat-DKAbaR7B.js → useTokenFormat-DalbmT3S.js} +1 -1
- package/dashboard/dist/assets/{zap-CqDAEt0Z.js → zap-DanLIcSw.js} +1 -1
- package/dashboard/dist/brand-logos/cline.png +0 -0
- package/dashboard/dist/index.html +13 -11
- package/dashboard/dist/ip-check.html +1 -1
- package/dashboard/dist/leaderboard.html +1 -1
- package/dashboard/dist/llms.txt +3 -2
- package/dashboard/dist/share.html +1 -1
- package/package.json +2 -2
- package/src/commands/init.js +25 -0
- package/src/commands/status.js +31 -0
- package/src/commands/sync.js +39 -0
- package/src/lib/pricing/curated-overrides.json +15 -0
- package/src/lib/pricing/index.js +6 -3
- package/src/lib/pricing/matcher.js +7 -0
- package/src/lib/pricing/seed-snapshot.json +1 -1
- package/src/lib/rollout.js +540 -0
- package/src/lib/zcode-limits.js +147 -16
- package/dashboard/dist/assets/DialogDescription-BS-3kTZ6.js +0 -1
- package/dashboard/dist/assets/use-reduced-motion-DE2WaiPY.js +0 -1
- package/dashboard/dist/assets/use-usage-limits-Cfx1w2nQ.js +0 -1
package/src/lib/zcode-limits.js
CHANGED
|
@@ -74,10 +74,13 @@ function resolveZcodeAppVersion({ home, env = process.env } = {}) {
|
|
|
74
74
|
return DEFAULT_ZCODE_APP_VERSION;
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
+
/** True when any ZCode layout is present: legacy v2/config.json, 3.14+ credentials, or the CLI db. */
|
|
77
78
|
function isZcodeInstalled({ home, env } = {}) {
|
|
78
79
|
const zcodeHome = resolveZcodeHome({ home, env });
|
|
79
80
|
const configPath = path.join(zcodeHome, "v2", "config.json");
|
|
80
81
|
if (fs.existsSync(configPath)) return true;
|
|
82
|
+
// ZCode 3.14+ no longer writes v2/config.json; a signed-in desktop app still keeps credentials.
|
|
83
|
+
if (fs.existsSync(path.join(zcodeHome, "v2", "credentials.json"))) return true;
|
|
81
84
|
const dbPath = path.join(zcodeHome, "cli", "db", "db.sqlite");
|
|
82
85
|
return fs.existsSync(dbPath);
|
|
83
86
|
}
|
|
@@ -128,8 +131,10 @@ function loadZcodeSelectedPlans({ home, env } = {}) {
|
|
|
128
131
|
try {
|
|
129
132
|
const setting = JSON.parse(fs.readFileSync(settingPath, "utf8"));
|
|
130
133
|
const selected = setting?.modelProviderFamilySelectedKeys;
|
|
131
|
-
if (!selected || typeof selected !== "object") return [];
|
|
132
134
|
const domain = typeof setting?.providerFamilyDomain === "string" ? setting.providerFamilyDomain : "";
|
|
135
|
+
if (!selected || typeof selected !== "object") {
|
|
136
|
+
return loadZcodeConnectionSelectedPlans(setting?.providerFamilyConnectionSelections, domain);
|
|
137
|
+
}
|
|
133
138
|
const domains = [domain, ...Object.keys(selected)].filter(Boolean);
|
|
134
139
|
const out = [];
|
|
135
140
|
for (const key of domains) {
|
|
@@ -144,6 +149,26 @@ function loadZcodeSelectedPlans({ home, env } = {}) {
|
|
|
144
149
|
}
|
|
145
150
|
}
|
|
146
151
|
|
|
152
|
+
/**
|
|
153
|
+
* ZCode 3.14+ records the chosen plan per family as `providerFamilyConnectionSelections`
|
|
154
|
+
* (`{ zai: { kind: "individual-coding-plan" } }`) instead of `modelProviderFamilySelectedKeys`.
|
|
155
|
+
* Team scope for these selections lives on the account credential, not here.
|
|
156
|
+
*/
|
|
157
|
+
function loadZcodeConnectionSelectedPlans(selections, domain) {
|
|
158
|
+
if (!selections || typeof selections !== "object") return [];
|
|
159
|
+
const families = [domain, ...Object.keys(selections)].filter((family) => family === "bigmodel" || family === "zai");
|
|
160
|
+
const out = [];
|
|
161
|
+
for (const family of families) {
|
|
162
|
+
const kind = typeof selections[family]?.kind === "string" ? selections[family].kind : "";
|
|
163
|
+
const planKind = /coding-plan$/.test(kind) ? "coding" : kind === "start-plan" ? "start" : null;
|
|
164
|
+
if (!planKind) continue;
|
|
165
|
+
const providerKey = `builtin:${family}-${planKind}-plan`;
|
|
166
|
+
if (out.some((plan) => plan.providerKey === providerKey)) continue;
|
|
167
|
+
out.push({ providerKey, teamContext: null });
|
|
168
|
+
}
|
|
169
|
+
return out;
|
|
170
|
+
}
|
|
171
|
+
|
|
147
172
|
/** Return the ordered provider keys without exposing the internal team context. */
|
|
148
173
|
function loadZcodeSelectedPlanProviderKeys(options = {}) {
|
|
149
174
|
return loadZcodeSelectedPlans(options).map((plan) => plan.providerKey);
|
|
@@ -218,6 +243,47 @@ function resolveZcodeCredentialAuth(providerKey, { home, env } = {}) {
|
|
|
218
243
|
return "";
|
|
219
244
|
}
|
|
220
245
|
|
|
246
|
+
/**
|
|
247
|
+
* Map a ZCode 3.14+ per-account key name onto the built-in coding-plan provider it serves:
|
|
248
|
+
* account-provider:coding-plan:account:<family>-individual-coding-plan:account:<id>:api-key
|
|
249
|
+
* account-provider:team:<providerId>:<productId>:<orgId>:<projectId>:account:<id>:api-key
|
|
250
|
+
* Team segments are URI-encoded by ZCode. Start-plan balances use the zcodejwttoken instead.
|
|
251
|
+
* @returns {{ providerKey: string, teamContext: { organizationId: string, projectId: string } | null } | null}
|
|
252
|
+
*/
|
|
253
|
+
function parseZcodeAccountProviderCredentialName(name) {
|
|
254
|
+
const match = typeof name === "string" ? name.match(/^account-provider:(.+):account:[^:]+:api-key$/) : null;
|
|
255
|
+
if (!match) return null;
|
|
256
|
+
const scope = match[1];
|
|
257
|
+
const individual = scope.match(/^coding-plan:account:(bigmodel|zai)-individual-coding-plan$/);
|
|
258
|
+
if (individual) return { providerKey: `builtin:${individual[1]}-coding-plan`, teamContext: null };
|
|
259
|
+
if (!scope.startsWith("team:")) return null;
|
|
260
|
+
const parts = scope.slice("team:".length).split(":");
|
|
261
|
+
if (parts.length !== 4) return null;
|
|
262
|
+
try {
|
|
263
|
+
const [providerId, productId, organizationId, projectId] = parts.map((part) => decodeURIComponent(part).trim());
|
|
264
|
+
const team = providerId.match(/^account:(bigmodel|zai)-team-coding-plan$/);
|
|
265
|
+
if (!team || !productId || !organizationId || !projectId) return null;
|
|
266
|
+
return { providerKey: `builtin:${team[1]}-coding-plan`, teamContext: { organizationId, projectId } };
|
|
267
|
+
} catch (_error) {
|
|
268
|
+
return null;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/** Collect decrypted per-account coding-plan keys, grouped by built-in provider key. */
|
|
273
|
+
function loadZcodeAccountProviderAuths({ home, env } = {}) {
|
|
274
|
+
const credentials = loadZcodeCredentials({ home, env });
|
|
275
|
+
const out = {};
|
|
276
|
+
for (const name of Object.keys(credentials)) {
|
|
277
|
+
const parsed = parseZcodeAccountProviderCredentialName(name);
|
|
278
|
+
if (!parsed) continue;
|
|
279
|
+
const decrypted = decryptZcodeCredentialValue(credentials[name], { home, env });
|
|
280
|
+
const apiKey = typeof decrypted === "string" ? decrypted.trim() : "";
|
|
281
|
+
if (!apiKey) continue;
|
|
282
|
+
(out[parsed.providerKey] ||= []).push({ apiKey, teamContext: parsed.teamContext });
|
|
283
|
+
}
|
|
284
|
+
return out;
|
|
285
|
+
}
|
|
286
|
+
|
|
221
287
|
function isZcodeBuiltinPlanProvider(providerKey) {
|
|
222
288
|
return /^builtin:(bigmodel|zai)-(start|coding)-plan$/.test(providerKey);
|
|
223
289
|
}
|
|
@@ -281,15 +347,19 @@ function resolveZcodeProviderQuotaUrl(providerKey, provider, env = process.env)
|
|
|
281
347
|
/**
|
|
282
348
|
* Build quota/billing candidates from enabled providers and their existing keys.
|
|
283
349
|
* Selected plans take precedence; team scope stays attached to its own provider.
|
|
350
|
+
* ZCode 3.14+ dropped v2/config.json: there, candidates come from credentials.json
|
|
351
|
+
* alone (the active family's zcodejwttoken for start plans, per-account coding-plan keys).
|
|
284
352
|
*/
|
|
285
353
|
function loadZcodeAuthCandidates({ home, env } = {}) {
|
|
286
354
|
const zcodeHome = resolveZcodeHome({ home, env });
|
|
287
355
|
const configPath = path.join(zcodeHome, "v2", "config.json");
|
|
288
|
-
|
|
356
|
+
const hasConfig = fs.existsSync(configPath);
|
|
289
357
|
try {
|
|
290
|
-
const config = JSON.parse(fs.readFileSync(configPath, "utf8"));
|
|
358
|
+
const config = hasConfig ? JSON.parse(fs.readFileSync(configPath, "utf8")) : {};
|
|
291
359
|
if (!config || typeof config !== "object") return [];
|
|
292
360
|
const providers = config.provider || {};
|
|
361
|
+
// Per-account keys are a 3.14+ concept; a legacy config.json stays the only key source there.
|
|
362
|
+
const accountAuths = hasConfig ? {} : loadZcodeAccountProviderAuths({ home, env });
|
|
293
363
|
const defaultCandidates = [
|
|
294
364
|
"builtin:bigmodel-start-plan",
|
|
295
365
|
"builtin:zai-start-plan",
|
|
@@ -309,18 +379,25 @@ function loadZcodeAuthCandidates({ home, env } = {}) {
|
|
|
309
379
|
].filter((key, index, all) => all.indexOf(key) === index);
|
|
310
380
|
const auths = [];
|
|
311
381
|
for (const key of candidates) {
|
|
312
|
-
const
|
|
313
|
-
|
|
314
|
-
if (provider
|
|
382
|
+
const configured = providers[key];
|
|
383
|
+
const provider = configured && typeof configured === "object" ? configured : null;
|
|
384
|
+
if (provider?.enabled === false) continue;
|
|
315
385
|
if (hasAvailability && availability?.[key]?.status && availability[key].status !== "available") continue;
|
|
316
386
|
const apiKey = typeof provider?.options?.apiKey === "string" ? provider.options.apiKey.trim() : "";
|
|
317
387
|
const billingBaseUrl = resolveZcodeProviderBillingBaseUrl(key, provider, env);
|
|
318
388
|
const quotaUrl = resolveZcodeProviderQuotaUrl(key, provider, env);
|
|
319
389
|
const teamContext = selectedPlans.find((plan) => plan.providerKey === key)?.teamContext;
|
|
320
|
-
|
|
390
|
+
// Legacy layouts only trust the shared JWT for providers config.json still lists.
|
|
391
|
+
const credentialApiKey = provider || !hasConfig ? resolveZcodeCredentialAuth(key, { home, env }) : "";
|
|
392
|
+
const accountEntries = (accountAuths[key] || []).map((entry) => ({
|
|
393
|
+
apiKey: entry.apiKey,
|
|
394
|
+
authSource: "credential:account-provider",
|
|
395
|
+
teamContext: entry.teamContext,
|
|
396
|
+
}));
|
|
321
397
|
const authEntries = [
|
|
322
|
-
credentialApiKey ? { apiKey: credentialApiKey, authSource: "credential:zcodejwttoken" } : null,
|
|
323
|
-
|
|
398
|
+
credentialApiKey ? { apiKey: credentialApiKey, authSource: "credential:zcodejwttoken", teamContext } : null,
|
|
399
|
+
...accountEntries,
|
|
400
|
+
apiKey ? { apiKey, authSource: "provider:config", teamContext } : null,
|
|
324
401
|
].filter(Boolean);
|
|
325
402
|
const seenKeys = new Set();
|
|
326
403
|
for (const entry of authEntries) {
|
|
@@ -334,7 +411,7 @@ function loadZcodeAuthCandidates({ home, env } = {}) {
|
|
|
334
411
|
baseUrl: provider?.options?.baseURL || null,
|
|
335
412
|
billingBaseUrl,
|
|
336
413
|
quotaUrl,
|
|
337
|
-
...(teamContext ? { teamContext } : {}),
|
|
414
|
+
...(entry.teamContext ? { teamContext: entry.teamContext } : {}),
|
|
338
415
|
availability: availability?.[key]?.status || null,
|
|
339
416
|
});
|
|
340
417
|
}
|
|
@@ -349,6 +426,7 @@ function loadZcodeApiKey({ home, env } = {}) {
|
|
|
349
426
|
return loadZcodeAuthCandidates({ home, env })[0] || null;
|
|
350
427
|
}
|
|
351
428
|
|
|
429
|
+
/** Client-identification headers ZCode sends to its own billing host, including X-Device-Mid when known. */
|
|
352
430
|
function buildZcodeSourceHeaders({ home, env } = {}) {
|
|
353
431
|
const headers = {
|
|
354
432
|
"User-Agent": `ZCode/${resolveZcodeAppVersion({ home, env })}`,
|
|
@@ -361,11 +439,29 @@ function buildZcodeSourceHeaders({ home, env } = {}) {
|
|
|
361
439
|
"X-Os-Category": process.platform,
|
|
362
440
|
"X-Os-Version": os.release(),
|
|
363
441
|
};
|
|
364
|
-
const deviceMid =
|
|
442
|
+
const deviceMid = loadZcodeTelemetryDeviceMid({ home, env })
|
|
443
|
+
|| loadZcodeCredential("zcodefeedbackclientid", { home, env });
|
|
365
444
|
if (deviceMid) headers["X-Device-Mid"] = deviceMid;
|
|
366
445
|
return headers;
|
|
367
446
|
}
|
|
368
447
|
|
|
448
|
+
/**
|
|
449
|
+
* ZCode 3.14+ keeps the device id in v2/telemetry-state.json, and billing/balance
|
|
450
|
+
* rejects requests without X-Device-Mid as `code=3001 parameter error`.
|
|
451
|
+
* @returns {string} the device id, or "" when absent or not header-safe
|
|
452
|
+
*/
|
|
453
|
+
function loadZcodeTelemetryDeviceMid({ home, env } = {}) {
|
|
454
|
+
const statePath = path.join(resolveZcodeHome({ home, env }), "v2", "telemetry-state.json");
|
|
455
|
+
if (!fs.existsSync(statePath)) return "";
|
|
456
|
+
try {
|
|
457
|
+
const state = JSON.parse(fs.readFileSync(statePath, "utf8"));
|
|
458
|
+
const deviceMid = typeof state?.deviceMid === "string" ? state.deviceMid.trim() : "";
|
|
459
|
+
return /^[\x20-\x7e]+$/.test(deviceMid) ? deviceMid : "";
|
|
460
|
+
} catch (_error) {
|
|
461
|
+
return "";
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
|
|
369
465
|
function zcodeValNumber(value) {
|
|
370
466
|
if (value == null) return null;
|
|
371
467
|
const n = Number(value);
|
|
@@ -407,6 +503,10 @@ function deriveZcodePlanLabel(planId) {
|
|
|
407
503
|
return m[1].charAt(0).toUpperCase() + m[1].slice(1);
|
|
408
504
|
}
|
|
409
505
|
|
|
506
|
+
/**
|
|
507
|
+
* Normalize a start-plan billing/balance payload into labelled buckets plus the
|
|
508
|
+
* primary/secondary/tertiary windows (daily allowances first, promotional grants after).
|
|
509
|
+
*/
|
|
410
510
|
function normalizeZcodeBalanceResponse(body) {
|
|
411
511
|
const data = body?.data;
|
|
412
512
|
if (!data || typeof data !== "object") {
|
|
@@ -428,6 +528,20 @@ function normalizeZcodeBalanceResponse(body) {
|
|
|
428
528
|
}
|
|
429
529
|
|
|
430
530
|
const serverTime = zcodeValNumber(data.server_time);
|
|
531
|
+
// Promotional grants ("free eggs", weekend builds) arrive as extra plans whose
|
|
532
|
+
// entitlements are one-time; index them so each bucket can say where it came from.
|
|
533
|
+
const plans = Array.isArray(data.plans) ? data.plans : [];
|
|
534
|
+
const hasPlans = plans.length > 0;
|
|
535
|
+
const planByUserPlanId = new Map();
|
|
536
|
+
const periodByEntitlementId = new Map();
|
|
537
|
+
for (const plan of plans) {
|
|
538
|
+
if (typeof plan?.user_plan_id === "string") planByUserPlanId.set(plan.user_plan_id, plan);
|
|
539
|
+
for (const ent of Array.isArray(plan?.entitlements) ? plan.entitlements : []) {
|
|
540
|
+
if (typeof ent?.entitlement_id === "string" && typeof ent?.period === "string") {
|
|
541
|
+
periodByEntitlementId.set(ent.entitlement_id, ent.period);
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
}
|
|
431
545
|
const buckets = balances.map((b) => {
|
|
432
546
|
const total = zcodeValNumber(b.total_units);
|
|
433
547
|
const used = zcodeValNumber(b.used_units);
|
|
@@ -437,9 +551,21 @@ function normalizeZcodeBalanceResponse(body) {
|
|
|
437
551
|
const usedPercent =
|
|
438
552
|
total != null && total > 0 && used != null ? (used / total) * 100 : null;
|
|
439
553
|
|
|
554
|
+
const showName = typeof b.show_name === "string" ? b.show_name : "";
|
|
555
|
+
const entitlementId = typeof b.entitlement_id === "string" ? b.entitlement_id : "";
|
|
556
|
+
const plan = planByUserPlanId.get(b.user_plan_id) || null;
|
|
557
|
+
const period = periodByEntitlementId.get(entitlementId) || null;
|
|
558
|
+
const oneTime = period === "one_time";
|
|
559
|
+
const planName = typeof plan?.name === "string" && plan.name.trim() ? plan.name.trim() : null;
|
|
560
|
+
|
|
440
561
|
return {
|
|
441
|
-
show_name:
|
|
442
|
-
|
|
562
|
+
show_name: showName,
|
|
563
|
+
label: oneTime && planName ? `${showName} · ${planName}` : showName,
|
|
564
|
+
entitlement_id: entitlementId,
|
|
565
|
+
plan_id: typeof b.plan_id === "string" ? b.plan_id : null,
|
|
566
|
+
plan_name: planName,
|
|
567
|
+
period,
|
|
568
|
+
priority: zcodeValNumber(b.priority),
|
|
443
569
|
total_units: total,
|
|
444
570
|
used_units: used,
|
|
445
571
|
remaining_units: remaining,
|
|
@@ -447,15 +573,20 @@ function normalizeZcodeBalanceResponse(body) {
|
|
|
447
573
|
};
|
|
448
574
|
});
|
|
449
575
|
|
|
450
|
-
//
|
|
451
|
-
//
|
|
576
|
+
// Recurring (daily) allowances first so the primary/secondary windows keep meaning
|
|
577
|
+
// "today's main models"; one-time promotional grants follow. Within each group, ZCode's
|
|
578
|
+
// own bucket priority (flagship model first), then larger totals.
|
|
452
579
|
const sorted = buckets.slice().sort((a, b) => {
|
|
580
|
+
const aOneTime = a.period === "one_time" ? 1 : 0;
|
|
581
|
+
const bOneTime = b.period === "one_time" ? 1 : 0;
|
|
582
|
+
if (aOneTime !== bOneTime) return aOneTime - bOneTime;
|
|
583
|
+
if (hasPlans && a.priority != null && b.priority != null && a.priority !== b.priority) return b.priority - a.priority;
|
|
453
584
|
const aTotal = a.total_units || 0;
|
|
454
585
|
const bTotal = b.total_units || 0;
|
|
455
586
|
return bTotal - aTotal;
|
|
456
587
|
});
|
|
457
588
|
|
|
458
|
-
const planId = typeof balances[0]?.plan_id === "string" ? balances[0].plan_id : null;
|
|
589
|
+
const planId = sorted[0]?.plan_id || (typeof balances[0]?.plan_id === "string" ? balances[0].plan_id : null);
|
|
459
590
|
return {
|
|
460
591
|
server_time: serverTime,
|
|
461
592
|
plan_kind: "start-plan",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{r as n,v as a}from"./__vite-browser-external-_RSGXjh3.js";import{u as p}from"./DialogTitle-CRJVqO3Z.js";import{u as c}from"./composite-Bwj_AQ49.js";const x=n.forwardRef(function(e,r){const{render:l,className:u,style:m,id:s,...t}=e,i=p(),o=c(s);return i.useSyncedValueWithCleanup("descriptionElementId",o),a("p",e,{ref:r,props:[{id:o},t]})});export{x as D};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{r as o}from"./__vite-browser-external-_RSGXjh3.js";import{h as r,i as t,p as s}from"./react-Bj8RUcSV.js";function i(){!r.current&&t();const[e]=o.useState(s.current);return e}export{i as u};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{J as S,ab as x,r as d,c as N,ac as O,ad as A,ae as g}from"./__vite-browser-external-_RSGXjh3.js";import{l as R,i as _,L as P,a as q}from"./use-limits-display-prefs-BGZ8e1eB.js";import{u as z}from"./use-latest-request-guard-Drj2VWM_.js";const F="native:notificationPermission";let M=null;function I(){return typeof window<"u"&&!!window.chrome?.webview}function L(){return S()?M||"unknown":I()?"granted":typeof Notification>"u"?"unsupported":Notification.permission}function j(e){if(typeof window>"u")return()=>{};const i=n=>{const w=n?.detail?.status;typeof w=="string"&&(M=w),e(L())};return window.addEventListener(F,i),e(L()),S()&&x({type:"getNotificationStatus"}),()=>window.removeEventListener(F,i)}async function T(){if(S()){x({type:"requestNotificationPermission"});return}I()||typeof Notification<"u"&&Notification.permission==="default"&&await Notification.requestPermission().catch(()=>"denied")}const v="tt.limitAlerts.enabled";function $(){try{return window.localStorage.getItem(v)==="1"}catch{return!1}}function te(){const[e,i]=d.useState($),[n,w]=d.useState("unknown");d.useEffect(()=>j(w),[]);const u=d.useCallback(async o=>{const r=!!o;r&&await T();try{window.localStorage.setItem(v,r?"1":"0")}catch{}i(r)},[]);return{enabled:e,setEnabled:u,permissionBlocked:n==="denied"}}function B(e,i){if(!(e>0))return null;const n=(e-i)/e;return Number.isFinite(n)?Math.min(Math.max(n,0),1):null}function G(e,i,n=.03){return e>i+n}function V(e){const i=Math.max(0,Math.floor(e)),n=Math.floor(i/3600);return n>24?`${Math.floor(n/24)}d`:n>0?`${n}h`:`${Math.floor(i/60)}m`}function J(e,i){if(typeof e.windowSeconds=="number")return e.windowSeconds;if(e.windowSecondsField&&i){const n=i[e.windowSecondsField];return typeof n=="number"&&n>0?n:null}return null}function U(e){return e==null?NaN:typeof e=="number"?e*1e3:Date.parse(e)}function H({usedPercent:e,windowSeconds:i,resetMs:n,mode:w,now:u=Date.now()}){const o=Math.min(Math.max(Number(e)||0,0),100)/100,r={pacePercent:null,paceOver:!1,expectedPercent:null,runsOutEta:null,projectedEnd:null};if(!(i>0)||!Number.isFinite(n))return r;const l=Math.max(0,(n-u)/1e3),a=B(i,l);if(a==null)return r;if(r.expectedPercent=Math.round(a*100),r.paceOver=G(o,a),o>=.05){const c=w==="remaining"?1-a:a;r.pacePercent=c*100}if(a>.02&&o>0){const c=i*a,m=o/c,f=o/a;f>=1&&m>0?r.runsOutEta=V((1-o)/m):r.projectedEnd=Math.round(Math.min(f,1)*100)}return r}const W={claude:{windows(e){const i=Array.isArray(e.weekly_scoped)?e.weekly_scoped.map(n=>({key:`scoped-${n.label}`,label:n.label,window:n,pctField:"utilization",resetField:"resets_at",windowSeconds:604800})):[];return[{key:"5h",labelKey:"limits.label.claude_5h",window:e.five_hour,pctField:"utilization",resetField:"resets_at",windowSeconds:5*3600},{key:"7d",labelKey:"limits.label.claude_7d",window:e.seven_day,pctField:"utilization",resetField:"resets_at",windowSeconds:7*86400},{key:"opus",labelKey:"limits.label.claude_opus",window:e.seven_day_opus,pctField:"utilization",resetField:"resets_at",windowSeconds:7*86400},...i]}},codex:{extra:"codex_meta",windows(e){return[{key:"5h",labelKey:"limits.label.codex_5h",window:e.primary_window,windowSecondsField:"limit_window_seconds"},{key:"7d",labelKey:"limits.label.codex_7d",window:e.secondary_window,windowSecondsField:"limit_window_seconds"},{key:"credits",labelKey:"limits.label.codex_credits",window:e.credit_window},{key:"spark-5h",labelKey:"limits.label.codex_spark_5h",window:e.spark_primary_window,windowSecondsField:"limit_window_seconds"},{key:"spark-7d",labelKey:"limits.label.codex_spark_7d",window:e.spark_secondary_window,windowSecondsField:"limit_window_seconds"}]}},cursor:{windows(e){return[{key:"plan",labelKey:"limits.label.cursor_plan",window:e.primary_window,windowSecondsField:"limit_window_seconds"},{key:"auto",labelKey:"limits.label.cursor_auto",window:e.secondary_window,windowSecondsField:"limit_window_seconds"},{key:"api",labelKey:"limits.label.cursor_api",window:e.tertiary_window,windowSecondsField:"limit_window_seconds"},{key:"grok-bot",labelKey:"limits.label.cursor_grok_bot",window:e.quaternary_window,windowSecondsField:"limit_window_seconds"}]}},gemini:{windows(e){return[{key:"pro",labelKey:"limits.label.gemini_pro",window:e.primary_window},{key:"flash",labelKey:"limits.label.gemini_flash",window:e.secondary_window},{key:"lite",labelKey:"limits.label.gemini_lite",window:e.tertiary_window}]}},kimi:{extra:"kimi_parallel",windows(e){return[{key:"weekly",labelKey:"limits.label.kimi_weekly",window:e.primary_window,windowSeconds:7*86400},{key:"5h",labelKey:"limits.label.kimi_5h",window:e.secondary_window,windowSeconds:5*3600},{key:"total",labelKey:"limits.label.kimi_total",window:e.tertiary_window}]}},kiro:{extra:"kiro_credits",windows(e){return[{key:"month",labelKey:"limits.label.kiro_month",window:e.primary_window},{key:"bonus",labelKey:"limits.label.kiro_bonus",window:e.secondary_window}]}},grok:{windows(e){const i=typeof e.period_type=="string"?e.period_type:null,n=i==="weekly"?"limits.label.grok_week":i==="daily"?"limits.label.grok_day":"limits.label.grok_month",w=i==="weekly"?7*86400:i==="daily"?86400:void 0;return[{key:i==="weekly"?"week":i==="daily"?"day":"month",labelKey:n,window:e.primary_window,windowSeconds:w},{key:"ondemand",labelKey:"limits.label.grok_ondemand",window:e.secondary_window}]}},antigravity:{windows(e){return[{key:"claude-weekly",labelKey:"limits.label.antigravity_claude_weekly",window:e.primary_window},{key:"claude-5h",labelKey:"limits.label.antigravity_claude_5h",window:e.secondary_window},{key:"gemini-weekly",labelKey:"limits.label.antigravity_gemini_weekly",window:e.tertiary_window},{key:"gemini-5h",labelKey:"limits.label.antigravity_gemini_5h",window:e.quaternary_window}]}},copilot:{extra:"copilot_otel",windows(e){return[{key:"premium",labelKey:"limits.label.copilot_premium",window:e.primary_window},{key:"chat",labelKey:"limits.label.copilot_chat",window:e.secondary_window}]}},zcode:{windows(e){return e.plan_kind==="coding-plan"?[{key:"5h",labelKey:"limits.label.zcode_5h",window:e.primary_window},{key:"weekly",labelKey:"limits.label.zcode_weekly",window:e.secondary_window},{key:"tools",labelKey:"limits.label.zcode_tools",window:e.tertiary_window}]:[{key:"glm52",labelKey:"limits.label.zcode_glm52",window:e.primary_window},{key:"glm5t",labelKey:"limits.label.zcode_glm5t",window:e.secondary_window}]}},opencodeGo:{windows(e){return[{key:"5h",labelKey:"limits.label.opencode_go_5h",window:e.primary_window},{key:"weekly",labelKey:"limits.label.opencode_go_weekly",window:e.secondary_window},{key:"monthly",labelKey:"limits.label.opencode_go_monthly",window:e.tertiary_window}]}},qoder:{windows(e){return[{key:"credits",labelKey:"limits.label.qoder_credits",window:e.primary_window},{key:"ultimate",labelKey:"limits.label.qoder_ultimate",window:e.secondary_window,timeKind:"expiry"}]}},qoderCn:{windows(e){return[{key:"credits",labelKey:"limits.label.qoder_cn_credits",window:e.primary_window},{key:"ultimate",labelKey:"limits.label.qoder_cn_ultimate",window:e.secondary_window,timeKind:"expiry"}]}},codingPlan:{windows(e){return[{key:"5h",labelKey:"limits.label.ark_coding_plan_5h",window:e.primary_window},{key:"weekly",labelKey:"limits.label.ark_coding_plan_weekly",window:e.secondary_window},{key:"monthly",labelKey:"limits.label.ark_coding_plan_monthly",window:e.tertiary_window}]}},commandCode:{windows(e){return[{key:"5h",labelKey:"limits.label.command_code_5h",window:e.primary_window},{key:"weekly",labelKey:"limits.label.command_code_weekly",window:e.secondary_window}]}},agentPlan:{windows(e){return[{key:"5h",labelKey:"limits.label.ark_agent_plan_5h",window:e.primary_window},{key:"weekly",labelKey:"limits.label.ark_agent_plan_weekly",window:e.secondary_window},{key:"monthly",labelKey:"limits.label.ark_agent_plan_monthly",window:e.tertiary_window}]}},devin:{windows(e){return[{key:"daily",labelKey:"limits.label.devin_daily",window:e.primary_window,windowSecondsField:"limit_window_seconds"},{key:"weekly",labelKey:"limits.label.devin_weekly",window:e.secondary_window,windowSecondsField:"limit_window_seconds"}]}}},D="tt.limitAlerts.cycles.v1";function Y(){try{return JSON.parse(window.localStorage.getItem(D)||"{}")}catch{return{}}}function Q(e){try{window.localStorage.setItem(D,JSON.stringify(e))}catch{}}function X(e,{now:i=Date.now()}={}){const n=[],w=W;for(const[u,o]of Object.entries(e||{})){const r=w[u];if(!(!o?.configured||o.error||!r))for(const l of r.windows(o)){if(!l.window)continue;const a=Number(l.pctField==="utilization"?l.window.utilization:l.window.used_percent),c=l.resetField==="resets_at"?l.window.resets_at:l.window.reset_at,m=U(c),f=H({usedPercent:a,windowSeconds:J(l,l.window),resetMs:m,mode:"used",now:i});!f.runsOutEta||!f.paceOver||a<20||!(m>i)||n.push({id:`${u}:${l.key}:${m}`,providerId:u,windowKey:l.key,resetMs:m,usedPercent:a,runsOutEta:f.runsOutEta})}}return n}function Z(e){const i=Y(),n=X(e);for(const o of n){if(i[o.id])continue;const r=R(o.providerId),l=N("limits.alert.title",{provider:r}),a=N("limits.alert.body",{eta:o.runsOutEta,percent:Math.round(o.usedPercent)});let c=O({title:l,body:a,id:o.id});!c&&typeof Notification<"u"&&Notification.permission==="granted"&&(new Notification(l,{body:a,tag:o.id}),c=!0),c&&(i[o.id]=Date.now())}const w=Date.now()-864e5,u=Object.fromEntries(Object.entries(i).filter(([o,r])=>{const l=Number(o.split(":").at(-1));return Number.isFinite(l)?l>=w:Number(r)>=w}).slice(-100));return Q(u),n.length}function k(e,i){return!e||i||!e.devin||e.devin.configured===!1&&Object.keys(e.devin).length===1?e:{...e,devin:{configured:!1}}}function oe(e){const i=!!e?.initialState,[n,w]=d.useState(_),[u,o]=d.useState(()=>i?k(e?.initialState?.data??null,_()):null),[r,l]=d.useState(()=>i?e?.initialState?.error??null:null),[a,c]=d.useState(!i),m=!!e?.initialRefresh,f=!!e?.publishToPreloadCache,b=z([n]);d.useEffect(()=>{if(typeof window>"u")return;const s=()=>w(_()),t=y=>{q(y.key)&&s()};return window.addEventListener(P,s),window.addEventListener("storage",t),()=>{window.removeEventListener(P,s),window.removeEventListener("storage",t)}},[]),d.useEffect(()=>{if(!(!u||typeof window>"u"))try{window.localStorage.getItem(v)==="1"&&Z(u)}catch{}},[u]);const p=d.useCallback((s,t)=>{!f||!s||typeof s!="object"||A(k(s,_()),{source:t})},[f]),C=d.useCallback(async()=>{const s=b();try{const t=await g({refresh:!0,devinEnabled:_()});if(!s())return;const y=t&&typeof t=="object"?t:null;o(k(y,_())),l(null),c(!1),p(y,"manual-refresh")}catch(t){if(!s())return;l(t?.message||String(t)),c(!1)}},[b,p]),h=d.useCallback(async()=>{const s=b();try{const t=await g({devinEnabled:_()});if(!s())return;const y=t&&typeof t=="object"?t:null;o(k(y,_())),l(null),c(!1),p(y,"page-load")}catch(t){if(!s())return;l(t?.message||String(t)),c(!1)}},[b,p]);d.useEffect(()=>{if(typeof window>"u"||typeof document>"u")return;const s=15e3;let t=Date.now();const y=()=>{if(document.visibilityState!=="visible")return;const E=Date.now();E-t<s||(t=E,h())};return window.addEventListener("focus",y),document.addEventListener("visibilitychange",y),()=>{window.removeEventListener("focus",y),document.removeEventListener("visibilitychange",y)}},[h]);const K=d.useRef(n);return d.useEffect(()=>{K.current!==n&&(K.current=n,n||o(s=>k(s,!1)),h())},[n,h]),d.useEffect(()=>{if(i&&!m)return;const s=b();(async()=>{try{const t=await g({devinEnabled:_()});if(!s())return;const y=t&&typeof t=="object"?t:null;o(k(y,_())),l(null),p(y,"page-load")}catch(t){if(!s())return;l(t?.message||String(t))}finally{s()&&c(!1)}})()},[b,i,m,p]),{data:u,error:r,isLoading:a,refresh:C}}export{W as P,J as a,te as b,H as c,U as r,Z as s,oe as u};
|