sidekick-shared 0.25.0 → 0.26.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.
Files changed (116) hide show
  1. package/CHANGELOG.md +57 -0
  2. package/README.md +49 -3
  3. package/dist/accountChanges.js +22 -3
  4. package/dist/accountRegistry.d.ts +22 -1
  5. package/dist/accountRegistry.js +37 -14
  6. package/dist/accountStatus.d.ts +9 -1
  7. package/dist/accountStatus.js +3 -3
  8. package/dist/accounts.d.ts +3 -1
  9. package/dist/accounts.js +84 -64
  10. package/dist/aggregation/EventAggregator.d.ts +15 -2
  11. package/dist/aggregation/EventAggregator.js +54 -9
  12. package/dist/aggregation/costProvenance.d.ts +14 -0
  13. package/dist/aggregation/costProvenance.js +35 -0
  14. package/dist/aggregation/snapshot.d.ts +13 -2
  15. package/dist/aggregation/snapshot.js +57 -6
  16. package/dist/aggregation/types.d.ts +30 -1
  17. package/dist/analytics/compactionLedger.js +15 -5
  18. package/dist/analytics/qualityScore.js +2 -1
  19. package/dist/browser.d.ts +11 -1
  20. package/dist/browser.js +29 -1
  21. package/dist/codexProfiles.d.ts +3 -1
  22. package/dist/codexProfiles.js +4 -2
  23. package/dist/codexQuota.d.ts +2 -0
  24. package/dist/codexQuota.js +11 -66
  25. package/dist/failingTools.d.ts +37 -0
  26. package/dist/failingTools.js +70 -0
  27. package/dist/formatters/sessionDump.js +13 -7
  28. package/dist/formatting.d.ts +13 -0
  29. package/dist/formatting.js +35 -0
  30. package/dist/historicalStore.d.ts +47 -0
  31. package/dist/historicalStore.js +312 -0
  32. package/dist/index.d.ts +46 -12
  33. package/dist/index.js +112 -24
  34. package/dist/node.d.ts +19 -0
  35. package/dist/node.js +47 -1
  36. package/dist/observedContextWindows.d.ts +7 -0
  37. package/dist/observedContextWindows.js +17 -2
  38. package/dist/observedSessionCollector.d.ts +3 -8
  39. package/dist/observedSessionCollector.js +10 -27
  40. package/dist/parsers/sessionActivityDetector.d.ts +24 -2
  41. package/dist/parsers/sessionActivityDetector.js +95 -17
  42. package/dist/parsers/sessionPathResolver.d.ts +11 -0
  43. package/dist/parsers/sessionPathResolver.js +13 -10
  44. package/dist/peakHours.d.ts +34 -3
  45. package/dist/peakHours.js +92 -7
  46. package/dist/pricingCatalog.d.ts +7 -0
  47. package/dist/pricingCatalog.js +8 -5
  48. package/dist/providers/claudeCode.js +11 -96
  49. package/dist/providers/codex.d.ts +2 -0
  50. package/dist/providers/codex.js +94 -259
  51. package/dist/providers/detect.d.ts +2 -0
  52. package/dist/providers/detect.js +29 -24
  53. package/dist/providers/factory.d.ts +6 -0
  54. package/dist/providers/openCode.d.ts +2 -0
  55. package/dist/providers/openCode.js +105 -121
  56. package/dist/providers/rolloutWalker.d.ts +53 -0
  57. package/dist/providers/rolloutWalker.js +209 -0
  58. package/dist/providers/types.d.ts +30 -0
  59. package/dist/quota.d.ts +30 -3
  60. package/dist/quota.js +35 -3
  61. package/dist/quotaHistory.d.ts +1 -1
  62. package/dist/quotaHistory.js +36 -35
  63. package/dist/quotaResolver.d.ts +81 -0
  64. package/dist/quotaResolver.js +213 -0
  65. package/dist/quotaSnapshots.d.ts +15 -2
  66. package/dist/quotaSnapshots.js +25 -3
  67. package/dist/quotaThresholds.d.ts +60 -0
  68. package/dist/quotaThresholds.js +90 -0
  69. package/dist/report/htmlReportGenerator.js +10 -4
  70. package/dist/report/sessionReportInputs.d.ts +23 -0
  71. package/dist/report/sessionReportInputs.js +34 -0
  72. package/dist/schemas/index.d.ts +2 -0
  73. package/dist/schemas/index.js +10 -1
  74. package/dist/schemas/quota.d.ts +139 -0
  75. package/dist/schemas/quota.js +17 -2
  76. package/dist/schemas/quotaHistory.d.ts +1 -0
  77. package/dist/schemas/quotaHistory.js +1 -1
  78. package/dist/schemas/sessionEvent.d.ts +6 -0
  79. package/dist/schemas/sessionEvent.js +1 -0
  80. package/dist/schemas/stateFile.d.ts +198 -0
  81. package/dist/schemas/stateFile.js +77 -0
  82. package/dist/schemas/transcript.js +2 -0
  83. package/dist/sessionFingerprint.d.ts +25 -0
  84. package/dist/sessionFingerprint.js +46 -0
  85. package/dist/sessionPreviews.d.ts +7 -1
  86. package/dist/sessionPreviews.js +15 -3
  87. package/dist/sessionStats.d.ts +51 -0
  88. package/dist/sessionStats.js +166 -0
  89. package/dist/stateFile.d.ts +113 -0
  90. package/dist/stateFile.js +160 -0
  91. package/dist/statusline/claudeStatuslinePayload.d.ts +89 -0
  92. package/dist/statusline/claudeStatuslinePayload.js +152 -0
  93. package/dist/statusline/formatter.d.ts +13 -0
  94. package/dist/statusline/formatter.js +48 -6
  95. package/dist/statusline/index.d.ts +10 -2
  96. package/dist/statusline/index.js +19 -1
  97. package/dist/tokenSummary.d.ts +62 -0
  98. package/dist/tokenSummary.js +72 -0
  99. package/dist/transcript.d.ts +5 -0
  100. package/dist/transcript.js +2 -0
  101. package/dist/types/observedSessionV1.d.ts +2 -0
  102. package/dist/types/observedSessionV1.js +75 -18
  103. package/dist/types/sessionEvent.d.ts +2 -0
  104. package/dist/usage/billingBlocks.d.ts +85 -0
  105. package/dist/usage/billingBlocks.js +153 -0
  106. package/dist/usage/importSessionHistory.d.ts +53 -0
  107. package/dist/usage/importSessionHistory.js +88 -0
  108. package/dist/usage/usageEvents.d.ts +92 -0
  109. package/dist/usage/usageEvents.js +322 -0
  110. package/dist/usage/usageReports.d.ts +76 -0
  111. package/dist/usage/usageReports.js +208 -0
  112. package/dist/watchers/factory.d.ts +6 -0
  113. package/dist/watchers/factory.js +30 -25
  114. package/dist/zaiQuotaApi.d.ts +2 -0
  115. package/dist/zaiQuotaApi.js +2 -0
  116. package/package.json +1 -1
@@ -33,6 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.enrichCodexQuota = enrichCodexQuota;
36
37
  exports.quotaFromCodexRateLimits = quotaFromCodexRateLimits;
37
38
  exports.readLatestCodexQuotaFromRollouts = readLatestCodexQuotaFromRollouts;
38
39
  exports.resolveCodexQuotaFromLocalSources = resolveCodexQuotaFromLocalSources;
@@ -45,6 +46,7 @@ const codexProfiles_1 = require("./codexProfiles");
45
46
  const quotaSnapshots_1 = require("./quotaSnapshots");
46
47
  const quota_1 = require("./quota");
47
48
  const codex_1 = require("./providers/codex");
49
+ const rolloutWalker_1 = require("./providers/rolloutWalker");
48
50
  const codex_2 = require("./types/codex");
49
51
  const DEFAULT_TAIL_BYTES = 2 * 1024 * 1024;
50
52
  const DEFAULT_MAX_SESSION_FILES = 50;
@@ -105,6 +107,7 @@ function timestampToIso(seconds) {
105
107
  function accountEmail(account) {
106
108
  return account?.email ?? account?.metadata?.email;
107
109
  }
110
+ /** Stamp a Codex quota sample with its runtime provider, projections, and account identity. */
108
111
  function enrichCodexQuota(state, account) {
109
112
  const withProjections = (0, quota_1.withQuotaProjections)(state);
110
113
  return {
@@ -278,39 +281,14 @@ function readLatestCodexQuotaHitFromRollouts(sessionPaths, options = {}) {
278
281
  }
279
282
  return latest;
280
283
  }
281
- function dedupePaths(paths) {
282
- const seen = new Set();
283
- const unique = [];
284
- for (const filePath of paths) {
285
- if (seen.has(filePath))
286
- continue;
287
- seen.add(filePath);
288
- unique.push(filePath);
289
- }
290
- return unique;
291
- }
292
- function sortPathsByMtimeDesc(paths) {
293
- return [...paths].sort((a, b) => {
294
- const aMtime = safeMtimeMs(a);
295
- const bMtime = safeMtimeMs(b);
296
- return bMtime - aMtime;
297
- });
298
- }
299
- function safeMtimeMs(filePath) {
300
- try {
301
- return fs.statSync(filePath).mtime.getTime();
302
- }
303
- catch {
304
- return 0;
305
- }
306
- }
307
- function findAccountRolloutFiles(codexHome) {
284
+ /**
285
+ * The newest account-level rollouts, one capped walk across the monitored
286
+ * homes. `limit` bounds the walk itself, so a large history is never fully
287
+ * enumerated or stat'ed just to tail a handful of files.
288
+ */
289
+ function findAccountRolloutFiles(codexHome, limit) {
308
290
  const homes = codexHome ? [codexHome] : (0, codexProfiles_1.getCodexMonitoringHomes)();
309
- const files = [];
310
- for (const home of homes) {
311
- files.push(...findRolloutFiles(path.join(home, 'sessions')));
312
- }
313
- return sortPathsByMtimeDesc(dedupePaths(files));
291
+ return (0, rolloutWalker_1.walkRolloutFiles)(homes.map((home) => path.join(home, 'sessions')), { limit }).map((file) => file.path);
314
292
  }
315
293
  function resolveCodexQuotaFromLocalSources(options = {}) {
316
294
  const account = options.activeAccount !== undefined ? options.activeAccount : (0, codexProfiles_1.getActiveCodexAccount)();
@@ -335,7 +313,7 @@ function resolveCodexQuotaFromLocalSources(options = {}) {
335
313
  if (workspaceHit)
336
314
  candidates.push(workspaceHit);
337
315
  }
338
- const accountSessions = findAccountRolloutFiles(options.codexHome);
316
+ const accountSessions = findAccountRolloutFiles(options.codexHome, maxSessionFiles);
339
317
  const accountHit = readLatestCodexQuotaHitFromRollouts(accountSessions, {
340
318
  maxTailBytes,
341
319
  maxSessionFiles,
@@ -626,36 +604,3 @@ function readLatestQuotaFromRollout(sessionPath, maxTailBytes, source) {
626
604
  }
627
605
  return null;
628
606
  }
629
- function findRolloutFiles(sessionsDir) {
630
- const results = [];
631
- function visit(dir) {
632
- let entries;
633
- try {
634
- entries = fs.readdirSync(dir, { withFileTypes: true });
635
- }
636
- catch {
637
- return;
638
- }
639
- for (const entry of entries) {
640
- const fullPath = path.join(dir, entry.name);
641
- if (entry.isDirectory()) {
642
- visit(fullPath);
643
- continue;
644
- }
645
- if (!entry.isFile() || !entry.name.startsWith('rollout-') || !entry.name.endsWith('.jsonl'))
646
- continue;
647
- try {
648
- const stat = fs.statSync(fullPath);
649
- if (stat.size > 0) {
650
- results.push({ path: fullPath, mtime: stat.mtime.getTime() });
651
- }
652
- }
653
- catch {
654
- // Skip inaccessible files.
655
- }
656
- }
657
- }
658
- visit(sessionsDir);
659
- results.sort((a, b) => b.mtime - a.mtime);
660
- return results.map((item) => item.path);
661
- }
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Failing-tool trend rows shared by the CLI `stats` block and the VS Code
3
+ * Health tab. Browser-safe: no filesystem access; callers pass the two
4
+ * windows they read with `getTopFailingTools()`.
5
+ *
6
+ * @module failingTools
7
+ */
8
+ /** The shape `getTopFailingTools()` returns; declared structurally to stay fs-free. */
9
+ export interface FailingToolWindow {
10
+ tool: string;
11
+ failures: number;
12
+ categories?: Record<string, number>;
13
+ }
14
+ export type FailingToolTrend = 'up' | 'down' | 'flat';
15
+ export interface FailingToolTrendRow {
16
+ tool: string;
17
+ /** Failures in the last 7 days. */
18
+ last7: number;
19
+ /** Failures in the last 30 days. */
20
+ last30: number;
21
+ /** Category counts over the 30-day window (or the 7-day one when only that is known). */
22
+ categories: Record<string, number>;
23
+ /** Whether the last week is worse, better, or in line with the 30-day weekly average. */
24
+ trend: FailingToolTrend;
25
+ }
26
+ /**
27
+ * Compare the last week against the 30-day weekly average: more than 10%
28
+ * above is `up`, more than 10% below is `down`, otherwise `flat`. A tool
29
+ * with no 30-day history but failures this week is `up`.
30
+ */
31
+ export declare function failingToolTrend(last7: number, last30: number): FailingToolTrend;
32
+ export declare const FAILING_TOOL_TREND_ARROWS: Record<FailingToolTrend, string>;
33
+ /**
34
+ * Merge the 7-day and 30-day windows into one row per tool, ordered by
35
+ * 7-day failures, then 30-day failures, then name.
36
+ */
37
+ export declare function mergeFailingToolWindows(last7: FailingToolWindow[], last30: FailingToolWindow[]): FailingToolTrendRow[];
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ /**
3
+ * Failing-tool trend rows shared by the CLI `stats` block and the VS Code
4
+ * Health tab. Browser-safe: no filesystem access; callers pass the two
5
+ * windows they read with `getTopFailingTools()`.
6
+ *
7
+ * @module failingTools
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.FAILING_TOOL_TREND_ARROWS = void 0;
11
+ exports.failingToolTrend = failingToolTrend;
12
+ exports.mergeFailingToolWindows = mergeFailingToolWindows;
13
+ const TREND_TOLERANCE = 0.1;
14
+ /**
15
+ * Compare the last week against the 30-day weekly average: more than 10%
16
+ * above is `up`, more than 10% below is `down`, otherwise `flat`. A tool
17
+ * with no 30-day history but failures this week is `up`.
18
+ */
19
+ function failingToolTrend(last7, last30) {
20
+ const weeklyAverage = last30 / (30 / 7);
21
+ if (weeklyAverage <= 0)
22
+ return last7 > 0 ? 'up' : 'flat';
23
+ const ratio = last7 / weeklyAverage;
24
+ if (ratio > 1 + TREND_TOLERANCE)
25
+ return 'up';
26
+ if (ratio < 1 - TREND_TOLERANCE)
27
+ return 'down';
28
+ return 'flat';
29
+ }
30
+ exports.FAILING_TOOL_TREND_ARROWS = {
31
+ up: '↑',
32
+ down: '↓',
33
+ flat: '→',
34
+ };
35
+ /**
36
+ * Merge the 7-day and 30-day windows into one row per tool, ordered by
37
+ * 7-day failures, then 30-day failures, then name.
38
+ */
39
+ function mergeFailingToolWindows(last7, last30) {
40
+ const rows = new Map();
41
+ for (const tool of last30) {
42
+ rows.set(tool.tool, {
43
+ tool: tool.tool,
44
+ last7: 0,
45
+ last30: tool.failures,
46
+ categories: { ...(tool.categories ?? {}) },
47
+ trend: 'flat',
48
+ });
49
+ }
50
+ for (const tool of last7) {
51
+ const row = rows.get(tool.tool);
52
+ if (row) {
53
+ row.last7 = tool.failures;
54
+ // A 7-day count cannot exceed the 30-day one; tolerate windows read at different instants.
55
+ row.last30 = Math.max(row.last30, tool.failures);
56
+ }
57
+ else {
58
+ rows.set(tool.tool, {
59
+ tool: tool.tool,
60
+ last7: tool.failures,
61
+ last30: tool.failures,
62
+ categories: { ...(tool.categories ?? {}) },
63
+ trend: 'flat',
64
+ });
65
+ }
66
+ }
67
+ for (const row of rows.values())
68
+ row.trend = failingToolTrend(row.last7, row.last30);
69
+ return [...rows.values()].sort((a, b) => b.last7 - a.last7 || b.last30 - a.last30 || a.tool.localeCompare(b.tool));
70
+ }
@@ -15,7 +15,9 @@ exports.fmtTokens = fmtTokens;
15
15
  exports.fmtCost = fmtCost;
16
16
  exports.formatTimestamp = formatTimestamp;
17
17
  exports.formatDuration = formatDuration;
18
+ const costProvenance_1 = require("../aggregation/costProvenance");
18
19
  const formatting_1 = require("../formatting");
20
+ const tokenSummary_1 = require("../tokenSummary");
19
21
  // ── JSON output ──
20
22
  /**
21
23
  * Serialize aggregated metrics as pretty-printed JSON.
@@ -128,9 +130,12 @@ function formatSessionMarkdown(metrics, options = {}) {
128
130
  lines.push(`| Output | ${fmtTokens(metrics.tokens.outputTokens)} |`);
129
131
  lines.push(`| Cache write | ${fmtTokens(metrics.tokens.cacheWriteTokens)} |`);
130
132
  lines.push(`| Cache read | ${fmtTokens(metrics.tokens.cacheReadTokens)} |`);
131
- lines.push(`| Total | ${fmtTokens(metrics.tokens.inputTokens + metrics.tokens.outputTokens)} |`);
132
- if (metrics.tokens.reportedCost > 0) {
133
- lines.push(`| Cost | ${fmtCost(metrics.tokens.reportedCost)} |`);
133
+ lines.push(`| ${tokenSummary_1.TOKEN_TOTAL_LABEL} | ${fmtTokens((0, tokenSummary_1.summarizeTokens)(metrics.tokens).total)} |`);
134
+ if (metrics.tokens.costUsd > 0) {
135
+ lines.push(`| Cost | ${fmtCost(metrics.tokens.costUsd)} (${(0, costProvenance_1.describeCostProvenance)(metrics.tokens)}) |`);
136
+ }
137
+ else if (metrics.tokens.unpricedCalls > 0) {
138
+ lines.push(`| Cost | — (${(0, costProvenance_1.describeCostProvenance)(metrics.tokens)}) |`);
134
139
  }
135
140
  lines.push('');
136
141
  // Model stats
@@ -222,9 +227,9 @@ function formatHeader(metrics) {
222
227
  }
223
228
  function formatTokenSummary(metrics) {
224
229
  const t = metrics.tokens;
225
- const total = t.inputTokens + t.outputTokens;
230
+ const total = (0, tokenSummary_1.summarizeTokens)(t).total;
226
231
  const parts = [
227
- `Tokens: ${fmtTokens(total)} total`,
232
+ `Tokens: ${fmtTokens(total)} total incl. cache`,
228
233
  `(${fmtTokens(t.inputTokens)} in`,
229
234
  `${fmtTokens(t.outputTokens)} out`,
230
235
  ];
@@ -233,8 +238,9 @@ function formatTokenSummary(metrics) {
233
238
  if (t.cacheWriteTokens > 0)
234
239
  parts.push(`${fmtTokens(t.cacheWriteTokens)} cache-write`);
235
240
  const line = parts.join(', ');
236
- if (t.reportedCost > 0)
237
- return `${line}) Cost: ${fmtCost(t.reportedCost)}`;
241
+ if (t.costUsd > 0) {
242
+ return `${line}) Cost: ${fmtCost(t.costUsd)} (${(0, costProvenance_1.describeCostProvenance)(t)})`;
243
+ }
238
244
  return line + ')';
239
245
  }
240
246
  /** @internal Exported for tests. */
@@ -24,3 +24,16 @@ export interface FormatDurationMsOptions {
24
24
  export declare function formatTokenCount(value: number, options?: FormatTokenCountOptions): string;
25
25
  /** Format an elapsed duration in milliseconds. */
26
26
  export declare function formatDurationMs(ms: number, options?: FormatDurationMsOptions): string;
27
+ /**
28
+ * Calendar-date key (`YYYY-MM-DD`) in the machine's local time zone.
29
+ *
30
+ * Sidekick buckets "today", daily history, and heatmaps by the user's local
31
+ * day, so every writer and reader of a date key goes through this helper.
32
+ * A UTC key would move late-evening work onto the next day for anyone west
33
+ * of Greenwich and onto the previous day for anyone east of it.
34
+ */
35
+ export declare function formatLocalDateKey(value?: Date | number): string;
36
+ /** Parse a `YYYY-MM-DD` key produced by `formatLocalDateKey` back into local midnight. */
37
+ export declare function parseLocalDateKey(key: string): Date | null;
38
+ /** Shift a `YYYY-MM-DD` key by whole local days (DST-safe). */
39
+ export declare function addLocalDays(key: string, days: number): string;
@@ -10,6 +10,9 @@
10
10
  Object.defineProperty(exports, "__esModule", { value: true });
11
11
  exports.formatTokenCount = formatTokenCount;
12
12
  exports.formatDurationMs = formatDurationMs;
13
+ exports.formatLocalDateKey = formatLocalDateKey;
14
+ exports.parseLocalDateKey = parseLocalDateKey;
15
+ exports.addLocalDays = addLocalDays;
13
16
  /** Format a token count with compact `k` / `M` suffixes. */
14
17
  function formatTokenCount(value, options = {}) {
15
18
  if (!Number.isFinite(value))
@@ -52,3 +55,35 @@ function formatDurationMs(ms, options = {}) {
52
55
  }
53
56
  return `${minutes}m${separator}${remainingSeconds}s`;
54
57
  }
58
+ /**
59
+ * Calendar-date key (`YYYY-MM-DD`) in the machine's local time zone.
60
+ *
61
+ * Sidekick buckets "today", daily history, and heatmaps by the user's local
62
+ * day, so every writer and reader of a date key goes through this helper.
63
+ * A UTC key would move late-evening work onto the next day for anyone west
64
+ * of Greenwich and onto the previous day for anyone east of it.
65
+ */
66
+ function formatLocalDateKey(value = new Date()) {
67
+ const date = typeof value === 'number' ? new Date(value) : value;
68
+ if (Number.isNaN(date.getTime()))
69
+ return '';
70
+ const year = date.getFullYear();
71
+ const month = String(date.getMonth() + 1).padStart(2, '0');
72
+ const day = String(date.getDate()).padStart(2, '0');
73
+ return `${year}-${month}-${day}`;
74
+ }
75
+ /** Parse a `YYYY-MM-DD` key produced by `formatLocalDateKey` back into local midnight. */
76
+ function parseLocalDateKey(key) {
77
+ const match = /^(\d{4})-(\d{2})-(\d{2})$/.exec(key);
78
+ if (!match)
79
+ return null;
80
+ const date = new Date(Number(match[1]), Number(match[2]) - 1, Number(match[3]));
81
+ return Number.isNaN(date.getTime()) ? null : date;
82
+ }
83
+ /** Shift a `YYYY-MM-DD` key by whole local days (DST-safe). */
84
+ function addLocalDays(key, days) {
85
+ const date = parseLocalDateKey(key);
86
+ if (!date)
87
+ return key;
88
+ return formatLocalDateKey(new Date(date.getFullYear(), date.getMonth(), date.getDate() + days));
89
+ }
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Pure mutations of the `historical-data.json` store.
3
+ *
4
+ * Ported verbatim from the VS Code extension's HistoricalDataService so the
5
+ * CLI importer and the extension apply session summaries the same way:
6
+ * a session's previous contribution is subtracted before the new one is
7
+ * added (idempotent replacement), daily, hourly, monthly, and all-time
8
+ * buckets are updated together, and the per-session record list is capped
9
+ * at `HISTORICAL_SESSION_RETENTION_LIMIT`. Browser-safe: no Node imports.
10
+ *
11
+ * @module historicalStore
12
+ */
13
+ import type { SessionFileStats } from './providers/types';
14
+ import type { HistoricalDataStore, SessionHistoryRecord, SessionSummary } from './types/historicalData';
15
+ export interface ApplySessionSummaryOptions {
16
+ /** Clock for `updatedAt` stamps (default `new Date()`). */
17
+ now?: Date;
18
+ /** Cap on `store.sessions` (default `HISTORICAL_SESSION_RETENTION_LIMIT`). */
19
+ retentionLimit?: number;
20
+ }
21
+ /** Subtract a previously saved session's contribution from every bucket. */
22
+ export declare function removeSessionSummary(store: HistoricalDataStore, record: SessionHistoryRecord, now?: Date): void;
23
+ /**
24
+ * Apply a completed session to the daily, hourly, monthly, and all-time
25
+ * buckets and the capped per-session list. Re-applying the same session id
26
+ * replaces its earlier contribution instead of double counting it.
27
+ *
28
+ * Returns the stored per-session record.
29
+ */
30
+ export declare function applySessionSummary(store: HistoricalDataStore, summary: SessionSummary, options?: ApplySessionSummaryOptions): SessionHistoryRecord;
31
+ /** Whether a session file has already been folded into the store. */
32
+ export declare function isFileImported(store: HistoricalDataStore, filePath: string): boolean;
33
+ /** Record a session file as imported. Returns false when it was already listed. */
34
+ export declare function markFileImported(store: HistoricalDataStore, filePath: string, now?: Date): boolean;
35
+ export interface SessionSummaryFromStatsOptions {
36
+ /** Session provider id stored on the record (default `stats.providerId`). */
37
+ provider?: string;
38
+ /** Workspace path stored on the record (default `'unknown'`). */
39
+ project?: string | null;
40
+ }
41
+ /**
42
+ * Build the summary the history store expects from unified session stats,
43
+ * so the CLI importer and the extension's first-activation import store the
44
+ * same per-model cost, tool success/failure split, and unpriced markers.
45
+ * Pending tool calls count as successes (stats only split out failures).
46
+ */
47
+ export declare function sessionSummaryFromStats(stats: SessionFileStats, options?: SessionSummaryFromStatsOptions): SessionSummary;