tokentracker-cli 1.1.10 → 1.1.12
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 +2 -1
- package/dashboard/dist/assets/{AchievementBadge-CH97d6cg.js → AchievementBadge-bxsSwozZ.js} +1 -1
- package/dashboard/dist/assets/{AchievementsPage-Dwvj09sF.js → AchievementsPage-CCGsTNky.js} +2 -2
- package/dashboard/dist/assets/{AchievementsSection-D6HHK1f-.js → AchievementsSection-a-ucN3O9.js} +1 -1
- package/dashboard/dist/assets/{BadgeDetailModal-Bpr6rY9l.js → BadgeDetailModal-CNCCgDRL.js} +1 -1
- package/dashboard/dist/assets/BotAnimated-DYrmIQt7.js +1 -0
- package/dashboard/dist/assets/{Card-38v0-L6e.js → Card-615UteEP.js} +1 -1
- package/dashboard/dist/assets/{CommandPalette-Bj0e0ye0.js → CommandPalette-BzmRKASJ.js} +1 -1
- package/dashboard/dist/assets/{CommunityStatsModal-IoQLJCe2.js → CommunityStatsModal-DdRpM1bD.js} +1 -1
- package/dashboard/dist/assets/{ConfirmModal-B7uK0Wjr.js → ConfirmModal-BQIPBiA5.js} +1 -1
- package/dashboard/dist/assets/Controls-Cup1Mj2U.js +1 -0
- package/dashboard/dist/assets/DashboardPage-DF1bFyHx.js +1 -0
- package/dashboard/dist/assets/{DevicePage-DE-NSyZg.js → DevicePage-CC31pv5N.js} +1 -1
- package/dashboard/dist/assets/{DialogClose-DB6ZRDR3.js → DialogClose-CaYoc9xQ.js} +1 -1
- package/dashboard/dist/assets/DialogDescription-DZLOEWil.js +1 -0
- package/dashboard/dist/assets/{DialogTitle-CgwmTJf3.js → DialogTitle-BViOiFtR.js} +1 -1
- package/dashboard/dist/assets/{FadeIn-CMjPtMSB.js → FadeIn-BQYqxLXW.js} +1 -1
- package/dashboard/dist/assets/{HeaderGithubStar-D5cSnbcg.js → HeaderGithubStar-CpGwcrZV.js} +1 -1
- package/dashboard/dist/assets/{HoverTooltip-CFV8yLxb.js → HoverTooltip--hTrUe1c.js} +1 -1
- package/dashboard/dist/assets/{IpCheckPage-Ctu-GWJQ.js → IpCheckPage-gPQntnIE.js} +1 -1
- package/dashboard/dist/assets/{LandingPage-PAIF034o.js → LandingPage-Cw72oDTD.js} +2 -2
- package/dashboard/dist/assets/{LeaderboardAvatar-D3CsY-nP.js → LeaderboardAvatar-CnqlbA5v.js} +1 -1
- package/dashboard/dist/assets/{LeaderboardPage-qE8DD-Ia.js → LeaderboardPage-CvdG-SGy.js} +2 -2
- package/dashboard/dist/assets/{LeaderboardProfileModal-BY3uaIdF.js → LeaderboardProfileModal-CqzEW_FY.js} +4 -4
- package/dashboard/dist/assets/{LeaderboardProfilePage-CwX77U5Z.js → LeaderboardProfilePage-DCjJ7yF3.js} +3 -3
- package/dashboard/dist/assets/{LimitsPage-BlJgvFay.js → LimitsPage-DMGI3mL9.js} +2 -2
- package/dashboard/dist/assets/{LocalOnlyNotice-CLFKSu0V.js → LocalOnlyNotice-CpGpv1oF.js} +1 -1
- package/dashboard/dist/assets/{LoginCard-Bdp2gihl.js → LoginCard-B5W06Jrz.js} +1 -1
- package/dashboard/dist/assets/{LoginModal-o_t6uvYP.js → LoginModal-B4Y8XRkn.js} +1 -1
- package/dashboard/dist/assets/{LoginPage-Cc3ZHUU8.js → LoginPage-BLN-PdCh.js} +1 -1
- package/dashboard/dist/assets/PetPage-BvY7fR8_.js +1 -0
- package/dashboard/dist/assets/{PopoverPopup-CGJBBnIf.js → PopoverPopup-C4_m01Pc.js} +1 -1
- package/dashboard/dist/assets/{ProviderIcon-1OG4Kbkl.js → ProviderIcon-LgUYzw52.js} +1 -1
- package/dashboard/dist/assets/{ResetPasswordPage-DbfS1gfH.js → ResetPasswordPage-Dgzafk9_.js} +1 -1
- package/dashboard/dist/assets/{SegmentedControl-DPKl-28R.js → SegmentedControl-CMWf089j.js} +1 -1
- package/dashboard/dist/assets/{Select-BTA6mSut.js → Select-BNFp1Pww.js} +1 -1
- package/dashboard/dist/assets/{SelectItemText-CX5Br8hd.js → SelectItemText-Jz-4OEyW.js} +1 -1
- package/dashboard/dist/assets/{ServiceStatusPage-CaTOLkT7.js → ServiceStatusPage-AEW89tSP.js} +1 -1
- package/dashboard/dist/assets/{SessionsPage-Ixp6Fseo.js → SessionsPage-DTW1sFcW.js} +2 -2
- package/dashboard/dist/assets/SettingsPage-2z_a9T_C.js +2 -0
- package/dashboard/dist/assets/{SkillsPage-BUUfMFpU.js → SkillsPage-BkPEwhXO.js} +1 -1
- package/dashboard/dist/assets/{TokenGalaxy-DnfKnQhr.js → TokenGalaxy-Cs5wfOxe.js} +1 -1
- package/dashboard/dist/assets/{ToolbarRootContext-D0wMtL6Z.js → ToolbarRootContext-B3pyxVI-.js} +1 -1
- package/dashboard/dist/assets/TrendMonitor-BmSRt3h3.js +19 -0
- package/dashboard/dist/assets/{WidgetsPage-Bfod5aSH.js → WidgetsPage-BN5ePVqf.js} +1 -1
- package/dashboard/dist/assets/{WrappedPage-fYftPA8s.js → WrappedPage-DZTG3lCh.js} +1 -1
- package/dashboard/dist/assets/__vite-browser-external-4IDwIR3i.js +45 -0
- package/dashboard/dist/assets/__vite-browser-external-CAQ_i-1v.css +1 -0
- package/dashboard/dist/assets/{agent-logos-C0O8Lnmv.js → agent-logos-DQmv0J3b.js} +1 -1
- package/dashboard/dist/assets/{arrow-up-right-Bs0RpChC.js → arrow-up-right-BbkRcWv3.js} +1 -1
- package/dashboard/dist/assets/{check-Dj5Wi1I7.js → check-Dz72GL-k.js} +1 -1
- package/dashboard/dist/assets/{composite-BeHO1nUS.js → composite-COAFYYB2.js} +1 -1
- package/dashboard/dist/assets/{copy-Dgp1NqhD.js → copy-wEl0WhF0.js} +1 -1
- package/dashboard/dist/assets/{download-D1JugY5p.js → download-W7dmHuLF.js} +1 -1
- package/dashboard/dist/assets/{external-link-ow0tAluE.js → external-link-B-pvBbFP.js} +1 -1
- package/dashboard/dist/assets/{flame-Obus_5g4.js → flame-y6R5Plz2.js} +1 -1
- package/dashboard/dist/assets/{format-tokens-yToZ6yvw.js → format-tokens-CkWutEDc.js} +1 -1
- package/dashboard/dist/assets/{icons-Da1IxY6v.js → icons-C_ECRc6a.js} +1 -1
- package/dashboard/dist/assets/{index-0hD-aFe2.js → index-B1Am3t0P.js} +1 -1
- package/dashboard/dist/assets/{index-BtmxTdj8.js → index-BzmW4EmI.js} +1 -1
- package/dashboard/dist/assets/{index-DduY8rpi.js → index-Dtl4UhBX.js} +1 -1
- package/dashboard/dist/assets/{info-CQjQ1whr.js → info-CCfzQ-S6.js} +1 -1
- package/dashboard/dist/assets/{link-2-BGYfWbPb.js → link-2-DvFi_t5y.js} +1 -1
- package/dashboard/dist/assets/{loader-circle-WArW9cmn.js → loader-circle-BglSN88W.js} +1 -1
- package/dashboard/dist/assets/{maximize-2-Bhde1l0n.js → maximize-2-B7Nzrb8n.js} +1 -1
- package/dashboard/dist/assets/{modifiers.esm-BRxUZvoy.js → modifiers.esm-CsJhvsvC.js} +1 -1
- package/dashboard/dist/assets/{monitor-smartphone-2ZT8ACJS.js → monitor-smartphone-DpicOpX8.js} +1 -1
- package/dashboard/dist/assets/{plus-C_cg6gJE.js → plus-C40ubjK3.js} +1 -1
- package/dashboard/dist/assets/{provider-display-CM8dzzcI.js → provider-display-E2soZfeg.js} +2 -2
- package/dashboard/dist/assets/{react-C3vDx5Sr.js → react-BseCgHfW.js} +1 -1
- package/dashboard/dist/assets/{search-Vd9we7KU.js → search-Bu5sWW2G.js} +1 -1
- package/dashboard/dist/assets/{skills-api-CHxubvN1.js → skills-api-BBF6YhPQ.js} +1 -1
- package/dashboard/dist/assets/skins-Mc0sI20C.js +1 -0
- package/dashboard/dist/assets/{sortable.esm-rLR8Wj9r.js → sortable.esm-CLXvOgJi.js} +1 -1
- package/dashboard/dist/assets/{store-rdi5mnme.js → store-DdObzMvx.js} +1 -1
- package/dashboard/dist/assets/{terminal-xEPZhi6v.js → terminal-CRqmFLSX.js} +1 -1
- package/dashboard/dist/assets/{trash-Cad8nQc4.js → trash-Dknznc_u.js} +1 -1
- package/dashboard/dist/assets/{use-community-stats-SMq01IVW.js → use-community-stats-ZvEm6sF4.js} +1 -1
- package/dashboard/dist/assets/{use-latest-request-guard-CSQ3Ypu3.js → use-latest-request-guard-QHLPnnSW.js} +1 -1
- package/dashboard/dist/assets/{use-limits-display-prefs-DaaT6TL9.js → use-limits-display-prefs-CRg1sYpO.js} +1 -1
- package/dashboard/dist/assets/{use-ordered-list-g58JllvT.js → use-ordered-list-NpIo40Y4.js} +1 -1
- package/dashboard/dist/assets/use-pet-settings-BUroRCzh.js +2 -0
- package/dashboard/dist/assets/use-reduced-motion-CDg8lAbR.js +1 -0
- package/dashboard/dist/assets/{use-session-efficiency-pref-DyATLZ-L.js → use-session-efficiency-pref-aQVRBt9R.js} +1 -1
- package/dashboard/dist/assets/{use-transform-XYEzPgA-.js → use-transform-BP8NiCzk.js} +1 -1
- package/dashboard/dist/assets/use-usage-limits-CvIocz6v.js +1 -0
- package/dashboard/dist/assets/{useCurrency-4xq0xUFx.js → useCurrency-CyksuFrj.js} +1 -1
- package/dashboard/dist/assets/useTokenFormat-CUwCluPw.js +1 -0
- package/dashboard/dist/assets/{zap-InLQedtD.js → zap-BcWplbpF.js} +1 -1
- package/dashboard/dist/index.html +2 -2
- package/dashboard/dist/ip-check.html +2 -2
- package/dashboard/dist/leaderboard.html +2 -2
- package/dashboard/dist/share.html +2 -2
- package/package.json +3 -2
- package/src/commands/init.js +1 -1
- package/src/commands/sync.js +71 -34
- package/src/lib/claude-categorizer.js +4 -7
- package/src/lib/claude-user-identity.js +56 -0
- package/src/lib/cloud-sync-prefs.js +14 -0
- package/src/lib/cursor-store.js +636 -57
- package/src/lib/grok-limits.js +17 -4
- package/src/lib/kimi-profile.js +61 -0
- package/src/lib/local-api.js +17 -11
- package/src/lib/multi-install-parser.js +3 -1
- package/src/lib/pricing/seed-snapshot.json +1 -1
- package/src/lib/rollout.js +91 -39
- package/src/lib/usage-limits.js +128 -79
- package/dashboard/dist/assets/BotAnimated-srF64s63.js +0 -1
- package/dashboard/dist/assets/ClawdAnimated-C9a1u9lq.js +0 -2
- package/dashboard/dist/assets/Controls-D5XuFAlI.js +0 -1
- package/dashboard/dist/assets/DashboardPage-Ddb8k4DR.js +0 -1
- package/dashboard/dist/assets/DialogDescription-CaRzgdvP.js +0 -1
- package/dashboard/dist/assets/PetPage-DFaWnKsI.js +0 -1
- package/dashboard/dist/assets/SettingsPage-BmeQse01.js +0 -2
- package/dashboard/dist/assets/TrendMonitor-D3WafvUS.js +0 -19
- package/dashboard/dist/assets/__vite-browser-external-B98Yok9C.js +0 -45
- package/dashboard/dist/assets/__vite-browser-external-Bg0J-a5P.css +0 -1
- package/dashboard/dist/assets/skins-C8EyB85e.js +0 -1
- package/dashboard/dist/assets/use-reduced-motion-Dgdv5SSP.js +0 -1
- package/dashboard/dist/assets/use-usage-limits-DL260plD.js +0 -1
- package/dashboard/dist/assets/useTokenFormat-B6fHArH6.js +0 -1
package/src/lib/grok-limits.js
CHANGED
|
@@ -644,15 +644,28 @@ async function fetchGrokBilling(
|
|
|
644
644
|
headers,
|
|
645
645
|
deadlineMs,
|
|
646
646
|
);
|
|
647
|
-
if (creditsResult.ok)
|
|
648
|
-
|
|
647
|
+
if (creditsResult.ok) {
|
|
648
|
+
// Keep the unified pool even when its fields are malformed. The caller
|
|
649
|
+
// must surface its parse error rather than substitute a legacy pool.
|
|
650
|
+
if (creditsResult.body?.config?.currentPeriod) return creditsResult.body;
|
|
651
|
+
try {
|
|
652
|
+
// Only a response without a unified period is eligible for shape
|
|
653
|
+
// fallback; a parseable legacy response can already be used as-is.
|
|
654
|
+
normalizeGrokBillingResponse(creditsResult.body);
|
|
655
|
+
return creditsResult.body;
|
|
656
|
+
} catch (error) {
|
|
657
|
+
creditsFailure = `unrecognized response (${error?.message || "invalid billing data"})`;
|
|
658
|
+
}
|
|
659
|
+
} else {
|
|
660
|
+
creditsFailure = `HTTP ${creditsResult.status}`;
|
|
661
|
+
}
|
|
649
662
|
} catch (error) {
|
|
650
663
|
if (error?.code === "GROK_AUTH_REQUIRED") throw error;
|
|
651
664
|
if (error?.code === "GROK_BILLING_TIMEOUT") throw error;
|
|
652
665
|
}
|
|
653
666
|
|
|
654
|
-
// Non-auth HTTP, network,
|
|
655
|
-
// shape once, while sharing the original request deadline.
|
|
667
|
+
// Non-auth HTTP, network, response-decoding, or shape failure → try the
|
|
668
|
+
// legacy shape once, while sharing the original request deadline.
|
|
656
669
|
let legacyResult;
|
|
657
670
|
try {
|
|
658
671
|
legacyResult = await fetchGrokBillingAttempt(
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const fs = require("node:fs");
|
|
4
|
+
const os = require("node:os");
|
|
5
|
+
const path = require("node:path");
|
|
6
|
+
const { parse } = require("smol-toml");
|
|
7
|
+
const { expandHome } = require("./scan-roots");
|
|
8
|
+
|
|
9
|
+
const MAINLAND = { oauthHost: "https://auth.kimi.com", baseUrl: "https://api.kimi.com/coding/v1" };
|
|
10
|
+
const GLOBAL = { oauthHost: "https://auth.kimi.ai", baseUrl: "https://api.kimi.ai/coding/v1" };
|
|
11
|
+
|
|
12
|
+
function endpoint(value, fallback) {
|
|
13
|
+
return typeof value === "string" ? value.trim().replace(/\/+$/, "") : fallback;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// The two supported official endpoint pairs have stable upstream credential
|
|
17
|
+
// slots. The global suffix is SHA-256(JSON.stringify({ oauthHost, baseUrl }))
|
|
18
|
+
// truncated to 16 hex characters, matching managed-kimi-code.ts. Keeping the
|
|
19
|
+
// filenames constant also prevents remote configuration from shaping paths.
|
|
20
|
+
function credentialKey(oauthHost, baseUrl) {
|
|
21
|
+
return oauthHost === GLOBAL.oauthHost && baseUrl === GLOBAL.baseUrl
|
|
22
|
+
? "kimi-code-env-0e4f99c69cc27850" : "kimi-code";
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function resolveKimiProfile({ home, env = process.env } = {}) {
|
|
26
|
+
const base = home || os.homedir();
|
|
27
|
+
const explicit = expandHome(env?.KIMI_HOME, base);
|
|
28
|
+
const explicitCode = expandHome(env?.KIMI_CODE_HOME, base);
|
|
29
|
+
const codeHome = explicit || explicitCode || path.join(base, ".kimi-code");
|
|
30
|
+
const codeConfig = path.join(codeHome, "config.toml");
|
|
31
|
+
let provider = null;
|
|
32
|
+
let error = null;
|
|
33
|
+
if (fs.existsSync(codeConfig)) {
|
|
34
|
+
try {
|
|
35
|
+
provider = parse(fs.readFileSync(codeConfig, "utf8"))?.providers?.["managed:kimi-code"] || null;
|
|
36
|
+
} catch {
|
|
37
|
+
error = "Could not parse Kimi Code config.toml";
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
let hasCodeLogin = false;
|
|
41
|
+
try {
|
|
42
|
+
hasCodeLogin = Boolean(JSON.parse(fs.readFileSync(path.join(codeHome, "credentials", "kimi-code.json"), "utf8"))?.access_token);
|
|
43
|
+
} catch { /* No default-slot login. */ }
|
|
44
|
+
const hasEnvOverride = env?.KIMI_CODE_BASE_URL != null || env?.KIMI_CODE_OAUTH_HOST != null || env?.KIMI_OAUTH_HOST != null;
|
|
45
|
+
const kimiHome = explicit || explicitCode || provider || error || hasCodeLogin || hasEnvOverride
|
|
46
|
+
? codeHome : path.join(base, ".kimi");
|
|
47
|
+
const oauthHost = endpoint(hasEnvOverride ? env?.KIMI_CODE_OAUTH_HOST ?? env?.KIMI_OAUTH_HOST : provider?.oauth?.oauth_host, MAINLAND.oauthHost);
|
|
48
|
+
const baseUrl = endpoint(env?.KIMI_CODE_BASE_URL ?? provider?.base_url, MAINLAND.baseUrl);
|
|
49
|
+
if (![MAINLAND, GLOBAL].some((region) => region.oauthHost === oauthHost && region.baseUrl === baseUrl)) {
|
|
50
|
+
error = "Unsupported Kimi quota endpoints; configure a matching official mainland or global profile";
|
|
51
|
+
}
|
|
52
|
+
if (provider?.oauth?.storage && provider.oauth.storage !== "file") {
|
|
53
|
+
error = "Kimi quota supports file credentials; the configured credential storage is unsupported";
|
|
54
|
+
}
|
|
55
|
+
// Derive the endpoint-scoped slot, just as upstream does when a stored key
|
|
56
|
+
// mismatches the endpoints. Never read an unrelated slot or legacy login.
|
|
57
|
+
const credsPath = path.join(kimiHome, "credentials", `${credentialKey(oauthHost, baseUrl)}.json`);
|
|
58
|
+
return { home: kimiHome, credsPath, oauthHost, baseUrl, error, configured: fs.existsSync(path.join(kimiHome, "config.toml")) };
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
module.exports = { resolveKimiProfile };
|
package/src/lib/local-api.js
CHANGED
|
@@ -1357,23 +1357,25 @@ function createLocalApiHandler({ queuePath, serverVersion = null }) {
|
|
|
1357
1357
|
// sync is on. Cloud sync is a dashboard (WebView) preference persisted in
|
|
1358
1358
|
// localStorage; the dashboard mirrors it here via POST
|
|
1359
1359
|
// /functions/tokentracker-cloud-sync-pref so the auth-unaware popover can key
|
|
1360
|
-
// off the same flag. Defaults
|
|
1361
|
-
//
|
|
1362
|
-
// takes effect for signed-in users; an explicit {enabled:false} still wins.
|
|
1360
|
+
// off the same flag. Defaults OFF, exactly like the dashboard toggle;
|
|
1361
|
+
// existing saved choices are preserved.
|
|
1363
1362
|
const cloudSyncPrefPath = path.join(trackerDataDir, "cloud-sync-pref.json");
|
|
1364
1363
|
let cloudSyncPrefCache;
|
|
1365
1364
|
let cloudSyncPrefGeneration = 0;
|
|
1366
1365
|
function getCloudSyncPref() {
|
|
1367
1366
|
if (cloudSyncPrefCache === undefined) {
|
|
1368
|
-
|
|
1369
|
-
cloudSyncPrefCache = JSON.parse(fs.readFileSync(cloudSyncPrefPath, "utf8"))?.enabled !== false;
|
|
1370
|
-
} catch {
|
|
1371
|
-
cloudSyncPrefCache = true;
|
|
1372
|
-
}
|
|
1367
|
+
cloudSyncPrefCache = require("./cloud-sync-prefs").readCloudSyncEnabled(trackerDataDir);
|
|
1373
1368
|
}
|
|
1374
1369
|
return cloudSyncPrefCache;
|
|
1375
1370
|
}
|
|
1376
|
-
function setCloudSyncPref(enabled) {
|
|
1371
|
+
function setCloudSyncPref(enabled, changedAtMs = Date.now()) {
|
|
1372
|
+
// Multiple dashboard windows can deliver mirrors out of order. Keep the
|
|
1373
|
+
// newest saved choice; old files without an ordering marker remain valid.
|
|
1374
|
+
try {
|
|
1375
|
+
const saved = JSON.parse(fs.readFileSync(cloudSyncPrefPath, "utf8"));
|
|
1376
|
+
if (Number(saved?.changedAtMs || 0) > changedAtMs ||
|
|
1377
|
+
(changedAtMs > 0 && saved?.changedAtMs === changedAtMs && saved?.enabled === false && enabled)) return;
|
|
1378
|
+
} catch { /* first choice or an unreadable preference */ }
|
|
1377
1379
|
if (getCloudSyncPref() !== Boolean(enabled)) {
|
|
1378
1380
|
cloudSyncPrefGeneration += 1;
|
|
1379
1381
|
clearLocalSyncDeviceTokenCache();
|
|
@@ -1384,7 +1386,7 @@ function createLocalApiHandler({ queuePath, serverVersion = null }) {
|
|
|
1384
1386
|
if (!fs.existsSync(trackerDataDir)) fs.mkdirSync(trackerDataDir, { recursive: true });
|
|
1385
1387
|
fs.writeFileSync(
|
|
1386
1388
|
cloudSyncPrefPath,
|
|
1387
|
-
JSON.stringify({ enabled: cloudSyncPrefCache, updatedAt: new Date().toISOString() }),
|
|
1389
|
+
JSON.stringify({ enabled: cloudSyncPrefCache, changedAtMs, updatedAt: new Date().toISOString() }),
|
|
1388
1390
|
{ encoding: "utf8", mode: 0o600 },
|
|
1389
1391
|
);
|
|
1390
1392
|
} catch (e) {
|
|
@@ -2875,7 +2877,11 @@ function createLocalApiHandler({ queuePath, serverVersion = null }) {
|
|
|
2875
2877
|
json(res, { ok: false, error: "enabled must be a boolean" }, 400);
|
|
2876
2878
|
return true;
|
|
2877
2879
|
}
|
|
2878
|
-
|
|
2880
|
+
if (body.changedAtMs != null && (!Number.isSafeInteger(body.changedAtMs) || body.changedAtMs < 0)) {
|
|
2881
|
+
json(res, { ok: false, error: "changedAtMs must be a nonnegative safe integer" }, 400);
|
|
2882
|
+
return true;
|
|
2883
|
+
}
|
|
2884
|
+
setCloudSyncPref(body.enabled, body.changedAtMs ?? Date.now());
|
|
2879
2885
|
json(res, { ok: true, enabled: getCloudSyncPref() });
|
|
2880
2886
|
return true;
|
|
2881
2887
|
}
|
|
@@ -47,7 +47,9 @@ async function multiInstallParse({ paths, parserFn, providerName, cursors, getPa
|
|
|
47
47
|
eventsAggregated += result.eventsAggregated || 0;
|
|
48
48
|
bucketsQueued += result.bucketsQueued || 0;
|
|
49
49
|
} catch (parseErr) {
|
|
50
|
-
|
|
50
|
+
if (parseErr?.code !== "TOKENTRACKER_CURSOR_STORE_RETRY") {
|
|
51
|
+
cursors[providerName] = ns;
|
|
52
|
+
}
|
|
51
53
|
throw parseErr;
|
|
52
54
|
}
|
|
53
55
|
}
|