tokentracker-cli 1.3.16 → 1.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.de.md +5 -4
- package/README.ja.md +5 -4
- package/README.ko.md +5 -4
- package/README.md +5 -4
- package/README.zh-CN.md +5 -4
- package/dashboard/dist/assets/{AchievementBadge-D5sRTMmp.js → AchievementBadge-WGbdoboF.js} +1 -1
- package/dashboard/dist/assets/{AchievementsPage-CaiCfchd.js → AchievementsPage-BvybbsXv.js} +2 -2
- package/dashboard/dist/assets/{AchievementsSection-D6dTxdUd.js → AchievementsSection-ChNzTFSR.js} +1 -1
- package/dashboard/dist/assets/{BadgeDetailModal-C0UrWb9m.js → BadgeDetailModal-DhI9Ejz3.js} +1 -1
- package/dashboard/dist/assets/{BotAnimated-CgpBB5FZ.js → BotAnimated-Bch0Yxej.js} +1 -1
- package/dashboard/dist/assets/{Card-CuwBiIYz.js → Card-DWdL7d1T.js} +1 -1
- package/dashboard/dist/assets/{CloudCheckoutPage-BNCnBR0h.js → CloudCheckoutPage-BjGoOz6P.js} +1 -1
- package/dashboard/dist/assets/{CloudPage-CuYXUQnv.js → CloudPage-Btb6a97x.js} +2 -2
- package/dashboard/dist/assets/{CommandPalette-CV6a_7yK.js → CommandPalette-DwP3k7LE.js} +1 -1
- package/dashboard/dist/assets/{CommunityStatsModal-Dw-64Tig.js → CommunityStatsModal-mzqLxpwE.js} +1 -1
- package/dashboard/dist/assets/{ConfirmModal-CoFO1Nas.js → ConfirmModal-Dm76q4EX.js} +1 -1
- package/dashboard/dist/assets/{Controls-DB9eQ_rg.js → Controls-ClZjOBoD.js} +1 -1
- package/dashboard/dist/assets/DashboardPage-Doc8f4NL.js +1 -0
- package/dashboard/dist/assets/{DateRangePopover-DgZEnn4X.js → DateRangePopover-vfTUePPg.js} +1 -1
- package/dashboard/dist/assets/DevicePage-Jjg5q0C2.js +1 -0
- package/dashboard/dist/assets/{DialogClose-BR9QrB34.js → DialogClose-Ci5mPZ6X.js} +1 -1
- package/dashboard/dist/assets/DialogDescription-Di5ev5K6.js +1 -0
- package/dashboard/dist/assets/DialogTitle-DI21oZxH.js +1 -0
- package/dashboard/dist/assets/{ElectricLogo-nrlBy-l9.js → ElectricLogo-DfeZBwPZ.js} +1 -1
- package/dashboard/dist/assets/{FadeIn-CyJJ3l_P.js → FadeIn-C7SIILTc.js} +1 -1
- package/dashboard/dist/assets/{HeaderGithubStar-C7BX7loS.js → HeaderGithubStar-RStLbadn.js} +1 -1
- package/dashboard/dist/assets/{HoverTooltip-KGluh6sO.js → HoverTooltip-DI7uAp1_.js} +1 -1
- package/dashboard/dist/assets/{IpCheckPage-Ci2ybTDg.js → IpCheckPage-DTZNTJVh.js} +1 -1
- package/dashboard/dist/assets/{LandingPage-C9N17IpV.js → LandingPage-Df5scNlw.js} +2 -2
- package/dashboard/dist/assets/{LeaderboardPage-Cco7iFen.js → LeaderboardPage-Ck3SqtnI.js} +2 -2
- package/dashboard/dist/assets/{LeaderboardProBadge-tmm5NN8p.js → LeaderboardProBadge-CGx6m7R6.js} +1 -1
- package/dashboard/dist/assets/{LeaderboardProfileModal-WhjsvZ9Q.js → LeaderboardProfileModal-DuP7rgfv.js} +3 -3
- package/dashboard/dist/assets/{LeaderboardProfilePage-Ba3oVu5z.js → LeaderboardProfilePage-B5qUJkZX.js} +1 -1
- package/dashboard/dist/assets/{LimitsPage-CUa46XJy.js → LimitsPage-Bv_Lcvcz.js} +1 -1
- package/dashboard/dist/assets/{LocalOnlyNotice-BSewrWlY.js → LocalOnlyNotice-Cg4y02JM.js} +1 -1
- package/dashboard/dist/assets/{LoginCard-CUWn0Tz4.js → LoginCard-Wz0uJKXx.js} +1 -1
- package/dashboard/dist/assets/{LoginModal-UKk3xCsV.js → LoginModal-C13v_Gs0.js} +1 -1
- package/dashboard/dist/assets/{LoginPage-BhxiWgc5.js → LoginPage-COH9xXtd.js} +1 -1
- package/dashboard/dist/assets/{PetPage-BRyxC-Iu.js → PetPage-BWCnURub.js} +2 -2
- package/dashboard/dist/assets/PopoverPopup-Dw811N-_.js +1 -0
- package/dashboard/dist/assets/{ProviderIcon-htNu1RTN.js → ProviderIcon-CHxhYzK-.js} +1 -1
- package/dashboard/dist/assets/{ResetPasswordPage-DawMNiM1.js → ResetPasswordPage-Ll6jshqg.js} +1 -1
- package/dashboard/dist/assets/Select-BbooQ3sa.js +1 -0
- package/dashboard/dist/assets/SelectItemText-DBiW70wi.js +1 -0
- package/dashboard/dist/assets/{SelfHostPage-BMCMrt5I.js → SelfHostPage-BMHJxz5q.js} +1 -1
- package/dashboard/dist/assets/{ServiceStatusPage-e_7xC0RY.js → ServiceStatusPage-D6LH0ac-.js} +1 -1
- package/dashboard/dist/assets/{SessionsPage-Xr2FJa6E.js → SessionsPage-Mrer6v17.js} +2 -2
- package/dashboard/dist/assets/SettingsPage-D_7P_y_l.js +5 -0
- package/dashboard/dist/assets/SkillsPage-Ka7xm-1v.js +1 -0
- package/dashboard/dist/assets/{TokenGalaxy--6ijNK6P.js → TokenGalaxy-BEURDPFq.js} +1 -1
- package/dashboard/dist/assets/TooltipPopup-ZiuFFARC.js +1 -0
- package/dashboard/dist/assets/{TrendMonitor-DjIZyzxp.js → TrendMonitor-H73lyGEf.js} +1 -1
- package/dashboard/dist/assets/{WidgetsPage-CzCqGbb4.js → WidgetsPage-_7iCvyTk.js} +1 -1
- package/dashboard/dist/assets/{WrappedPage-B0RMtpvr.js → WrappedPage-DEXNb6-k.js} +1 -1
- package/dashboard/dist/assets/__vite-browser-external-BkNP5Ecj.js +45 -0
- package/dashboard/dist/assets/{agent-logos-CSlyeabY.js → agent-logos-OVBc_0cF.js} +1 -1
- package/dashboard/dist/assets/{arrow-left-DaqMiXTO.js → arrow-left-DDphsclm.js} +1 -1
- package/dashboard/dist/assets/{arrow-right-B1p9R8vH.js → arrow-right-B1aNq0Ki.js} +1 -1
- package/dashboard/dist/assets/{arrow-up-right-CK_9HuEh.js → arrow-up-right-yTM9azz_.js} +1 -1
- package/dashboard/dist/assets/{calendar-days-BVyCx4dJ.js → calendar-days-D22ithNF.js} +1 -1
- package/dashboard/dist/assets/{check-DIfCVsPJ.js → check-Dk7tknvE.js} +1 -1
- package/dashboard/dist/assets/{chevron-down-DrWxRBXX.js → chevron-down-DdyEzQ4f.js} +1 -1
- package/dashboard/dist/assets/{cloud-checkout-DOxBG7oS.js → cloud-checkout-BJjbipnH.js} +1 -1
- package/dashboard/dist/assets/composite-DEqP00XV.js +1 -0
- package/dashboard/dist/assets/{download-CEXAmejX.js → download-C9ixNyzn.js} +1 -1
- package/dashboard/dist/assets/{external-link-tDBZy6QP.js → external-link-DL4HSsLw.js} +1 -1
- package/dashboard/dist/assets/{flame-86y9Xf0g.js → flame-DqNH65nB.js} +1 -1
- package/dashboard/dist/assets/{format-tokens-BNN9k5mV.js → format-tokens-CyVjKz4I.js} +1 -1
- package/dashboard/dist/assets/{gift-BEOvq2zc.js → gift-ChJQQe_G.js} +1 -1
- package/dashboard/dist/assets/{host-mode-UjbNKxFB.js → host-mode-DpUDpoOz.js} +1 -1
- package/dashboard/dist/assets/{icons-DJmZD0si.js → icons-CJiHeOaU.js} +1 -1
- package/dashboard/dist/assets/{index-BwUwnqE0.js → index-72LQsAaf.js} +1 -1
- package/dashboard/dist/assets/{index-B8kizz-s.js → index-BucEg3fu.js} +1 -1
- package/dashboard/dist/assets/{index-Ci3CZ-2g.js → index-CrFlTSra.js} +1 -1
- package/dashboard/dist/assets/{info-ynVg8RzK.js → info-DReYqxC7.js} +1 -1
- package/dashboard/dist/assets/{link-2-B9SLPcBg.js → link-2-kIZbhK2S.js} +1 -1
- package/dashboard/dist/assets/{loader-circle-FTE9k7Sk.js → loader-circle-1An-X85y.js} +1 -1
- package/dashboard/dist/assets/{modifiers.esm-B4babCm_.js → modifiers.esm-FoVheEKT.js} +1 -1
- package/dashboard/dist/assets/module-DOCYJaxl.js +3 -0
- package/dashboard/dist/assets/{monitor-smartphone-CNzgbo-M.js → monitor-smartphone-Ch6lr_P2.js} +1 -1
- package/dashboard/dist/assets/{play-9W4Ua21o.js → play-CbJ6ZF1K.js} +1 -1
- package/dashboard/dist/assets/{plus-BA85lApI.js → plus-C-5ID3a9.js} +1 -1
- package/dashboard/dist/assets/{provider-display-D1ETarsz.js → provider-display-BFzRtoL2.js} +2 -2
- package/dashboard/dist/assets/{react-VsHxeqq7.js → react-D4CR_fLQ.js} +1 -1
- package/dashboard/dist/assets/safePolygon-DP21Ibqj.js +1 -0
- package/dashboard/dist/assets/{search-Svi--7CN.js → search-CaznkY7U.js} +1 -1
- package/dashboard/dist/assets/{server-CgHdX6TE.js → server-CUOmC6xZ.js} +1 -1
- package/dashboard/dist/assets/{shield-check-Cjv-T4aT.js → shield-check-Dr2KBMmA.js} +1 -1
- package/dashboard/dist/assets/{skills-api-Cn8hEYL4.js → skills-api-BAz_fblS.js} +1 -1
- package/dashboard/dist/assets/{sortable.esm-g3UcmvFU.js → sortable.esm-knEfm5hE.js} +1 -1
- package/dashboard/dist/assets/store-CL97jcij.js +1 -0
- package/dashboard/dist/assets/{terminal-o0jvDfI0.js → terminal-EjFyreWj.js} +1 -1
- package/dashboard/dist/assets/{trash-0cqpTyN6.js → trash-ByqaZXkQ.js} +1 -1
- package/dashboard/dist/assets/{use-community-stats-BFgORaJS.js → use-community-stats-Bs4RDJZE.js} +1 -1
- package/dashboard/dist/assets/{use-latest-request-guard-9eZP_jA5.js → use-latest-request-guard-CG3Ir1cP.js} +1 -1
- package/dashboard/dist/assets/{use-limits-display-prefs-BjO3hsmw.js → use-limits-display-prefs-tACgCxeR.js} +1 -1
- package/dashboard/dist/assets/{use-native-settings-YKn-htVo.js → use-native-settings-CWjXyJXi.js} +1 -1
- package/dashboard/dist/assets/{use-ordered-list-D5h4UwhF.js → use-ordered-list-DsuC9JQa.js} +1 -1
- package/dashboard/dist/assets/use-reduced-motion-CwFguzkm.js +1 -0
- package/dashboard/dist/assets/{use-session-efficiency-pref-BShLuIbk.js → use-session-efficiency-pref-NeoJE8BL.js} +1 -1
- package/dashboard/dist/assets/{use-transform-DVZHJPVD.js → use-transform-BWGKOsya.js} +1 -1
- package/dashboard/dist/assets/{use-usage-limits-BhJbW76K.js → use-usage-limits-CFWFNwHS.js} +1 -1
- package/dashboard/dist/assets/{useCurrency-BmEbDVaa.js → useCurrency-B_C4_P5x.js} +1 -1
- package/dashboard/dist/assets/usePositioner-B0L5_o38.js +1 -0
- package/dashboard/dist/assets/{useTokenFormat-CBlBP2aA.js → useTokenFormat-DH1GWHSU.js} +1 -1
- package/dashboard/dist/assets/{zap-cML2-Nx4.js → zap-Chv1p7pS.js} +1 -1
- 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 +3 -3
- package/src/commands/doctor.js +15 -1
- package/src/commands/init.js +9 -0
- package/src/commands/status.js +21 -3
- package/src/commands/sync.js +59 -4
- package/src/lib/cloud-device-token.js +77 -10
- package/src/lib/cloud-usage-reset.js +115 -0
- package/src/lib/diagnostics.js +5 -2
- package/src/lib/kimi-model-repair.js +173 -0
- package/src/lib/kimi-session.js +216 -0
- package/src/lib/local-api.js +46 -1
- package/src/lib/pricing/index.js +2 -1
- package/src/lib/pricing/seed-snapshot.json +1 -1
- package/src/lib/qoder-cn-cli-limits.js +9 -7
- package/src/lib/qoder-limits.js +45 -15
- package/src/lib/rollout.js +408 -4
- package/src/lib/session-analytics.js +47 -9
- package/dashboard/dist/assets/DashboardPage-sZKijU6h.js +0 -1
- package/dashboard/dist/assets/DevicePage-YCnJnsmz.js +0 -1
- package/dashboard/dist/assets/DialogDescription-Cx1R3WT7.js +0 -1
- package/dashboard/dist/assets/DialogTitle-ck8f1qeP.js +0 -1
- package/dashboard/dist/assets/PopoverPopup-D-Tpl294.js +0 -1
- package/dashboard/dist/assets/Select-6WChWtqK.js +0 -1
- package/dashboard/dist/assets/SelectItemText-DRmxMwo5.js +0 -1
- package/dashboard/dist/assets/SettingsPage-Bxq2Mhxz.js +0 -5
- package/dashboard/dist/assets/SkillsPage-CEIBW63c.js +0 -1
- package/dashboard/dist/assets/TooltipPopup--TLYUg0c.js +0 -1
- package/dashboard/dist/assets/__vite-browser-external-BsOjTB8Q.js +0 -45
- package/dashboard/dist/assets/composite-W1R1XwoE.js +0 -1
- package/dashboard/dist/assets/module-BNnaKM__.js +0 -3
- package/dashboard/dist/assets/safePolygon-CCDOsx-z.js +0 -1
- package/dashboard/dist/assets/store-D2gn9bSV.js +0 -1
- package/dashboard/dist/assets/use-reduced-motion-C83gmg0F.js +0 -1
- package/dashboard/dist/assets/usePositioner-nY0YNa-6.js +0 -1
|
@@ -37,6 +37,7 @@ const { resolveZcodeNativeDbPath, resolveInstallPaths } = require("./install-res
|
|
|
37
37
|
const { readCursorStateSummary } = require("./cursor-store");
|
|
38
38
|
const { USD_TICKS_PER_USD, normalizeGrokUsage } = require("./grok-usage");
|
|
39
39
|
const wsl = require("./wsl-probe");
|
|
40
|
+
const { discoverKimiWireFiles, kimiSessionDependencies, readKimiSessions } = require("./kimi-session");
|
|
40
41
|
const {
|
|
41
42
|
appendUniqueDirs,
|
|
42
43
|
dedupeDirsByRealpath,
|
|
@@ -85,7 +86,8 @@ const {
|
|
|
85
86
|
// v22 adds metadata-only OpenCode database sessions.
|
|
86
87
|
// v23 excludes database updates and user records from request durations.
|
|
87
88
|
// v24 keeps OpenCode usage dates at event time and fork history on its ancestor.
|
|
88
|
-
|
|
89
|
+
// v25 adds Kimi wire sessions, including official/legacy migration dedup.
|
|
90
|
+
const SIDECAR_VERSION = 25;
|
|
89
91
|
const EDIT_TOOLS = new Set([
|
|
90
92
|
"apply_patch",
|
|
91
93
|
"edit",
|
|
@@ -1925,6 +1927,14 @@ function groupCodexFiles(filePaths) {
|
|
|
1925
1927
|
return ordered;
|
|
1926
1928
|
}
|
|
1927
1929
|
|
|
1930
|
+
async function scanKimiSessions(filePaths) {
|
|
1931
|
+
const rows = await readKimiSessions(Array.isArray(filePaths) ? filePaths : [filePaths]);
|
|
1932
|
+
return rows.map(({ identity, files, ...row }) => finalizeRecord({
|
|
1933
|
+
...row, version: SIDECAR_VERSION, source: "kimi", session_hash: sessionHash("kimi", identity),
|
|
1934
|
+
project_key: projectKey(row.project_ref, files[0]), ...sessionStorageUsage(files),
|
|
1935
|
+
}));
|
|
1936
|
+
}
|
|
1937
|
+
|
|
1928
1938
|
async function discoverSessionFiles(home, env = process.env, deps = {}) {
|
|
1929
1939
|
const grokHome = resolveGrokHome(home);
|
|
1930
1940
|
// config.scanRoots (#657): read from the tracker config unless the caller
|
|
@@ -2007,7 +2017,17 @@ async function discoverSessionFiles(home, env = process.env, deps = {}) {
|
|
|
2007
2017
|
const opencodePaths = resolveInstallPaths({ nativeValue: opencodeNativeDir, wslValue: opencodeWslDir }, env, { platform: zcodePlatform });
|
|
2008
2018
|
const opencode = [...new Set(Object.values(opencodePaths).filter(Boolean)
|
|
2009
2019
|
.map((dir) => path.join(dir, "opencode.db")).filter((dbPath) => fs.existsSync(dbPath)))];
|
|
2010
|
-
|
|
2020
|
+
const kimiRoots = [".kimi", ".kimi-code"].flatMap((directory) => {
|
|
2021
|
+
const roots = providerRoots(home, directory, env, deps);
|
|
2022
|
+
const override = env[directory === ".kimi" ? "KIMI_HOME" : "KIMI_CODE_HOME"];
|
|
2023
|
+
if (override && path.resolve(home) === path.resolve((deps.homedir || os.homedir)())) {
|
|
2024
|
+
const native = path.join(home, directory);
|
|
2025
|
+
return roots.map((root) => root === native ? expandHome(override, home) : root);
|
|
2026
|
+
}
|
|
2027
|
+
return roots;
|
|
2028
|
+
});
|
|
2029
|
+
const kimi = discoverKimiWireFiles(dedupeDirsByRealpath(kimiRoots), incomplete);
|
|
2030
|
+
return { claude, codex: groupCodexFiles([...codex, ...archived]), grok, zcode, opencode, kimi, incomplete };
|
|
2011
2031
|
}
|
|
2012
2032
|
|
|
2013
2033
|
// Warn once per unreadable directory per process: the dashboard polls this
|
|
@@ -2108,6 +2128,9 @@ function analyticsEntryStatKey(source, filePath) {
|
|
|
2108
2128
|
));
|
|
2109
2129
|
return `${sessionStat}|title-index:${titleStats.join("|")}`;
|
|
2110
2130
|
}
|
|
2131
|
+
if (source === "kimi") {
|
|
2132
|
+
return `${sessionStat}|metadata:${filesSignature(kimiSessionDependencies(filePaths))}`;
|
|
2133
|
+
}
|
|
2111
2134
|
if (source === "grok") {
|
|
2112
2135
|
const primary = filePaths[0];
|
|
2113
2136
|
return `${sessionStat}|summary:${sessionFileStatKey(grokSummaryPathFor(primary)) || "missing"}|signals:${sessionFileStatKey(grokSignalsPathFor(primary)) || "missing"}`;
|
|
@@ -2147,13 +2170,15 @@ async function buildSessionAnalyticsInternal({ home = os.homedir(), force = fals
|
|
|
2147
2170
|
const retryZcodeScan = fs.existsSync(incompleteZcodePath);
|
|
2148
2171
|
const incompleteOpencodePath = `${metaPath}.opencode-incomplete`;
|
|
2149
2172
|
const retryOpencodeScan = fs.existsSync(incompleteOpencodePath);
|
|
2173
|
+
const incompleteKimiPath = `${metaPath}.kimi-incomplete`;
|
|
2174
|
+
const retryKimiScan = fs.existsSync(incompleteKimiPath);
|
|
2150
2175
|
let previousMeta = null;
|
|
2151
2176
|
if (!force) {
|
|
2152
2177
|
try {
|
|
2153
2178
|
previousMeta = JSON.parse(fs.readFileSync(metaPath, "utf8"));
|
|
2154
2179
|
const checkedAt = Date.parse(previousMeta.checked_at || previousMeta.generated_at || "");
|
|
2155
2180
|
if (
|
|
2156
|
-
!retryZcodeScan && !retryOpencodeScan && previousMeta.version === SIDECAR_VERSION &&
|
|
2181
|
+
!retryZcodeScan && !retryOpencodeScan && !retryKimiScan && previousMeta.version === SIDECAR_VERSION &&
|
|
2157
2182
|
Number.isFinite(checkedAt) &&
|
|
2158
2183
|
Date.now() - checkedAt < Math.max(0, Number(cacheTtlMs) || 0)
|
|
2159
2184
|
) {
|
|
@@ -2183,13 +2208,15 @@ async function buildSessionAnalyticsInternal({ home = os.homedir(), force = fals
|
|
|
2183
2208
|
...discovered.claude.flat(),
|
|
2184
2209
|
...discovered.codex.flat(),
|
|
2185
2210
|
...discovered.codex.flat().map(codexTitleIndexPathFor).filter(Boolean),
|
|
2211
|
+
...discovered.kimi,
|
|
2212
|
+
...kimiSessionDependencies(discovered.kimi),
|
|
2186
2213
|
...discovered.grok,
|
|
2187
2214
|
...discovered.grok.map(grokSummaryPathFor),
|
|
2188
2215
|
...discovered.grok.map(grokSignalsPathFor),
|
|
2189
2216
|
// db + its WAL sidecars: the trio is one logical file for change detection.
|
|
2190
2217
|
...[...(discovered.zcode || []), ...(discovered.opencode || [])].flatMap((dbPath) => [dbPath, `${dbPath}-wal`, `${dbPath}-shm`]),
|
|
2191
2218
|
]);
|
|
2192
|
-
if (!force && !retryZcodeScan && !retryOpencodeScan && previousMeta?.version === SIDECAR_VERSION && previousMeta.signature === signature) {
|
|
2219
|
+
if (!force && !retryZcodeScan && !retryOpencodeScan && !retryKimiScan && previousMeta?.version === SIDECAR_VERSION && previousMeta.signature === signature) {
|
|
2193
2220
|
await writeAtomic(metaPath, `${JSON.stringify({ ...previousMeta, checked_at: new Date().toISOString() })}\n`);
|
|
2194
2221
|
return readSidecar(sidecarPath);
|
|
2195
2222
|
}
|
|
@@ -2211,6 +2238,7 @@ async function buildSessionAnalyticsInternal({ home = os.homedir(), force = fals
|
|
|
2211
2238
|
...discovered.grok.map((filePath) => ({ source: "grok", filePath, scan: scanGrokSession })),
|
|
2212
2239
|
...(discovered.zcode.length ? [{ source: "zcode", filePath: discovered.zcode, scan: scanZcodeSessions }] : []),
|
|
2213
2240
|
...(discovered.opencode.length ? [{ source: "opencode", filePath: discovered.opencode, scan: scanOpencodeSessions }] : []),
|
|
2241
|
+
...(discovered.kimi.length ? [{ source: "kimi", filePath: discovered.kimi, scan: scanKimiSessions }] : []),
|
|
2214
2242
|
];
|
|
2215
2243
|
// Files we could not turn into a row (permission denied, half-written line,
|
|
2216
2244
|
// vanished mid-scan). Swallowing these silently made sessions disappear with
|
|
@@ -2218,6 +2246,7 @@ async function buildSessionAnalyticsInternal({ home = os.homedir(), force = fals
|
|
|
2218
2246
|
let skippedFiles = 0;
|
|
2219
2247
|
let incompleteZcodeScan = false;
|
|
2220
2248
|
let incompleteOpencodeScan = false;
|
|
2249
|
+
let incompleteKimiScan = false;
|
|
2221
2250
|
for (const entry of entries) {
|
|
2222
2251
|
const cacheKey = sessionFileCacheKey(entry.source, entry.filePath);
|
|
2223
2252
|
const statKey = analyticsEntryStatKey(entry.source, entry.filePath);
|
|
@@ -2225,11 +2254,12 @@ async function buildSessionAnalyticsInternal({ home = os.homedir(), force = fals
|
|
|
2225
2254
|
skippedFiles += 1;
|
|
2226
2255
|
if (entry.source === "zcode") incompleteZcodeScan = true;
|
|
2227
2256
|
if (entry.source === "opencode") incompleteOpencodeScan = true;
|
|
2257
|
+
if (entry.source === "kimi") incompleteKimiScan = true;
|
|
2228
2258
|
continue;
|
|
2229
2259
|
}
|
|
2230
2260
|
let rows = null;
|
|
2231
|
-
if (!force && !(entry.source === "zcode" && retryZcodeScan) && !(entry.source === "opencode" && retryOpencodeScan) && previousFiles[cacheKey]?.stat_key === statKey) {
|
|
2232
|
-
if (entry.source === "zcode" || entry.source === "opencode") {
|
|
2261
|
+
if (!force && !(entry.source === "zcode" && retryZcodeScan) && !(entry.source === "opencode" && retryOpencodeScan) && !(entry.source === "kimi" && retryKimiScan) && previousFiles[cacheKey]?.stat_key === statKey) {
|
|
2262
|
+
if (entry.source === "zcode" || entry.source === "opencode" || entry.source === "kimi") {
|
|
2233
2263
|
// One db scans to many cached rows; recover them all from the previous
|
|
2234
2264
|
// pass. An empty recovery means the sidecar lost its rows — rescan.
|
|
2235
2265
|
const cached = previousRows.filter((row) => row?.source === entry.source);
|
|
@@ -2249,6 +2279,7 @@ async function buildSessionAnalyticsInternal({ home = os.homedir(), force = fals
|
|
|
2249
2279
|
skippedFiles += 1;
|
|
2250
2280
|
if (entry.source === "zcode") incompleteZcodeScan = true;
|
|
2251
2281
|
if (entry.source === "opencode") incompleteOpencodeScan = true;
|
|
2282
|
+
if (entry.source === "kimi") incompleteKimiScan = true;
|
|
2252
2283
|
if (!process.env.NODE_TEST_CONTEXT) {
|
|
2253
2284
|
console.warn(`[session-analytics] skipped ${entry.source} session file: ${error?.message || error}`);
|
|
2254
2285
|
}
|
|
@@ -2262,8 +2293,8 @@ async function buildSessionAnalyticsInternal({ home = os.homedir(), force = fals
|
|
|
2262
2293
|
// so key each by the db path plus its session id; a bare session id as a
|
|
2263
2294
|
// separate path element would be path.resolve()d against the process cwd
|
|
2264
2295
|
// and never match across runs.
|
|
2265
|
-
row._cache_key = (entry.source === "zcode" || entry.source === "opencode") && row.session_id
|
|
2266
|
-
? `${cacheKey}#${sessionHash(entry.source, row.session_id)}`
|
|
2296
|
+
row._cache_key = (entry.source === "zcode" || entry.source === "opencode" || entry.source === "kimi") && (row.session_id || row.session_hash)
|
|
2297
|
+
? `${cacheKey}#${sessionHash(entry.source, row.session_id || row.session_hash)}`
|
|
2267
2298
|
: cacheKey;
|
|
2268
2299
|
sessions.push(row);
|
|
2269
2300
|
}
|
|
@@ -2282,10 +2313,14 @@ async function buildSessionAnalyticsInternal({ home = os.homedir(), force = fals
|
|
|
2282
2313
|
sessions.push(...readSidecar(sidecarPath).filter((row) =>
|
|
2283
2314
|
row.source === "opencode" && row.version === SIDECAR_VERSION));
|
|
2284
2315
|
}
|
|
2316
|
+
if (incompleteKimiScan) {
|
|
2317
|
+
await writeAtomic(incompleteKimiPath, "1\n");
|
|
2318
|
+
sessions.push(...readSidecar(sidecarPath).filter((row) => row.source === "kimi" && row.version === SIDECAR_VERSION));
|
|
2319
|
+
}
|
|
2285
2320
|
sessions.sort((a, b) => String(b.ended_at || "").localeCompare(String(a.ended_at || "")));
|
|
2286
2321
|
// A failed database scan is an incomplete inventory. Keep the last complete
|
|
2287
2322
|
// snapshot and signature so an unchanged database is retried next build.
|
|
2288
|
-
if (incompleteDirs.length === 0 && !incompleteZcodeScan && !incompleteOpencodeScan) {
|
|
2323
|
+
if (incompleteDirs.length === 0 && !incompleteZcodeScan && !incompleteOpencodeScan && !incompleteKimiScan) {
|
|
2289
2324
|
const content = sessions.map(serializeSessionRecord).join("\n") + (sessions.length ? "\n" : "");
|
|
2290
2325
|
await writeAtomic(sidecarPath, content);
|
|
2291
2326
|
const generatedAt = new Date().toISOString();
|
|
@@ -2298,6 +2333,7 @@ async function buildSessionAnalyticsInternal({ home = os.homedir(), force = fals
|
|
|
2298
2333
|
})}\n`);
|
|
2299
2334
|
await fsp.rm(incompleteZcodePath, { force: true });
|
|
2300
2335
|
await fsp.rm(incompleteOpencodePath, { force: true });
|
|
2336
|
+
await fsp.rm(incompleteKimiPath, { force: true });
|
|
2301
2337
|
}
|
|
2302
2338
|
// Non-enumerable so the array still behaves exactly like a plain row list
|
|
2303
2339
|
// for every existing caller (map/filter/JSON of the rows is unaffected).
|
|
@@ -2579,6 +2615,7 @@ function resumeCommandFor(source, sessionId) {
|
|
|
2579
2615
|
if (source === "claude") return `claude --resume ${id}`;
|
|
2580
2616
|
if (source === "codex") return `codex resume ${id}`;
|
|
2581
2617
|
if (source === "opencode") return `opencode --session ${id}`;
|
|
2618
|
+
if (source === "kimi") return `kimi --session ${id}`;
|
|
2582
2619
|
// Grok Build: `grok --resume <session-id>` (also accepts a title). The
|
|
2583
2620
|
// command must still be run from the session's project_ref cwd.
|
|
2584
2621
|
if (source === "grok") return `grok --resume ${id}`;
|
|
@@ -2922,6 +2959,7 @@ module.exports = {
|
|
|
2922
2959
|
scanGrokSession,
|
|
2923
2960
|
scanZcodeSessions,
|
|
2924
2961
|
scanOpencodeSessions,
|
|
2962
|
+
scanKimiSessions,
|
|
2925
2963
|
buildSessionAnalytics,
|
|
2926
2964
|
summarizeSessions,
|
|
2927
2965
|
listSessionsForBrowser,
|