Repository navigation
5 hour session window usage info - #55
EphemeralSapient wants to merge 3 commits into
Conversation
There was a problem hiding this comment.
Summary of Changes
Hello @EphemeralSapient, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!
This pull request adds a significant new feature to the ccusage tool: the ability to analyze usage data specifically tailored to the Claude Max plan's 5-hour session window structure and its 50-session monthly limit. It provides detailed breakdowns per window and aggregates monthly statistics, including utilization and remaining sessions, to help users monitor their usage against the plan's constraints.
Highlights
- New Command: Introduced a new
sessionscommand to the CLI for tracking Claude Max plan 5-hour session windows. - Session Window Tracking: Implemented logic to group usage data entries into 5-hour windows based on the timestamp of the first message within that window's time slot.
- Monthly Limit Monitoring: Added reporting for the 50-session monthly limit, showing total sessions used, remaining sessions, and utilization percentage per month.
- Detailed Window Breakdown: The report includes a table detailing each 5-hour window with metrics like duration, message count, conversation count, token usage (input, output, cache), and cost.
- Reporting Options: The new command supports existing options like
--since,--untilfor date filtering,--jsonfor machine-readable output,--modefor cost calculation, and--orderfor sorting monthly results.
Using Gemini Code Assist
The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.
Invoking Gemini
You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.
| Feature | Command | Description |
|---|---|---|
| Code Review | /gemini review |
Performs a code review for the current pull request in its current state. |
| Pull Request Summary | /gemini summary |
Provides a summary of the current pull request in its current state. |
| Comment | @gemini-code-assist | Responds in comments when explicitly tagged, both in issue comments and review comments. |
| Help | /gemini help |
Displays a list of available commands. |
Customization
To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.
Limitations & Feedback
Gemini Code Assist is currently in preview and may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments to provide feedback.
You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.
Footnotes
-
Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configureGemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. ↩
There was a problem hiding this comment.
Code Review
This pull request adds a new sessions command to report Claude Code usage based on 5-hour session windows, including tracking against a monthly limit. The changes are well-tested and cover README updates, command implementation, data loading logic, and type definitions.
Key feedback points include ensuring consistency in default sort order documentation and implementation, correcting a token aggregation bug in loadSessionWindowData for monthly stats, and suggesting improvements for maintainability. The overall structure is good, and addressing these points will enhance the feature's robustness and clarity.
|
|
||
| const totals = windows.reduce((acc, window) => ({ | ||
| cost: acc.cost + window.totalCost, | ||
| tokens: acc.tokens + window.inputTokens + window.outputTokens, |
There was a problem hiding this comment.
The totals.tokens accumulation for monthly stats currently only sums window.inputTokens and window.outputTokens. This is inconsistent with how totalTokens is generally treated for individual windows (which includes all four types: input, output, cache creation, cache read) and how totalTokens is defined in SessionWindowSchema and used in sessions.ts.
To ensure consistency, totalTokens for the month should be the sum of all token types across all windows in that month.
tokens: acc.tokens + window.inputTokens + window.outputTokens + window.cacheCreationTokens + window.cacheReadTokens,| ccusage sessions --order asc # Show oldest months first | ||
| ccusage sessions --order desc # Show newest months first (default) |
There was a problem hiding this comment.
The default sort order for months in the sessions command is documented here as desc (newest months first). However, the sharedCommandConfig in src/shared-args.internal.ts specifies asc as the default for the --order argument. The sessionsCommand inherits this default.
This means that without an explicit --order flag, the sessions command will sort months in ascending order (oldest first), contradicting this documentation.
Consider either:
- Changing the default for
orderinsrc/shared-args.internal.tstodescif this is the preferred default for most/all commands. - Overriding the default for the
orderargument specifically within thesessionsCommanddefinition insrc/commands/sessions.ts. - Updating this documentation to reflect
ascas the default.
| while (sessionWindows.has(newWindowId)) { | ||
| newWindowStart = new Date(newWindowStart.getTime() + 5 * 60 * 60 * 1000); | ||
| newWindowId = getSessionWindowId(newWindowStart.toISOString()); | ||
| } |
There was a problem hiding this comment.
The while loop for finding an unused newWindowId seems to handle a potential key collision in the sessionWindows map. If getSessionWindowId(entry.data.timestamp) (which is newWindowId initially) is already a key, this loop shifts newWindowStart by 5-hour increments until an unused getSessionWindowId is found for the map key.
This means the window.windowId stored for the new session window (line 596) might not be getSessionWindowId(window.startTime). This could be confusing as windowId might not directly correspond to the window's actual start time's 5-hour slot.
If the intent is for window.windowId to always reflect getSessionWindowId(window.startTime), an alternative approach for map keys might be needed, such as using window.startTime.toISOString() as the unique key in sessionWindows map, and then deriving the reported windowId from window.startTime when constructing the SessionWindow object. This would simplify the key management here.
However, if this logic is intentionally mimicking a specific behavior of how Claude might use fixed slots, it might be correct but complex. Adding a comment explaining this specific scenario and why the key might be shifted would improve maintainability.
| const sortOrder = options?.order ?? 'desc'; | ||
| const sortedStats = sort(monthlyStats); | ||
| return sortOrder === 'desc' | ||
| ? sortedStats.desc(item => item.month) | ||
| : sortedStats.asc(item => item.month); |
There was a problem hiding this comment.
The default sort order for monthly stats is determined here. options?.order ?? 'desc' means if options.order is undefined or null, it defaults to desc.
However, sharedCommandConfig (in src/shared-args.internal.ts) sets the default for the --order argument to 'asc'. If gunshi passes this default value when the user doesn't specify --order, then options.order will be 'asc', and the ?? 'desc' fallback won't be used. This results in months being sorted ascendingly by default.
This conflicts with the README for the sessions command, which states that desc (newest months first) is the default. This inconsistency should be resolved. See the comment on README.md:223-224 for suggestions.
|
@EphemeralSapient Hi I found that there is a magic number |
|
|
||
| logger.info(`\n${pc.bold(monthStats.month)} - ${pc[utilizationColor](`${monthStats.totalSessions} sessions used`)} (${pc[utilizationColor](`${monthStats.utilizationPercent.toFixed(1)}%`)} of 50 limit)`); | ||
|
|
||
| if (monthStats.remainingSessions <= 5 && monthStats.remainingSessions > 0) { |
|
|
||
| export const SessionWindowSchema = v.object({ | ||
| windowId: v.string(), // Format: YYYY-MM-DD-HH (start of 5-hour window) | ||
| startTime: v.string(), // ISO timestamp of first message in window | ||
| endTime: v.string(), // ISO timestamp of last message in window | ||
| inputTokens: v.number(), | ||
| outputTokens: v.number(), | ||
| cacheCreationTokens: v.number(), | ||
| cacheReadTokens: v.number(), | ||
| totalCost: v.number(), | ||
| messageCount: v.number(), // Number of messages in this window | ||
| conversationCount: v.number(), // Number of unique conversations in this window | ||
| }); | ||
|
|
||
| export type SessionWindow = v.InferOutput<typeof SessionWindowSchema>; | ||
|
|
||
| export const CurrentSessionInfoSchema = v.object({ | ||
| hasActiveSession: v.boolean(), | ||
| timeRemainingMs: v.number(), | ||
| timeRemainingFormatted: v.string(), | ||
| activeWindow: v.optional(SessionWindowSchema), | ||
| }); | ||
|
|
||
| export type CurrentSessionInfo = v.InferOutput<typeof CurrentSessionInfoSchema>; | ||
|
|
||
| export const SessionWindowStatsSchema = v.object({ | ||
| month: v.pipe( | ||
| v.string(), | ||
| v.regex(/^\d{4}-\d{2}$/), // YYYY-MM format | ||
| ), | ||
| totalSessions: v.number(), // Total number of 5-hour windows with activity | ||
| remainingSessions: v.number(), // 50 - totalSessions (Max plan limit) | ||
| utilizationPercent: v.number(), // (totalSessions / 50) * 100 | ||
| totalCost: v.number(), | ||
| totalTokens: v.number(), | ||
| averageCostPerSession: v.number(), | ||
| averageTokensPerSession: v.number(), | ||
| windows: v.array(SessionWindowSchema), | ||
| currentSession: v.optional(CurrentSessionInfoSchema), | ||
| }); | ||
|
|
||
| export type SessionWindowStats = v.InferOutput<typeof SessionWindowStatsSchema>; |
There was a problem hiding this comment.
you can define those types in data-loader.ts because we don't use it in other files.
also you can stop exporting it
commit: |
There was a problem hiding this comment.
Pull Request Overview
This PR implements 5-hour session window tracking for the Claude Max plan, grouping usage into fixed windows and enforcing a 50-session monthly limit.
- Defined new Zod‐style schemas (
SessionWindow,CurrentSessionInfo,SessionWindowStats) in types.internal.ts - Added
loadSessionWindowData, window‐grouping utilities, and current session calculation in data-loader.ts - Introduced
ccusage sessionscommand, corresponding tests, and documentation in commands/ and README.md
Reviewed Changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| src/types.internal.ts | Added session window and monthly stats schemas |
| src/data-loader.ts | Implemented session window ID calculation and grouping |
| src/data-loader.test.ts | Added comprehensive tests for loadSessionWindowData |
| src/commands/sessions.ts | New CLI command for session window reports |
| src/commands/index.ts | Registered the new sessions subcommand |
| README.md | Updated docs and usage examples for session windows report |
|
|
||
| const newWindow = { | ||
| windowId: newWindowId, | ||
| startTime: entry.timestamp, |
There was a problem hiding this comment.
The new window’s startTime is set to the original entry.timestamp even after adjusting newWindowStart in the loop. This can misalign the window start when slot collisions occur. Use newWindowStart instead of entry.timestamp for startTime to match the computed windowId.
| startTime: entry.timestamp, | |
| startTime: newWindowStart, |
| + window.cacheCreationTokens + window.cacheReadTokens; | ||
|
|
||
| windowsTable.push([ | ||
| startTime.toLocaleString().substring(0, 16), // Remove seconds |
There was a problem hiding this comment.
[nitpick] Using substring on toLocaleString output is brittle and locale-dependent. Consider using toLocaleString with explicit formatting options (e.g., { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit' }) for consistent results.
| startTime.toLocaleString().substring(0, 16), // Remove seconds | |
| startTime.toLocaleString('en-US', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit' }), // Consistent formatting |
|
ah, forgot about that completely, I thought both 100$ and 200$ plan had same session; I was wrong followed up with above review; again used CC , sorry if I missed anything :P |
WalkthroughA new "Session Windows Report" feature was introduced, targeting the Claude Max plan. This includes a CLI command and data loader logic to aggregate usage into 5-hour session windows, track monthly session limits, and provide detailed per-window and monthly statistics. Documentation, CLI registration, argument defaults, and comprehensive tests were added or updated. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant CLI (sessionsCommand)
participant DataLoader (loadSessionWindowData)
participant Formatter/Console
User->>CLI (sessionsCommand): Run `ccusage sessions` with options
CLI (sessionsCommand)->>DataLoader (loadSessionWindowData): Load session window data (with filters, limits)
DataLoader (loadSessionWindowData)-->>CLI (sessionsCommand): Aggregated session stats (per window, per month)
CLI (sessionsCommand)->>Formatter/Console: Format and output report (JSON or styled table)
Formatter/Console-->>User: Display session windows report
Poem
✨ Finishing Touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Actionable comments posted: 6
♻️ Duplicate comments (2)
src/data-loader.ts (2)
765-768:⚠️ Potential issueInclude all token types in monthly total tokens calculation.
The
totalTokenscalculation currently only sumsinputTokensandoutputTokens, but cache tokens (cacheCreationTokensandcacheReadTokens) are tracked separately in windows. For consistency with how tokens are aggregated elsewhere in the codebase, include all token types.const totals = windows.reduce((acc, window) => ({ cost: acc.cost + window.totalCost, - tokens: acc.tokens + window.inputTokens + window.outputTokens, + tokens: acc.tokens + window.inputTokens + window.outputTokens + window.cacheCreationTokens + window.cacheReadTokens, }), { cost: 0, tokens: 0 });🧰 Tools
🪛 ESLint
[error] 765-768: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 766-766: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 766-766: Unsafe member access .cost on an
errortyped value.(ts/no-unsafe-member-access)
[error] 766-766: Unsafe member access .totalCost on an
errortyped value.(ts/no-unsafe-member-access)
[error] 767-767: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 767-767: Unsafe member access .tokens on an
errortyped value.(ts/no-unsafe-member-access)
[error] 767-767: Unsafe member access .inputTokens on an
errortyped value.(ts/no-unsafe-member-access)
[error] 767-767: Unsafe member access .outputTokens on an
errortyped value.(ts/no-unsafe-member-access)
689-708:⚠️ Potential issueFix window start time to match the computed window ID.
When a new window ID is computed after collision detection, the window's
startTimeshould be set tonewWindowStartto maintain consistency between the window ID and its actual start time.const newWindow = { windowId: newWindowId, - startTime: entry.timestamp, + startTime: newWindowStart, endTime: entry.timestamp, entries: [entry], conversationIds: new Set([entry.conversationId]), };🧰 Tools
🪛 ESLint
[error] 696-696: Unsafe argument of type error typed assigned to a parameter of type
string | number | Date.(ts/no-unsafe-argument)
[error] 696-696: Unsafe call of a(n)
errortype typed value.(ts/no-unsafe-call)
[error] 696-696: Unsafe member access .getTime on an
errortyped value.(ts/no-unsafe-member-access)
[error] 697-697: Unsafe argument of type error typed assigned to a parameter of type
string.(ts/no-unsafe-argument)
[error] 697-697: Unsafe call of a(n)
errortype typed value.(ts/no-unsafe-call)
[error] 697-697: Unsafe member access .toISOString on an
errortyped value.(ts/no-unsafe-member-access)
[error] 702-702: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 702-702: Unsafe member access .timestamp on an
errortyped value.(ts/no-unsafe-member-access)
[error] 703-703: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 703-703: Unsafe member access .timestamp on an
errortyped value.(ts/no-unsafe-member-access)
[error] 705-705: Unsafe member access .conversationId on an
errortyped value.(ts/no-unsafe-member-access)
🧹 Nitpick comments (3)
README.md (1)
365-394: Add language tag to fenced blockMarkdown-lint warning MD040 – simply append
bash:-``` +```bash🧰 Tools
🪛 markdownlint-cli2 (0.17.2)
365-365: Fenced code blocks should have a language specified
null(MD040, fenced-code-language)
src/commands/sessions.ts (2)
61-63:totalTokensrecomputed but already available
window.totalTokensexists in loader output. Recomputing risks divergence if loader logic changes.-totalTokens: window.inputTokens + window.outputTokens + window.cacheCreationTokens + window.cacheReadTokens, +totalTokens: window.totalTokens,🧰 Tools
🪛 ESLint
[error] 61-61: Unsafe assignment of an
anyvalue.(ts/no-unsafe-assignment)
[error] 61-61: Unsafe member access .inputTokens on an
anyvalue.(ts/no-unsafe-member-access)
[error] 61-61: Unsafe member access .outputTokens on an
anyvalue.(ts/no-unsafe-member-access)
[error] 61-61: Unsafe member access .cacheCreationTokens on an
anyvalue.(ts/no-unsafe-member-access)
[error] 61-61: Unsafe member access .cacheReadTokens on an
anyvalue.(ts/no-unsafe-member-access)
[error] 62-62: Unsafe assignment of an
anyvalue.(ts/no-unsafe-assignment)
[error] 62-62: Unsafe member access .totalCost on an
anyvalue.(ts/no-unsafe-member-access)
[error] 63-63: Unsafe assignment of an
anyvalue.(ts/no-unsafe-assignment)
[error] 63-63: Unsafe member access .messageCount on an
anyvalue.(ts/no-unsafe-member-access)
144-146: Date display uses brittle substring
toISOString().substring(0, 10)is always UTC; users in other zones may see an off-by-one date. Use locale-aware formatting:-startTime.toISOString().substring(0, 10) +startTime.toLocaleDateString('en-CA') // YYYY-MM-DDMaintains fixed width while respecting local midnight.
🧰 Tools
🪛 ESLint
[error] 146-146: Unsafe argument of type error typed assigned to a parameter of type
number.(ts/no-unsafe-argument)
[error] 146-146: Unsafe member access .messageCount on an
errortyped value.(ts/no-unsafe-member-access)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
README.md(4 hunks)package.json(1 hunks)src/commands/index.ts(1 hunks)src/commands/sessions.ts(1 hunks)src/data-loader.test.ts(2 hunks)src/data-loader.ts(4 hunks)src/shared-args.internal.ts(1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (3)
src/shared-args.internal.ts (1)
src/types.internal.ts (2)
SortOrder(13-13)SortOrders(12-12)
src/commands/sessions.ts (4)
src/shared-args.internal.ts (1)
sharedCommandConfig(79-82)src/logger.ts (2)
logger(5-5)log(8-8)src/data-loader.ts (1)
loadSessionWindowData(579-795)src/utils.internal.ts (2)
formatNumber(1-3)formatCurrency(5-7)
src/data-loader.test.ts (1)
src/data-loader.ts (2)
loadSessionWindowData(579-795)UsageData(81-81)
🪛 ESLint
src/shared-args.internal.ts
[error] 64-64: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
src/commands/sessions.ts
[error] 10-226: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 10-10: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 15-15: Unexpected any value in conditional. An explicit comparison or type conversion is required.
(ts/strict-boolean-expressions)
[error] 15-15: Unsafe member access .values on an any value.
(ts/no-unsafe-member-access)
[error] 16-16: Unsafe member access .level on an error typed value.
(ts/no-unsafe-member-access)
[error] 20-20: Unsafe assignment of an any value.
(ts/no-unsafe-assignment)
[error] 20-20: Unsafe member access .values on an any value.
(ts/no-unsafe-member-access)
[error] 21-21: Unsafe assignment of an any value.
(ts/no-unsafe-assignment)
[error] 21-21: Unsafe member access .values on an any value.
(ts/no-unsafe-member-access)
[error] 22-22: Unsafe assignment of an any value.
(ts/no-unsafe-assignment)
[error] 22-22: Unsafe member access .values on an any value.
(ts/no-unsafe-member-access)
[error] 23-23: Unsafe member access .values on an any value.
(ts/no-unsafe-member-access)
[error] 24-24: Unsafe member access .values on an any value.
(ts/no-unsafe-member-access)
[error] 25-25: Unsafe assignment of an any value.
(ts/no-unsafe-assignment)
[error] 25-25: Unsafe member access .values on an any value.
(ts/no-unsafe-member-access)
[error] 26-26: Unsafe assignment of an any value.
(ts/no-unsafe-assignment)
[error] 26-26: Unsafe member access .values on an any value.
(ts/no-unsafe-member-access)
[error] 30-30: Unexpected any value in conditional. An explicit comparison or type conversion is required.
(ts/strict-boolean-expressions)
[error] 30-30: Unsafe member access .values on an any value.
(ts/no-unsafe-member-access)
[error] 31-31: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 34-34: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 34-34: Unsafe member access .warn on an error typed value.
(ts/no-unsafe-member-access)
[error] 36-36: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 36-36: Unsafe member access .exit on an error typed value.
(ts/no-unsafe-member-access)
[error] 39-39: Unexpected any value in conditional. An explicit comparison or type conversion is required.
(ts/strict-boolean-expressions)
[error] 39-39: Unsafe member access .values on an any value.
(ts/no-unsafe-member-access)
[error] 43-43: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 43-43: Unsafe member access .month on an error typed value.
(ts/no-unsafe-member-access)
[error] 44-44: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 44-44: Unsafe member access .totalSessions on an error typed value.
(ts/no-unsafe-member-access)
[error] 45-45: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 45-45: Unsafe member access .remainingSessions on an error typed value.
(ts/no-unsafe-member-access)
[error] 46-46: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 46-46: Unsafe member access .utilizationPercent on an error typed value.
(ts/no-unsafe-member-access)
[error] 47-47: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 47-47: Unsafe member access .sessionLimit on an error typed value.
(ts/no-unsafe-member-access)
[error] 48-48: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 48-48: Unsafe member access .totalCost on an error typed value.
(ts/no-unsafe-member-access)
[error] 49-49: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 49-49: Unsafe member access .totalTokens on an error typed value.
(ts/no-unsafe-member-access)
[error] 50-50: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 50-50: Unsafe member access .averageCostPerSession on an error typed value.
(ts/no-unsafe-member-access)
[error] 51-51: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 51-51: Unsafe member access .averageTokensPerSession on an error typed value.
(ts/no-unsafe-member-access)
[error] 52-52: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 52-52: Unsafe member access .currentSession on an error typed value.
(ts/no-unsafe-member-access)
[error] 53-65: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 53-53: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 53-53: Unsafe member access .windows on an error typed value.
(ts/no-unsafe-member-access)
[error] 54-54: Unsafe assignment of an any value.
(ts/no-unsafe-assignment)
[error] 54-54: Unsafe member access .windowId on an any value.
(ts/no-unsafe-member-access)
[error] 55-55: Unsafe assignment of an any value.
(ts/no-unsafe-assignment)
[error] 55-55: Unsafe member access .startTime on an any value.
(ts/no-unsafe-member-access)
[error] 56-56: Unsafe assignment of an any value.
(ts/no-unsafe-assignment)
[error] 56-56: Unsafe member access .endTime on an any value.
(ts/no-unsafe-member-access)
[error] 57-57: Unsafe assignment of an any value.
(ts/no-unsafe-assignment)
[error] 57-57: Unsafe member access .inputTokens on an any value.
(ts/no-unsafe-member-access)
[error] 58-58: Unsafe assignment of an any value.
(ts/no-unsafe-assignment)
[error] 58-58: Unsafe member access .outputTokens on an any value.
(ts/no-unsafe-member-access)
[error] 59-59: Unsafe assignment of an any value.
(ts/no-unsafe-assignment)
[error] 59-59: Unsafe member access .cacheCreationTokens on an any value.
(ts/no-unsafe-member-access)
[error] 60-60: Unsafe assignment of an any value.
(ts/no-unsafe-assignment)
[error] 60-60: Unsafe member access .cacheReadTokens on an any value.
(ts/no-unsafe-member-access)
[error] 61-61: Unsafe assignment of an any value.
(ts/no-unsafe-assignment)
[error] 61-61: Unsafe member access .inputTokens on an any value.
(ts/no-unsafe-member-access)
[error] 61-61: Unsafe member access .outputTokens on an any value.
(ts/no-unsafe-member-access)
[error] 61-61: Unsafe member access .cacheCreationTokens on an any value.
(ts/no-unsafe-member-access)
[error] 61-61: Unsafe member access .cacheReadTokens on an any value.
(ts/no-unsafe-member-access)
[error] 62-62: Unsafe assignment of an any value.
(ts/no-unsafe-assignment)
[error] 62-62: Unsafe member access .totalCost on an any value.
(ts/no-unsafe-member-access)
[error] 63-63: Unsafe assignment of an any value.
(ts/no-unsafe-assignment)
[error] 63-63: Unsafe member access .messageCount on an any value.
(ts/no-unsafe-member-access)
[error] 64-64: Unsafe assignment of an any value.
(ts/no-unsafe-assignment)
[error] 64-64: Unsafe member access .conversationCount on an any value.
(ts/no-unsafe-member-access)
[error] 68-68: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 72-72: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 72-72: Unsafe member access .box on an error typed value.
(ts/no-unsafe-member-access)
[error] 76-76: Unsafe member access .utilizationPercent on an error typed value.
(ts/no-unsafe-member-access)
[error] 78-78: Unsafe member access .utilizationPercent on an error typed value.
(ts/no-unsafe-member-access)
[error] 82-82: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 82-82: Unsafe member access .info on an error typed value.
(ts/no-unsafe-member-access)
[error] 82-82: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 82-82: Unsafe member access .bold on an error typed value.
(ts/no-unsafe-member-access)
[error] 82-82: Unsafe member access .month on an error typed value.
(ts/no-unsafe-member-access)
[error] 82-82: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 82-82: Unsafe member access [utilizationColor] on an error typed value.
(ts/no-unsafe-member-access)
[error] 82-82: Unsafe member access .totalSessions on an error typed value.
(ts/no-unsafe-member-access)
[error] 82-82: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 82-82: Unsafe member access [utilizationColor] on an error typed value.
(ts/no-unsafe-member-access)
[error] 82-82: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 82-82: Unsafe member access .utilizationPercent on an error typed value.
(ts/no-unsafe-member-access)
[error] 82-82: Unsafe member access .sessionLimit on an error typed value.
(ts/no-unsafe-member-access)
[error] 84-84: Unsafe member access .remainingSessions on an error typed value.
(ts/no-unsafe-member-access)
[error] 84-84: Unsafe member access .values on an any value.
(ts/no-unsafe-member-access)
[error] 84-84: Unsafe member access .remainingSessions on an error typed value.
(ts/no-unsafe-member-access)
[error] 85-85: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 85-85: Unsafe member access .warn on an error typed value.
(ts/no-unsafe-member-access)
[error] 85-85: Unsafe member access .remainingSessions on an error typed value.
(ts/no-unsafe-member-access)
[error] 87-87: Unsafe member access .remainingSessions on an error typed value.
(ts/no-unsafe-member-access)
[error] 88-88: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 88-88: Unsafe member access .error on an error typed value.
(ts/no-unsafe-member-access)
[error] 91-91: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 91-91: Unsafe member access .success on an error typed value.
(ts/no-unsafe-member-access)
[error] 91-91: Unsafe member access .remainingSessions on an error typed value.
(ts/no-unsafe-member-access)
[error] 95-95: Unsafe member access .currentSession on an error typed value.
(ts/no-unsafe-member-access)
[error] 96-96: Unsafe member access .currentSession on an error typed value.
(ts/no-unsafe-member-access)
[error] 97-97: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 97-97: Unsafe member access .info on an error typed value.
(ts/no-unsafe-member-access)
[error] 97-97: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 97-97: Unsafe member access [timeColor] on an error typed value.
(ts/no-unsafe-member-access)
[error] 97-97: Unsafe member access .currentSession on an error typed value.
(ts/no-unsafe-member-access)
[error] 101-101: Unsafe member access .windows on an error typed value.
(ts/no-unsafe-member-access)
[error] 102-130: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 102-130: Unsafe construction of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 132-132: Unsafe member access .windows on an error typed value.
(ts/no-unsafe-member-access)
[error] 133-133: Unsafe argument of type error typed assigned to a parameter of type string | number | Date.
(ts/no-unsafe-argument)
[error] 133-133: Unsafe member access .startTime on an error typed value.
(ts/no-unsafe-member-access)
[error] 134-134: Unsafe argument of type error typed assigned to a parameter of type string | number | Date.
(ts/no-unsafe-argument)
[error] 134-134: Unsafe member access .endTime on an error typed value.
(ts/no-unsafe-member-access)
[error] 140-141: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 140-140: Unsafe member access .inputTokens on an error typed value.
(ts/no-unsafe-member-access)
[error] 140-140: Unsafe member access .outputTokens on an error typed value.
(ts/no-unsafe-member-access)
[error] 141-141: Unsafe member access .cacheCreationTokens on an error typed value.
(ts/no-unsafe-member-access)
[error] 141-141: Unsafe member access .cacheReadTokens on an error typed value.
(ts/no-unsafe-member-access)
[error] 143-143: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 143-143: Unsafe member access .push on an error typed value.
(ts/no-unsafe-member-access)
[error] 146-146: Unsafe argument of type error typed assigned to a parameter of type number.
(ts/no-unsafe-argument)
[error] 146-146: Unsafe member access .messageCount on an error typed value.
(ts/no-unsafe-member-access)
[error] 147-147: Unsafe argument of type error typed assigned to a parameter of type number.
(ts/no-unsafe-argument)
[error] 147-147: Unsafe member access .conversationCount on an error typed value.
(ts/no-unsafe-member-access)
[error] 148-148: Unsafe argument of type error typed assigned to a parameter of type number.
(ts/no-unsafe-argument)
[error] 148-148: Unsafe member access .inputTokens on an error typed value.
(ts/no-unsafe-member-access)
[error] 149-149: Unsafe argument of type error typed assigned to a parameter of type number.
(ts/no-unsafe-argument)
[error] 149-149: Unsafe member access .outputTokens on an error typed value.
(ts/no-unsafe-member-access)
[error] 150-150: Unsafe argument of type error typed assigned to a parameter of type number.
(ts/no-unsafe-argument)
[error] 150-150: Unsafe member access .cacheCreationTokens on an error typed value.
(ts/no-unsafe-member-access)
[error] 151-151: Unsafe argument of type error typed assigned to a parameter of type number.
(ts/no-unsafe-argument)
[error] 151-151: Unsafe member access .cacheReadTokens on an error typed value.
(ts/no-unsafe-member-access)
[error] 152-152: Unsafe argument of type error typed assigned to a parameter of type number.
(ts/no-unsafe-argument)
[error] 153-153: Unsafe argument of type error typed assigned to a parameter of type number.
(ts/no-unsafe-argument)
[error] 153-153: Unsafe member access .totalCost on an error typed value.
(ts/no-unsafe-member-access)
[error] 158-158: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 158-158: Unsafe member access .windows on an error typed value.
(ts/no-unsafe-member-access)
[error] 159-159: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 159-159: Unsafe member access .totalCost on an error typed value.
(ts/no-unsafe-member-access)
[error] 160-160: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 160-160: Unsafe member access .totalTokens on an error typed value.
(ts/no-unsafe-member-access)
[error] 161-161: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 161-161: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 161-161: Unsafe member access .windows on an error typed value.
(ts/no-unsafe-member-access)
[error] 161-161: Unsafe return of a value of type any.
(ts/no-unsafe-return)
[error] 161-161: Unsafe member access .inputTokens on an any value.
(ts/no-unsafe-member-access)
[error] 162-162: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 162-162: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 162-162: Unsafe member access .windows on an error typed value.
(ts/no-unsafe-member-access)
[error] 162-162: Unsafe return of a value of type any.
(ts/no-unsafe-return)
[error] 162-162: Unsafe member access .outputTokens on an any value.
(ts/no-unsafe-member-access)
[error] 163-163: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 163-163: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 163-163: Unsafe member access .windows on an error typed value.
(ts/no-unsafe-member-access)
[error] 163-163: Unsafe return of a value of type any.
(ts/no-unsafe-return)
[error] 163-163: Unsafe member access .cacheCreationTokens on an any value.
(ts/no-unsafe-member-access)
[error] 164-164: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 164-164: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 164-164: Unsafe member access .windows on an error typed value.
(ts/no-unsafe-member-access)
[error] 164-164: Unsafe return of a value of type any.
(ts/no-unsafe-return)
[error] 164-164: Unsafe member access .cacheReadTokens on an any value.
(ts/no-unsafe-member-access)
[error] 166-166: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 166-166: Unsafe member access .push on an error typed value.
(ts/no-unsafe-member-access)
[error] 179-179: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 179-179: Unsafe member access .push on an error typed value.
(ts/no-unsafe-member-access)
[error] 180-180: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 180-180: Unsafe member access .yellow on an error typed value.
(ts/no-unsafe-member-access)
[error] 181-181: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 181-181: Unsafe member access .yellow on an error typed value.
(ts/no-unsafe-member-access)
[error] 182-182: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 182-182: Unsafe member access .yellow on an error typed value.
(ts/no-unsafe-member-access)
[error] 183-183: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 183-183: Unsafe member access .yellow on an error typed value.
(ts/no-unsafe-member-access)
[error] 184-184: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 184-184: Unsafe member access .yellow on an error typed value.
(ts/no-unsafe-member-access)
[error] 184-184: Unsafe argument of type error typed assigned to a parameter of type number.
(ts/no-unsafe-argument)
[error] 185-185: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 185-185: Unsafe member access .yellow on an error typed value.
(ts/no-unsafe-member-access)
[error] 185-185: Unsafe argument of type error typed assigned to a parameter of type number.
(ts/no-unsafe-argument)
[error] 186-186: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 186-186: Unsafe member access .yellow on an error typed value.
(ts/no-unsafe-member-access)
[error] 186-186: Unsafe argument of type error typed assigned to a parameter of type number.
(ts/no-unsafe-argument)
[error] 187-187: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 187-187: Unsafe member access .yellow on an error typed value.
(ts/no-unsafe-member-access)
[error] 187-187: Unsafe argument of type error typed assigned to a parameter of type number.
(ts/no-unsafe-argument)
[error] 188-188: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 188-188: Unsafe member access .yellow on an error typed value.
(ts/no-unsafe-member-access)
[error] 188-188: Unsafe argument of type error typed assigned to a parameter of type number.
(ts/no-unsafe-argument)
[error] 189-189: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 189-189: Unsafe member access .yellow on an error typed value.
(ts/no-unsafe-member-access)
[error] 189-189: Unsafe argument of type error typed assigned to a parameter of type number.
(ts/no-unsafe-argument)
[error] 192-192: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 192-192: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 192-192: Unsafe member access .toString on an error typed value.
(ts/no-unsafe-member-access)
[error] 196-196: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 201-201: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 201-201: Unsafe return of a value of type error.
(ts/no-unsafe-return)
[error] 201-201: Unsafe member access .totalSessions on an error typed value.
(ts/no-unsafe-member-access)
[error] 202-202: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 202-202: Unsafe return of a value of type error.
(ts/no-unsafe-return)
[error] 202-202: Unsafe member access .totalCost on an error typed value.
(ts/no-unsafe-member-access)
[error] 203-203: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 203-203: Unsafe return of a value of type error.
(ts/no-unsafe-return)
[error] 203-203: Unsafe member access .totalTokens on an error typed value.
(ts/no-unsafe-member-access)
[error] 205-205: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 205-205: Unsafe member access .info on an error typed value.
(ts/no-unsafe-member-access)
[error] 205-205: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 205-205: Unsafe member access .bold on an error typed value.
(ts/no-unsafe-member-access)
[error] 206-212: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 206-212: Unsafe construction of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 214-214: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 214-214: Unsafe member access .push on an error typed value.
(ts/no-unsafe-member-access)
[error] 215-215: Unsafe argument of type error typed assigned to a parameter of type number.
(ts/no-unsafe-argument)
[error] 216-216: Unsafe argument of type error typed assigned to a parameter of type number.
(ts/no-unsafe-argument)
[error] 217-217: Unsafe argument of type error typed assigned to a parameter of type number.
(ts/no-unsafe-argument)
[error] 222-222: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 222-222: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 222-222: Unsafe member access .toString on an error typed value.
(ts/no-unsafe-member-access)
src/data-loader.test.ts
[error] 1809-1809: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1810-1810: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1811-1813: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 1811-1811: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1815-1815: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 1815-1815: Unsafe member access .path on an error typed value.
(ts/no-unsafe-member-access)
[error] 1816-1816: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1816-1816: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1816-1816: Unsafe member access .toEqual on an error typed value.
(ts/no-unsafe-member-access)
[error] 1819-1819: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1839-1847: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 1839-1839: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1849-1849: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 1849-1849: Unsafe member access .path on an error typed value.
(ts/no-unsafe-member-access)
[error] 1851-1851: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1851-1851: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1851-1851: Unsafe member access .toHaveLength on an error typed value.
(ts/no-unsafe-member-access)
[error] 1852-1852: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1852-1852: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1852-1852: Unsafe member access .month on an error typed value.
(ts/no-unsafe-member-access)
[error] 1852-1852: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 1853-1853: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1853-1853: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1853-1853: Unsafe member access .totalSessions on an error typed value.
(ts/no-unsafe-member-access)
[error] 1853-1853: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 1854-1854: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1854-1854: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1854-1854: Unsafe member access .windows on an error typed value.
(ts/no-unsafe-member-access)
[error] 1854-1854: Unsafe member access .toHaveLength on an error typed value.
(ts/no-unsafe-member-access)
[error] 1856-1856: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 1856-1856: Unsafe member access .windows on an error typed value.
(ts/no-unsafe-member-access)
[error] 1860-1860: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 1860-1860: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1860-1860: Unsafe member access .reduce on an error typed value.
(ts/no-unsafe-member-access)
[error] 1860-1860: Unsafe return of a value of type any.
(ts/no-unsafe-return)
[error] 1860-1860: Unsafe member access .inputTokens on an any value.
(ts/no-unsafe-member-access)
[error] 1861-1861: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 1861-1861: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1861-1861: Unsafe member access .reduce on an error typed value.
(ts/no-unsafe-member-access)
[error] 1861-1861: Unsafe return of a value of type any.
(ts/no-unsafe-return)
[error] 1861-1861: Unsafe member access .outputTokens on an any value.
(ts/no-unsafe-member-access)
[error] 1862-1862: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 1862-1862: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1862-1862: Unsafe member access .reduce on an error typed value.
(ts/no-unsafe-member-access)
[error] 1862-1862: Unsafe return of a value of type any.
(ts/no-unsafe-return)
[error] 1862-1862: Unsafe member access .totalCost on an any value.
(ts/no-unsafe-member-access)
[error] 1863-1863: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 1863-1863: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1863-1863: Unsafe member access .reduce on an error typed value.
(ts/no-unsafe-member-access)
[error] 1863-1863: Unsafe return of a value of type any.
(ts/no-unsafe-return)
[error] 1863-1863: Unsafe member access .messageCount on an any value.
(ts/no-unsafe-member-access)
[error] 1865-1865: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1865-1865: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1865-1865: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 1866-1866: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1866-1866: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1866-1866: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 1867-1867: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1867-1867: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1867-1867: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 1868-1868: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1868-1868: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1868-1868: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 1871-1871: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1879-1888: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 1879-1879: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1890-1890: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 1890-1890: Unsafe member access .path on an error typed value.
(ts/no-unsafe-member-access)
[error] 1892-1892: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1892-1892: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1892-1892: Unsafe member access .toHaveLength on an error typed value.
(ts/no-unsafe-member-access)
[error] 1893-1893: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1893-1893: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1893-1893: Unsafe member access .totalSessions on an error typed value.
(ts/no-unsafe-member-access)
[error] 1893-1893: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 1894-1894: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1894-1894: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1894-1894: Unsafe member access .remainingSessions on an error typed value.
(ts/no-unsafe-member-access)
[error] 1894-1894: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 1895-1895: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1895-1895: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1895-1895: Unsafe member access .utilizationPercent on an error typed value.
(ts/no-unsafe-member-access)
[error] 1895-1895: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 1898-1898: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1917-1926: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 1917-1917: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1928-1928: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 1928-1928: Unsafe member access .path on an error typed value.
(ts/no-unsafe-member-access)
[error] 1930-1930: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1930-1930: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1930-1930: Unsafe member access .toHaveLength on an error typed value.
(ts/no-unsafe-member-access)
[error] 1933-1933: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1933-1933: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1933-1933: Unsafe member access .month on an error typed value.
(ts/no-unsafe-member-access)
[error] 1933-1933: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 1934-1934: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1934-1934: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1934-1934: Unsafe member access .month on an error typed value.
(ts/no-unsafe-member-access)
[error] 1934-1934: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 1935-1935: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1935-1935: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1935-1935: Unsafe member access .month on an error typed value.
(ts/no-unsafe-member-access)
[error] 1935-1935: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 1939-1939: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1939-1939: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1939-1939: Unsafe member access .totalSessions on an error typed value.
(ts/no-unsafe-member-access)
[error] 1939-1939: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 1940-1940: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1940-1940: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1940-1940: Unsafe member access .remainingSessions on an error typed value.
(ts/no-unsafe-member-access)
[error] 1940-1940: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 1944-1944: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1957-1968: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 1957-1957: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1970-1970: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 1970-1970: Unsafe member access .path on an error typed value.
(ts/no-unsafe-member-access)
[error] 1972-1972: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1972-1972: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1972-1972: Unsafe member access .toHaveLength on an error typed value.
(ts/no-unsafe-member-access)
[error] 1973-1973: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 1973-1973: Unsafe member access .windows on an error typed value.
(ts/no-unsafe-member-access)
[error] 1974-1974: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1974-1974: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1974-1974: Unsafe member access .conversationCount on an error typed value.
(ts/no-unsafe-member-access)
[error] 1974-1974: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 1975-1975: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1975-1975: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1975-1975: Unsafe member access .messageCount on an error typed value.
(ts/no-unsafe-member-access)
[error] 1975-1975: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 1978-1978: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1992-2001: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 1992-1992: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2003-2003: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 2003-2003: Unsafe member access .path on an error typed value.
(ts/no-unsafe-member-access)
[error] 2005-2005: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2005-2005: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2005-2005: Unsafe member access .toHaveLength on an error typed value.
(ts/no-unsafe-member-access)
[error] 2006-2006: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 2007-2007: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2007-2007: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2007-2007: Unsafe member access .totalSessions on an error typed value.
(ts/no-unsafe-member-access)
[error] 2007-2007: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 2008-2008: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2008-2008: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2008-2008: Unsafe member access .totalCost on an error typed value.
(ts/no-unsafe-member-access)
[error] 2008-2008: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 2009-2009: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2009-2009: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2009-2009: Unsafe member access .totalTokens on an error typed value.
(ts/no-unsafe-member-access)
[error] 2009-2009: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 2010-2010: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2010-2010: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2010-2010: Unsafe member access .averageCostPerSession on an error typed value.
(ts/no-unsafe-member-access)
[error] 2010-2010: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 2011-2011: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2011-2011: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2011-2011: Unsafe member access .averageTokensPerSession on an error typed value.
(ts/no-unsafe-member-access)
[error] 2011-2011: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 2014-2014: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2028-2036: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 2028-2028: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2038-2038: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 2038-2038: Unsafe member access .path on an error typed value.
(ts/no-unsafe-member-access)
[error] 2040-2040: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2040-2040: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2040-2040: Unsafe member access .toHaveLength on an error typed value.
(ts/no-unsafe-member-access)
[error] 2041-2041: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 2041-2041: Unsafe member access .windows on an error typed value.
(ts/no-unsafe-member-access)
[error] 2042-2042: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2042-2042: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2042-2042: Unsafe member access .inputTokens on an error typed value.
(ts/no-unsafe-member-access)
[error] 2042-2042: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 2043-2043: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2043-2043: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2043-2043: Unsafe member access .outputTokens on an error typed value.
(ts/no-unsafe-member-access)
[error] 2043-2043: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 2044-2044: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2044-2044: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2044-2044: Unsafe member access .cacheCreationTokens on an error typed value.
(ts/no-unsafe-member-access)
[error] 2044-2044: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 2045-2045: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2045-2045: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2045-2045: Unsafe member access .cacheReadTokens on an error typed value.
(ts/no-unsafe-member-access)
[error] 2045-2045: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 2048-2048: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2067-2076: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 2067-2067: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2079-2079: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 2079-2079: Unsafe member access .path on an error typed value.
(ts/no-unsafe-member-access)
[error] 2084-2084: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2084-2084: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2084-2084: Unsafe member access .toHaveLength on an error typed value.
(ts/no-unsafe-member-access)
[error] 2085-2085: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2085-2085: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2085-2085: Unsafe member access .totalSessions on an error typed value.
(ts/no-unsafe-member-access)
[error] 2085-2085: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 2086-2086: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2086-2086: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2086-2086: Unsafe member access .windows on an error typed value.
(ts/no-unsafe-member-access)
[error] 2086-2086: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 2089-2089: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2108-2117: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 2108-2108: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2121-2121: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 2121-2121: Unsafe member access .path on an error typed value.
(ts/no-unsafe-member-access)
[error] 2124-2124: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2124-2124: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2124-2124: Unsafe return of a value of type error.
(ts/no-unsafe-return)
[error] 2124-2124: Unsafe member access .month on an error typed value.
(ts/no-unsafe-member-access)
[error] 2124-2124: Unsafe member access .toEqual on an error typed value.
(ts/no-unsafe-member-access)
[error] 2128-2128: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 2128-2128: Unsafe member access .path on an error typed value.
(ts/no-unsafe-member-access)
[error] 2131-2131: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2131-2131: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2131-2131: Unsafe return of a value of type error.
(ts/no-unsafe-return)
[error] 2131-2131: Unsafe member access .month on an error typed value.
(ts/no-unsafe-member-access)
[error] 2131-2131: Unsafe member access .toEqual on an error typed value.
(ts/no-unsafe-member-access)
[error] 2134-2134: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2142-2151: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 2142-2142: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2153-2153: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 2153-2153: Unsafe member access .path on an error typed value.
(ts/no-unsafe-member-access)
[error] 2155-2155: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2155-2155: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2155-2155: Unsafe member access .toHaveLength on an error typed value.
(ts/no-unsafe-member-access)
[error] 2156-2156: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2156-2156: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2156-2156: Unsafe member access .totalSessions on an error typed value.
(ts/no-unsafe-member-access)
[error] 2156-2156: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 2157-2157: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2157-2157: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2157-2157: Unsafe member access .remainingSessions on an error typed value.
(ts/no-unsafe-member-access)
[error] 2157-2157: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 2158-2158: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2158-2158: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2158-2158: Unsafe member access .utilizationPercent on an error typed value.
(ts/no-unsafe-member-access)
[error] 2158-2158: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
src/data-loader.ts
[error] 22-33: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 22-22: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 22-22: Unsafe member access .object on an error typed value.
(ts/no-unsafe-member-access)
[error] 23-23: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 23-23: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 23-23: Unsafe member access .string on an error typed value.
(ts/no-unsafe-member-access)
[error] 24-24: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 24-24: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 24-24: Unsafe member access .string on an error typed value.
(ts/no-unsafe-member-access)
[error] 25-25: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 25-25: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 25-25: Unsafe member access .string on an error typed value.
(ts/no-unsafe-member-access)
[error] 26-26: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 26-26: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 26-26: Unsafe member access .number on an error typed value.
(ts/no-unsafe-member-access)
[error] 27-27: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 27-27: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 27-27: Unsafe member access .number on an error typed value.
(ts/no-unsafe-member-access)
[error] 28-28: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 28-28: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 28-28: Unsafe member access .number on an error typed value.
(ts/no-unsafe-member-access)
[error] 29-29: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 29-29: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 29-29: Unsafe member access .number on an error typed value.
(ts/no-unsafe-member-access)
[error] 30-30: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 30-30: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 30-30: Unsafe member access .number on an error typed value.
(ts/no-unsafe-member-access)
[error] 31-31: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 31-31: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 31-31: Unsafe member access .number on an error typed value.
(ts/no-unsafe-member-access)
[error] 32-32: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 32-32: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 32-32: Unsafe member access .number on an error typed value.
(ts/no-unsafe-member-access)
[error] 37-42: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 37-37: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 37-37: Unsafe member access .object on an error typed value.
(ts/no-unsafe-member-access)
[error] 38-38: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 38-38: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 38-38: Unsafe member access .boolean on an error typed value.
(ts/no-unsafe-member-access)
[error] 39-39: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 39-39: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 39-39: Unsafe member access .number on an error typed value.
(ts/no-unsafe-member-access)
[error] 40-40: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 40-40: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 40-40: Unsafe member access .string on an error typed value.
(ts/no-unsafe-member-access)
[error] 41-41: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 41-41: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 41-41: Unsafe member access .optional on an error typed value.
(ts/no-unsafe-member-access)
[error] 47-62: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 47-47: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 47-47: Unsafe member access .object on an error typed value.
(ts/no-unsafe-member-access)
[error] 48-51: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 48-48: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 48-48: Unsafe member access .pipe on an error typed value.
(ts/no-unsafe-member-access)
[error] 49-49: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 49-49: Unsafe member access .string on an error typed value.
(ts/no-unsafe-member-access)
[error] 50-50: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 50-50: Unsafe member access .regex on an error typed value.
(ts/no-unsafe-member-access)
[error] 52-52: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 52-52: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 52-52: Unsafe member access .number on an error typed value.
(ts/no-unsafe-member-access)
[error] 53-53: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 53-53: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 53-53: Unsafe member access .number on an error typed value.
(ts/no-unsafe-member-access)
[error] 54-54: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 54-54: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 54-54: Unsafe member access .number on an error typed value.
(ts/no-unsafe-member-access)
[error] 55-55: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 55-55: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 55-55: Unsafe member access .number on an error typed value.
(ts/no-unsafe-member-access)
[error] 56-56: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 56-56: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 56-56: Unsafe member access .number on an error typed value.
(ts/no-unsafe-member-access)
[error] 57-57: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 57-57: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 57-57: Unsafe member access .number on an error typed value.
(ts/no-unsafe-member-access)
[error] 58-58: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 58-58: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 58-58: Unsafe member access .number on an error typed value.
(ts/no-unsafe-member-access)
[error] 59-59: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 59-59: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 59-59: Unsafe member access .number on an error typed value.
(ts/no-unsafe-member-access)
[error] 60-60: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 60-60: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 60-60: Unsafe member access .array on an error typed value.
(ts/no-unsafe-member-access)
[error] 61-61: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 61-61: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 61-61: Unsafe member access .optional on an error typed value.
(ts/no-unsafe-member-access)
[error] 542-544: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 543-543: Unsafe return of a value of type error.
(ts/no-unsafe-return)
[error] 543-543: Unsafe argument of type error typed assigned to a parameter of type string | number | Date.
(ts/no-unsafe-argument)
[error] 543-543: Unsafe member access .startTime on an error typed value.
(ts/no-unsafe-member-access)
[error] 543-543: Unsafe argument of type error typed assigned to a parameter of type string | number | Date.
(ts/no-unsafe-argument)
[error] 543-543: Unsafe member access .startTime on an error typed value.
(ts/no-unsafe-member-access)
[error] 547-547: Unsafe argument of type error typed assigned to a parameter of type string | number | Date.
(ts/no-unsafe-argument)
[error] 547-547: Unsafe member access .startTime on an error typed value.
(ts/no-unsafe-member-access)
[error] 568-568: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 583-583: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 583-583: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 583-583: Unsafe member access .join on an error typed value.
(ts/no-unsafe-member-access)
[error] 584-587: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 584-584: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 585-585: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 589-589: Unsafe member access .length on an error typed value.
(ts/no-unsafe-member-access)
[error] 594-594: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 609-609: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 609-609: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 609-609: Unsafe member access .relative on an error typed value.
(ts/no-unsafe-member-access)
[error] 610-610: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 610-610: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 610-610: Unsafe member access .replace on an error typed value.
(ts/no-unsafe-member-access)
[error] 612-612: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 612-612: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 613-616: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 613-616: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 613-615: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 613-614: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 614-614: Unsafe member access .trim on an error typed value.
(ts/no-unsafe-member-access)
[error] 615-615: Unsafe member access .split on an error typed value.
(ts/no-unsafe-member-access)
[error] 616-616: Unsafe member access .filter on an error typed value.
(ts/no-unsafe-member-access)
[error] 616-616: Unsafe member access .length on an any value.
(ts/no-unsafe-member-access)
[error] 620-620: Unsafe argument of type error typed assigned to a parameter of type string.
(ts/no-unsafe-argument)
[error] 621-621: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 621-621: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 621-621: Unsafe member access .safeParse on an error typed value.
(ts/no-unsafe-member-access)
[error] 622-622: Unexpected any value in conditional. An explicit comparison or type conversion is required.
(ts/strict-boolean-expressions)
[error] 622-622: Unsafe member access .success on an error typed value.
(ts/no-unsafe-member-access)
[error] 625-625: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 625-625: Unsafe member access .output on an error typed value.
(ts/no-unsafe-member-access)
[error] 627-629: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 629-629: Unsafe member access .costUSD on an error typed value.
(ts/no-unsafe-member-access)
[error] 632-632: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 633-633: Unsafe argument of type error typed assigned to a parameter of type string | number | Date.
(ts/no-unsafe-argument)
[error] 633-633: Unsafe member access .timestamp on an error typed value.
(ts/no-unsafe-member-access)
[error] 634-634: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 635-635: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 645-645: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 645-645: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 645-645: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 645-645: Unsafe member access .asc on an error typed value.
(ts/no-unsafe-member-access)
[error] 645-645: Unsafe return of a value of type any.
(ts/no-unsafe-return)
[error] 645-645: Unsafe call of a(n) any typed value.
(ts/no-unsafe-call)
[error] 645-645: Unsafe member access .timestamp on an any value.
(ts/no-unsafe-member-access)
[error] 657-657: Unsafe argument of type error typed assigned to a parameter of type string.
(ts/no-unsafe-argument)
[error] 657-657: Unsafe member access .data on an error typed value.
(ts/no-unsafe-member-access)
[error] 666-666: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 666-666: Unsafe member access .timestamp on an error typed value.
(ts/no-unsafe-member-access)
[error] 667-667: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 667-667: Unsafe member access .timestamp on an error typed value.
(ts/no-unsafe-member-access)
[error] 675-675: Unsafe argument of type error typed assigned to a parameter of type string.
(ts/no-unsafe-argument)
[error] 675-675: Unsafe member access .data on an error typed value.
(ts/no-unsafe-member-access)
[error] 677-677: Unsafe argument of type error typed assigned to a parameter of type { data: v.InferOutput<any>; timestamp: Date; cost: number; conversationId: string; }.
(ts/no-unsafe-argument)
[error] 678-678: Unsafe argument of type error typed assigned to a parameter of type string.
(ts/no-unsafe-argument)
[error] 678-678: Unsafe member access .conversationId on an error typed value.
(ts/no-unsafe-member-access)
[error] 679-679: Unsafe member access .timestamp on an error typed value.
(ts/no-unsafe-member-access)
[error] 680-680: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 680-680: Unsafe member access .timestamp on an error typed value.
(ts/no-unsafe-member-access)
[error] 686-686: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 686-686: Unsafe member access .timestamp on an error typed value.
(ts/no-unsafe-member-access)
[error] 687-687: Unsafe argument of type error typed assigned to a parameter of type string.
(ts/no-unsafe-argument)
[error] 687-687: Unsafe member access .data on an error typed value.
(ts/no-unsafe-member-access)
[error] 696-696: Unsafe argument of type error typed assigned to a parameter of type string | number | Date.
(ts/no-unsafe-argument)
[error] 696-696: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 696-696: Unsafe member access .getTime on an error typed value.
(ts/no-unsafe-member-access)
[error] 697-697: Unsafe argument of type error typed assigned to a parameter of type string.
(ts/no-unsafe-argument)
[error] 697-697: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 697-697: Unsafe member access .toISOString on an error typed value.
(ts/no-unsafe-member-access)
[error] 702-702: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 702-702: Unsafe member access .timestamp on an error typed value.
(ts/no-unsafe-member-access)
[error] 703-703: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 703-703: Unsafe member access .timestamp on an error typed value.
(ts/no-unsafe-member-access)
[error] 705-705: Unsafe member access .conversationId on an error typed value.
(ts/no-unsafe-member-access)
[error] 714-714: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 714-714: Unsafe member access .message on an error typed value.
(ts/no-unsafe-member-access)
[error] 715-715: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 715-715: Unsafe member access .message on an error typed value.
(ts/no-unsafe-member-access)
[error] 716-716: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 716-716: Unsafe member access .message on an error typed value.
(ts/no-unsafe-member-access)
[error] 717-717: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 717-717: Unsafe member access .message on an error typed value.
(ts/no-unsafe-member-access)
[error] 726-726: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 727-727: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 728-728: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 729-729: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 739-739: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 739-739: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 739-739: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 739-739: Unsafe member access .startTime on an error typed value.
(ts/no-unsafe-member-access)
[error] 739-739: Unsafe member access .replace on an error typed value.
(ts/no-unsafe-member-access)
[error] 751-751: Unsafe return of a value of type error.
(ts/no-unsafe-return)
[error] 751-751: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 751-751: Unsafe member access .startTime on an error typed value.
(ts/no-unsafe-member-access)
[error] 765-768: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 766-766: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 766-766: Unsafe member access .cost on an error typed value.
(ts/no-unsafe-member-access)
[error] 766-766: Unsafe member access .totalCost on an error typed value.
(ts/no-unsafe-member-access)
[error] 767-767: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 767-767: Unsafe member access .tokens on an error typed value.
(ts/no-unsafe-member-access)
[error] 767-767: Unsafe member access .inputTokens on an error typed value.
(ts/no-unsafe-member-access)
[error] 767-767: Unsafe member access .outputTokens on an error typed value.
(ts/no-unsafe-member-access)
[error] 771-771: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 779-779: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 779-779: Unsafe member access .cost on an error typed value.
(ts/no-unsafe-member-access)
[error] 780-780: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 780-780: Unsafe member access .tokens on an error typed value.
(ts/no-unsafe-member-access)
[error] 781-781: Unsafe member access .cost on an error typed value.
(ts/no-unsafe-member-access)
[error] 782-782: Unsafe member access .tokens on an error typed value.
(ts/no-unsafe-member-access)
[error] 783-783: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 783-783: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 783-783: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 783-783: Unsafe member access [options?.order === 'asc' ? 'asc' : 'desc'] on an error typed value.
(ts/no-unsafe-member-access)
[error] 783-783: Unsafe argument of type any assigned to a parameter of type string | number | Date.
(ts/no-unsafe-argument)
[error] 783-783: Unsafe member access .startTime on an any value.
(ts/no-unsafe-member-access)
[error] 784-784: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 790-790: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 791-791: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 791-791: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 792-794: Unsafe return of a value of type error.
(ts/no-unsafe-return)
[error] 793-793: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 793-793: Unsafe member access .desc on an error typed value.
(ts/no-unsafe-member-access)
[error] 793-793: Unsafe return of a value of type any.
(ts/no-unsafe-return)
[error] 793-793: Unsafe member access .month on an any value.
(ts/no-unsafe-member-access)
[error] 794-794: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 794-794: Unsafe member access .asc on an error typed value.
(ts/no-unsafe-member-access)
[error] 794-794: Unsafe return of a value of type any.
(ts/no-unsafe-return)
[error] 794-794: Unsafe member access .month on an any value.
(ts/no-unsafe-member-access)
🪛 markdownlint-cli2 (0.17.2)
README.md
365-365: Fenced code blocks should have a language specified
null
(MD040, fenced-code-language)
🔇 Additional comments (2)
src/shared-args.internal.ts (1)
60-66: 👍 Default sort order aligned with docsSwitching the default from
asctodescfinally removes the doc / code discrepancy flagged in earlier reviews.🧰 Tools
🪛 ESLint
[error] 64-64: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
package.json (1)
2-86: Formatting update only—no functional impact.Indentation was converted from tabs to spaces throughout
package.jsonwithout altering dependencies, scripts, or configuration. This aligns with the project's style rules.
| import { sessionsCommand } from './sessions.ts'; | ||
|
|
||
| // Create subcommands map | ||
| const subCommands = new Map(); | ||
| subCommands.set('daily', dailyCommand); | ||
| subCommands.set('monthly', monthlyCommand); | ||
| subCommands.set('session', sessionCommand); | ||
| subCommands.set('sessions', sessionsCommand); | ||
| subCommands.set('mcp', mcpCommand); |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Plural sessions vs singular session – potential UX confusion
Two sub-commands now differ only by a trailing “s”. On a fast CLI it is easy to mistype or mis-remember which one prints conversation sessions and which one prints 5-hour window sessions.
Consider:
- subCommands.set('session', sessionCommand);
- subCommands.set('sessions', sessionsCommand);
+subCommands.set('session', sessionCommand); // conversations
+subCommands.set('window', sessionsCommand); // 5-hour windowsor add an alias array in each command so both accept session|sessions while de-duplicating help output.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| import { sessionsCommand } from './sessions.ts'; | |
| // Create subcommands map | |
| const subCommands = new Map(); | |
| subCommands.set('daily', dailyCommand); | |
| subCommands.set('monthly', monthlyCommand); | |
| subCommands.set('session', sessionCommand); | |
| subCommands.set('sessions', sessionsCommand); | |
| subCommands.set('mcp', mcpCommand); | |
| import { sessionsCommand } from './sessions.ts'; | |
| // Create subcommands map | |
| const subCommands = new Map(); | |
| subCommands.set('daily', dailyCommand); | |
| subCommands.set('monthly', monthlyCommand); | |
| subCommands.set('session', sessionCommand); // conversations | |
| subCommands.set('window', sessionsCommand); // 5-hour windows | |
| subCommands.set('mcp', mcpCommand); |
🤖 Prompt for AI Agents
In src/commands/index.ts around lines 8 to 16, the subcommands 'session' and
'sessions' differ only by a trailing 's', which can cause user confusion. To fix
this, modify the command definitions to accept both 'session' and 'sessions' as
aliases for the same command, ensuring that both inputs trigger the same
functionality. Update the subCommands map or command registration logic to
support alias arrays, and adjust the help output to avoid duplicate entries for
these aliases.
| sessionLimit: { | ||
| type: 'number', | ||
| description: 'Monthly session limit (default: 50 for Max plan)', | ||
| default: 50, | ||
| }, | ||
| warningThreshold: { | ||
| type: 'number', | ||
| description: 'Warning threshold for remaining sessions (default: 5)', | ||
| default: 5, | ||
| }, |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Validate new numeric flags
sessionLimit and warningThreshold are accepted as plain numbers; negative or non-integer values would break downstream calculations.
sessionLimit: {
type: 'number',
description: 'Monthly session limit (default: 50 for Max plan)',
- default: 50,
+ default: 50,
+ validate: (v: number) => {
+ if (!Number.isInteger(v) || v <= 0) throw new TypeError('--session-limit must be a positive integer');
+ },
},
warningThreshold: {
type: 'number',
description: 'Warning threshold for remaining sessions (default: 5)',
- default: 5,
+ default: 5,
+ validate: (v: number) => {
+ if (!Number.isInteger(v) || v < 0) throw new TypeError('--warning-threshold must be 0 or a positive integer');
+ },
},Implementing a lightweight validator avoids unexpected NaNs later.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| sessionLimit: { | |
| type: 'number', | |
| description: 'Monthly session limit (default: 50 for Max plan)', | |
| default: 50, | |
| }, | |
| warningThreshold: { | |
| type: 'number', | |
| description: 'Warning threshold for remaining sessions (default: 5)', | |
| default: 5, | |
| }, | |
| sessionLimit: { | |
| type: 'number', | |
| description: 'Monthly session limit (default: 50 for Max plan)', | |
| default: 50, | |
| validate: (v: number) => { | |
| if (!Number.isInteger(v) || v <= 0) { | |
| throw new TypeError('--session-limit must be a positive integer'); | |
| } | |
| }, | |
| }, | |
| warningThreshold: { | |
| type: 'number', | |
| description: 'Warning threshold for remaining sessions (default: 5)', | |
| default: 5, | |
| validate: (v: number) => { | |
| if (!Number.isInteger(v) || v < 0) { | |
| throw new TypeError('--warning-threshold must be 0 or a positive integer'); | |
| } | |
| }, | |
| }, |
🤖 Prompt for AI Agents
In src/shared-args.internal.ts around lines 67 to 76, the numeric flags
sessionLimit and warningThreshold currently accept any number, including
negative or non-integer values, which can cause issues downstream. Add
validation logic to ensure these values are positive integers by checking that
they are numbers, greater than or equal to zero, and whole numbers. Reject or
throw an error for invalid inputs to prevent unexpected NaNs or calculation
errors later.
| if (sessionData.length === 0) { | ||
| if (ctx.values.json) { | ||
| log(JSON.stringify([])); | ||
| } | ||
| else { | ||
| logger.warn('No Claude usage data found.'); | ||
| } | ||
| process.exit(0); | ||
| } |
There was a problem hiding this comment.
Avoid process.exit inside command – let caller decide
process.exit(0) prevents unit tests or higher-level CLIs from chaining commands. Prefer returning early:
- logger.warn('No Claude usage data found.');
- }
- process.exit(0);
+ logger.warn('No Claude usage data found.');
+ }
+ return;This keeps the CLI graceful without hard-terminating the Node process.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if (sessionData.length === 0) { | |
| if (ctx.values.json) { | |
| log(JSON.stringify([])); | |
| } | |
| else { | |
| logger.warn('No Claude usage data found.'); | |
| } | |
| process.exit(0); | |
| } | |
| if (sessionData.length === 0) { | |
| if (ctx.values.json) { | |
| log(JSON.stringify([])); | |
| } | |
| else { | |
| logger.warn('No Claude usage data found.'); | |
| } | |
| return; | |
| } |
🧰 Tools
🪛 ESLint
[error] 30-30: Unexpected any value in conditional. An explicit comparison or type conversion is required.
(ts/strict-boolean-expressions)
[error] 30-30: Unsafe member access .values on an any value.
(ts/no-unsafe-member-access)
[error] 31-31: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 34-34: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 34-34: Unsafe member access .warn on an error typed value.
(ts/no-unsafe-member-access)
[error] 36-36: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 36-36: Unsafe member access .exit on an error typed value.
(ts/no-unsafe-member-access)
🤖 Prompt for AI Agents
In src/commands/sessions.ts around lines 29 to 37, remove the call to
process.exit(0) to avoid hard-terminating the Node process inside the command.
Instead, refactor the code to return early after logging the message or JSON
output, allowing the caller to decide how to proceed and enabling better
chaining and testing.
| async run(ctx) { | ||
| if (ctx.values.json) { | ||
| logger.level = 0; | ||
| } | ||
|
|
||
| const sessionData = await loadSessionWindowData({ | ||
| since: ctx.values.since, | ||
| until: ctx.values.until, | ||
| claudePath: ctx.values.path, | ||
| mode: ctx.values.mode, | ||
| order: ctx.values.order, | ||
| sessionLimit: ctx.values.sessionLimit, | ||
| warningThreshold: ctx.values.warningThreshold, | ||
| }); |
There was a problem hiding this comment.
🛠️ Refactor suggestion
ctx.values is inferred as any – tighten types & remove ESLint noise
gunshi.define loses type information when you spread ...sharedCommandConfig; consequently every access is flagged no-unsafe-member-access.
-async run(ctx) {
- if (ctx.values.json) {
+async run(ctx: { values: typeof sharedCommandConfig.args }) {
+ const {
+ json,
+ since,
+ until,
+ path,
+ mode,
+ order,
+ sessionLimit,
+ warningThreshold,
+ } = ctx.values;
+
+ if (json) {Benefits: eliminates ~70 ESLint errors, improves IDE autocomplete, and makes future refactors safer.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| async run(ctx) { | |
| if (ctx.values.json) { | |
| logger.level = 0; | |
| } | |
| const sessionData = await loadSessionWindowData({ | |
| since: ctx.values.since, | |
| until: ctx.values.until, | |
| claudePath: ctx.values.path, | |
| mode: ctx.values.mode, | |
| order: ctx.values.order, | |
| sessionLimit: ctx.values.sessionLimit, | |
| warningThreshold: ctx.values.warningThreshold, | |
| }); | |
| async run(ctx: { values: typeof sharedCommandConfig.args }) { | |
| const { | |
| json, | |
| since, | |
| until, | |
| path, | |
| mode, | |
| order, | |
| sessionLimit, | |
| warningThreshold, | |
| } = ctx.values; | |
| if (json) { | |
| logger.level = 0; | |
| } | |
| const sessionData = await loadSessionWindowData({ | |
| since: ctx.values.since, | |
| until: ctx.values.until, | |
| claudePath: ctx.values.path, | |
| mode: ctx.values.mode, | |
| order: ctx.values.order, | |
| sessionLimit: ctx.values.sessionLimit, | |
| warningThreshold: ctx.values.warningThreshold, | |
| }); |
🧰 Tools
🪛 ESLint
[error] 15-15: Unexpected any value in conditional. An explicit comparison or type conversion is required.
(ts/strict-boolean-expressions)
[error] 15-15: Unsafe member access .values on an any value.
(ts/no-unsafe-member-access)
[error] 16-16: Unsafe member access .level on an error typed value.
(ts/no-unsafe-member-access)
[error] 20-20: Unsafe assignment of an any value.
(ts/no-unsafe-assignment)
[error] 20-20: Unsafe member access .values on an any value.
(ts/no-unsafe-member-access)
[error] 21-21: Unsafe assignment of an any value.
(ts/no-unsafe-assignment)
[error] 21-21: Unsafe member access .values on an any value.
(ts/no-unsafe-member-access)
[error] 22-22: Unsafe assignment of an any value.
(ts/no-unsafe-assignment)
[error] 22-22: Unsafe member access .values on an any value.
(ts/no-unsafe-member-access)
[error] 23-23: Unsafe member access .values on an any value.
(ts/no-unsafe-member-access)
[error] 24-24: Unsafe member access .values on an any value.
(ts/no-unsafe-member-access)
[error] 25-25: Unsafe assignment of an any value.
(ts/no-unsafe-assignment)
[error] 25-25: Unsafe member access .values on an any value.
(ts/no-unsafe-member-access)
[error] 26-26: Unsafe assignment of an any value.
(ts/no-unsafe-assignment)
[error] 26-26: Unsafe member access .values on an any value.
(ts/no-unsafe-member-access)
🤖 Prompt for AI Agents
In src/commands/sessions.ts around lines 14 to 27, the ctx.values object is
currently typed as any, causing ESLint no-unsafe-member-access errors. To fix
this, define a specific TypeScript interface or type for the expected shape of
ctx.values with all required properties. Then, update the command definition to
use this type for ctx.values, ensuring proper typing is preserved when spreading
sharedCommandConfig. This will tighten types, remove ESLint noise, and improve
IDE autocomplete.
| describe('loadSessionWindowData', () => { | ||
| test('returns empty array when no files found', async () => { | ||
| await using fixture = await createFixture({ | ||
| projects: {}, | ||
| }); | ||
|
|
||
| const result = await loadSessionWindowData({ claudePath: fixture.path }); | ||
| expect(result).toEqual([]); | ||
| }); | ||
|
|
||
| test('groups messages into 5-hour session windows', async () => { | ||
| // Create test data with messages spread across different times | ||
| const mockData: UsageData[] = [ | ||
| { | ||
| timestamp: '2024-01-01T00:00:00Z', // Window 1: 00:00-05:00 | ||
| message: { usage: { input_tokens: 100, output_tokens: 50 } }, | ||
| costUSD: 0.01, | ||
| }, | ||
| { | ||
| timestamp: '2024-01-01T02:00:00Z', // Same window (within 5 hours) | ||
| message: { usage: { input_tokens: 200, output_tokens: 100 } }, | ||
| costUSD: 0.02, | ||
| }, | ||
| { | ||
| timestamp: '2024-01-01T06:00:00Z', // Window 2: 05:00-10:00 | ||
| message: { usage: { input_tokens: 300, output_tokens: 150 } }, | ||
| costUSD: 0.03, | ||
| }, | ||
| ]; | ||
|
|
||
| await using fixture = await createFixture({ | ||
| projects: { | ||
| project1: { | ||
| session1: { | ||
| 'chat.jsonl': mockData.map(d => JSON.stringify(d)).join('\n'), | ||
| }, | ||
| }, | ||
| }, | ||
| }); | ||
|
|
||
| const result = await loadSessionWindowData({ claudePath: fixture.path }); | ||
|
|
||
| expect(result).toHaveLength(1); // One month (2024-01) | ||
| expect(result[0]?.month).toBe('2024-01'); | ||
| expect(result[0]?.totalSessions).toBe(2); // Two 5-hour windows | ||
| expect(result[0]?.windows).toHaveLength(2); | ||
|
|
||
| const windows = result[0]?.windows ?? []; | ||
| // Windows are sorted by startTime desc by default | ||
| // The logic groups by first occurrence, so all messages from same conversation | ||
| // Check total aggregation instead of individual windows | ||
| const totalInputTokens = windows.reduce((sum, w) => sum + w.inputTokens, 0); | ||
| const totalOutputTokens = windows.reduce((sum, w) => sum + w.outputTokens, 0); | ||
| const totalCost = windows.reduce((sum, w) => sum + w.totalCost, 0); | ||
| const totalMessages = windows.reduce((sum, w) => sum + w.messageCount, 0); | ||
|
|
||
| expect(totalInputTokens).toBe(600); // 100 + 200 + 300 | ||
| expect(totalOutputTokens).toBe(300); // 50 + 100 + 150 | ||
| expect(totalCost).toBe(0.06); // 0.01 + 0.02 + 0.03 | ||
| expect(totalMessages).toBe(3); | ||
| }); | ||
|
|
||
| test('calculates session utilization and remaining sessions', async () => { | ||
| // Create test data with 3 sessions | ||
| const sessions = Array.from({ length: 3 }, (_, i) => ({ | ||
| timestamp: `2024-01-${String(i + 1).padStart(2, '0')}T00:00:00Z`, | ||
| message: { usage: { input_tokens: 100, output_tokens: 50 } }, | ||
| costUSD: 0.01, | ||
| })); | ||
|
|
||
| await using fixture = await createFixture({ | ||
| projects: { | ||
| project1: Object.fromEntries( | ||
| sessions.map((session, i) => [ | ||
| `session${i + 1}`, | ||
| { 'chat.jsonl': JSON.stringify(session) }, | ||
| ]), | ||
| ), | ||
| }, | ||
| }); | ||
|
|
||
| const result = await loadSessionWindowData({ claudePath: fixture.path }); | ||
|
|
||
| expect(result).toHaveLength(1); | ||
| expect(result[0]?.totalSessions).toBe(3); | ||
| expect(result[0]?.remainingSessions).toBe(47); // 50 - 3 | ||
| expect(result[0]?.utilizationPercent).toBe(6); // (3 / 50) * 100 | ||
| }); | ||
|
|
||
| test('handles sessions across multiple months', async () => { | ||
| const mockData: UsageData[] = [ | ||
| { | ||
| timestamp: '2024-01-15T00:00:00Z', | ||
| message: { usage: { input_tokens: 100, output_tokens: 50 } }, | ||
| costUSD: 0.01, | ||
| }, | ||
| { | ||
| timestamp: '2024-02-15T00:00:00Z', | ||
| message: { usage: { input_tokens: 200, output_tokens: 100 } }, | ||
| costUSD: 0.02, | ||
| }, | ||
| { | ||
| timestamp: '2024-03-15T00:00:00Z', | ||
| message: { usage: { input_tokens: 300, output_tokens: 150 } }, | ||
| costUSD: 0.03, | ||
| }, | ||
| ]; | ||
|
|
||
| await using fixture = await createFixture({ | ||
| projects: { | ||
| project1: Object.fromEntries( | ||
| mockData.map((data, i) => [ | ||
| `session${i + 1}`, | ||
| { 'chat.jsonl': JSON.stringify(data) }, | ||
| ]), | ||
| ), | ||
| }, | ||
| }); | ||
|
|
||
| const result = await loadSessionWindowData({ claudePath: fixture.path }); | ||
|
|
||
| expect(result).toHaveLength(3); // Three months | ||
|
|
||
| // Should be sorted by month descending (default) | ||
| expect(result[0]?.month).toBe('2024-03'); | ||
| expect(result[1]?.month).toBe('2024-02'); | ||
| expect(result[2]?.month).toBe('2024-01'); | ||
|
|
||
| // Each month should have 1 session | ||
| for (const monthData of result) { | ||
| expect(monthData.totalSessions).toBe(1); | ||
| expect(monthData.remainingSessions).toBe(49); | ||
| } | ||
| }); | ||
|
|
||
| test('tracks conversation count per window', async () => { | ||
| const mockData1: UsageData = { | ||
| timestamp: '2024-01-01T00:00:00Z', | ||
| message: { usage: { input_tokens: 100, output_tokens: 50 } }, | ||
| costUSD: 0.01, | ||
| }; | ||
|
|
||
| const mockData2: UsageData = { | ||
| timestamp: '2024-01-01T01:00:00Z', // Same window, different conversation | ||
| message: { usage: { input_tokens: 200, output_tokens: 100 } }, | ||
| costUSD: 0.02, | ||
| }; | ||
|
|
||
| await using fixture = await createFixture({ | ||
| projects: { | ||
| project1: { | ||
| conversation1: { | ||
| 'chat.jsonl': JSON.stringify(mockData1), | ||
| }, | ||
| conversation2: { | ||
| 'chat.jsonl': JSON.stringify(mockData2), | ||
| }, | ||
| }, | ||
| }, | ||
| }); | ||
|
|
||
| const result = await loadSessionWindowData({ claudePath: fixture.path }); | ||
|
|
||
| expect(result).toHaveLength(1); | ||
| const window = result[0]?.windows[0]; | ||
| expect(window?.conversationCount).toBe(2); // Two different conversations | ||
| expect(window?.messageCount).toBe(2); // Two total messages | ||
| }); | ||
|
|
||
| test('calculates average costs and tokens per session', async () => { | ||
| const sessions = [ | ||
| { | ||
| timestamp: '2024-01-01T00:00:00Z', | ||
| message: { usage: { input_tokens: 100, output_tokens: 50 } }, | ||
| costUSD: 0.01, | ||
| }, | ||
| { | ||
| timestamp: '2024-01-02T00:00:00Z', | ||
| message: { usage: { input_tokens: 300, output_tokens: 150 } }, | ||
| costUSD: 0.03, | ||
| }, | ||
| ]; | ||
|
|
||
| await using fixture = await createFixture({ | ||
| projects: { | ||
| project1: Object.fromEntries( | ||
| sessions.map((session, i) => [ | ||
| `session${i + 1}`, | ||
| { 'chat.jsonl': JSON.stringify(session) }, | ||
| ]), | ||
| ), | ||
| }, | ||
| }); | ||
|
|
||
| const result = await loadSessionWindowData({ claudePath: fixture.path }); | ||
|
|
||
| expect(result).toHaveLength(1); | ||
| const monthData = result[0]; | ||
| expect(monthData?.totalSessions).toBe(2); | ||
| expect(monthData?.totalCost).toBe(0.04); // 0.01 + 0.03 | ||
| expect(monthData?.totalTokens).toBe(600); // 150 + 450 | ||
| expect(monthData?.averageCostPerSession).toBe(0.02); // 0.04 / 2 | ||
| expect(monthData?.averageTokensPerSession).toBe(300); // 600 / 2 | ||
| }); | ||
|
|
||
| test('handles cache tokens correctly', async () => { | ||
| const mockData: UsageData = { | ||
| timestamp: '2024-01-01T00:00:00Z', | ||
| message: { | ||
| usage: { | ||
| input_tokens: 100, | ||
| output_tokens: 50, | ||
| cache_creation_input_tokens: 25, | ||
| cache_read_input_tokens: 10, | ||
| }, | ||
| }, | ||
| costUSD: 0.01, | ||
| }; | ||
|
|
||
| await using fixture = await createFixture({ | ||
| projects: { | ||
| project1: { | ||
| session1: { | ||
| 'chat.jsonl': JSON.stringify(mockData), | ||
| }, | ||
| }, | ||
| }, | ||
| }); | ||
|
|
||
| const result = await loadSessionWindowData({ claudePath: fixture.path }); | ||
|
|
||
| expect(result).toHaveLength(1); | ||
| const window = result[0]?.windows[0]; | ||
| expect(window?.inputTokens).toBe(100); | ||
| expect(window?.outputTokens).toBe(50); | ||
| expect(window?.cacheCreationTokens).toBe(25); | ||
| expect(window?.cacheReadTokens).toBe(10); | ||
| }); | ||
|
|
||
| test('filters by date range', async () => { | ||
| const sessions = [ | ||
| { | ||
| timestamp: '2024-01-01T00:00:00Z', | ||
| message: { usage: { input_tokens: 100, output_tokens: 50 } }, | ||
| costUSD: 0.01, | ||
| }, | ||
| { | ||
| timestamp: '2024-01-15T00:00:00Z', | ||
| message: { usage: { input_tokens: 200, output_tokens: 100 } }, | ||
| costUSD: 0.02, | ||
| }, | ||
| { | ||
| timestamp: '2024-01-31T00:00:00Z', | ||
| message: { usage: { input_tokens: 300, output_tokens: 150 } }, | ||
| costUSD: 0.03, | ||
| }, | ||
| ]; | ||
|
|
||
| await using fixture = await createFixture({ | ||
| projects: { | ||
| project1: Object.fromEntries( | ||
| sessions.map((session, i) => [ | ||
| `session${i + 1}`, | ||
| { 'chat.jsonl': JSON.stringify(session) }, | ||
| ]), | ||
| ), | ||
| }, | ||
| }); | ||
|
|
||
| const result = await loadSessionWindowData({ | ||
| claudePath: fixture.path, | ||
| since: '20240110', | ||
| until: '20240125', | ||
| }); | ||
|
|
||
| expect(result).toHaveLength(1); | ||
| expect(result[0]?.totalSessions).toBe(1); // Only the middle session | ||
| expect(result[0]?.windows[0]?.inputTokens).toBe(200); | ||
| }); | ||
|
|
||
| test('sorts monthly stats by month order', async () => { | ||
| const sessions = [ | ||
| { | ||
| timestamp: '2024-02-01T00:00:00Z', | ||
| message: { usage: { input_tokens: 200, output_tokens: 100 } }, | ||
| costUSD: 0.02, | ||
| }, | ||
| { | ||
| timestamp: '2024-01-01T00:00:00Z', | ||
| message: { usage: { input_tokens: 100, output_tokens: 50 } }, | ||
| costUSD: 0.01, | ||
| }, | ||
| { | ||
| timestamp: '2024-03-01T00:00:00Z', | ||
| message: { usage: { input_tokens: 300, output_tokens: 150 } }, | ||
| costUSD: 0.03, | ||
| }, | ||
| ]; | ||
|
|
||
| await using fixture = await createFixture({ | ||
| projects: { | ||
| project1: Object.fromEntries( | ||
| sessions.map((session, i) => [ | ||
| `session${i + 1}`, | ||
| { 'chat.jsonl': JSON.stringify(session) }, | ||
| ]), | ||
| ), | ||
| }, | ||
| }); | ||
|
|
||
| // Test descending order (default) | ||
| const descResult = await loadSessionWindowData({ | ||
| claudePath: fixture.path, | ||
| order: 'desc', | ||
| }); | ||
| expect(descResult.map(r => r.month)).toEqual(['2024-03', '2024-02', '2024-01']); | ||
|
|
||
| // Test ascending order | ||
| const ascResult = await loadSessionWindowData({ | ||
| claudePath: fixture.path, | ||
| order: 'asc', | ||
| }); | ||
| expect(ascResult.map(r => r.month)).toEqual(['2024-01', '2024-02', '2024-03']); | ||
| }); | ||
|
|
||
| test('handles edge case with exactly 50 sessions', async () => { | ||
| // Create exactly 50 sessions | ||
| const sessions = Array.from({ length: 50 }, (_, i) => ({ | ||
| timestamp: `2024-01-${String(Math.floor(i / 2) + 1).padStart(2, '0')}T${String((i % 2) * 12).padStart(2, '0')}:00:00Z`, | ||
| message: { usage: { input_tokens: 100, output_tokens: 50 } }, | ||
| costUSD: 0.01, | ||
| })); | ||
|
|
||
| await using fixture = await createFixture({ | ||
| projects: { | ||
| project1: Object.fromEntries( | ||
| sessions.map((session, i) => [ | ||
| `session${i + 1}`, | ||
| { 'chat.jsonl': JSON.stringify(session) }, | ||
| ]), | ||
| ), | ||
| }, | ||
| }); | ||
|
|
||
| const result = await loadSessionWindowData({ claudePath: fixture.path }); | ||
|
|
||
| expect(result).toHaveLength(1); | ||
| expect(result[0]?.totalSessions).toBe(50); | ||
| expect(result[0]?.remainingSessions).toBe(0); // Exactly at limit | ||
| expect(result[0]?.utilizationPercent).toBe(100); // 100% utilization | ||
| }); | ||
| }); |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Consider parameterizing the session limit in tests.
The test suite assumes a fixed session limit of 50 throughout, but according to the PR objectives, different subscription plans have different session limits. Consider making the session limit configurable in tests to ensure the implementation works correctly for all plan types.
For example, in the test starting at line 1871:
- test('calculates session utilization and remaining sessions', async () => {
+ test('calculates session utilization and remaining sessions', async () => {
+ const sessionLimit = 50; // Make this configurable based on plan type
// Create test data with 3 sessions
const sessions = Array.from({ length: 3 }, (_, i) => ({
timestamp: `2024-01-${String(i + 1).padStart(2, '0')}T00:00:00Z`,
message: { usage: { input_tokens: 100, output_tokens: 50 } },
costUSD: 0.01,
}));
await using fixture = await createFixture({
projects: {
project1: Object.fromEntries(
sessions.map((session, i) => [
`session${i + 1}`,
{ 'chat.jsonl': JSON.stringify(session) },
]),
),
},
});
- const result = await loadSessionWindowData({ claudePath: fixture.path });
+ const result = await loadSessionWindowData({
+ claudePath: fixture.path,
+ sessionLimit: sessionLimit
+ });
expect(result).toHaveLength(1);
expect(result[0]?.totalSessions).toBe(3);
- expect(result[0]?.remainingSessions).toBe(47); // 50 - 3
- expect(result[0]?.utilizationPercent).toBe(6); // (3 / 50) * 100
+ expect(result[0]?.remainingSessions).toBe(sessionLimit - 3);
+ expect(result[0]?.utilizationPercent).toBe((3 / sessionLimit) * 100);
});Similarly, update the edge case test at line 2134:
- test('handles edge case with exactly 50 sessions', async () => {
- // Create exactly 50 sessions
- const sessions = Array.from({ length: 50 }, (_, i) => ({
+ test.each([
+ { planName: '$100 plan', sessionLimit: 50 },
+ { planName: '$200 plan', sessionLimit: 100 }, // Adjust based on actual limit
+ ])('handles edge case with exactly maximum sessions for $planName', async ({ sessionLimit }) => {
+ // Create exactly sessionLimit sessions
+ const sessions = Array.from({ length: sessionLimit }, (_, i) => ({📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| describe('loadSessionWindowData', () => { | |
| test('returns empty array when no files found', async () => { | |
| await using fixture = await createFixture({ | |
| projects: {}, | |
| }); | |
| const result = await loadSessionWindowData({ claudePath: fixture.path }); | |
| expect(result).toEqual([]); | |
| }); | |
| test('groups messages into 5-hour session windows', async () => { | |
| // Create test data with messages spread across different times | |
| const mockData: UsageData[] = [ | |
| { | |
| timestamp: '2024-01-01T00:00:00Z', // Window 1: 00:00-05:00 | |
| message: { usage: { input_tokens: 100, output_tokens: 50 } }, | |
| costUSD: 0.01, | |
| }, | |
| { | |
| timestamp: '2024-01-01T02:00:00Z', // Same window (within 5 hours) | |
| message: { usage: { input_tokens: 200, output_tokens: 100 } }, | |
| costUSD: 0.02, | |
| }, | |
| { | |
| timestamp: '2024-01-01T06:00:00Z', // Window 2: 05:00-10:00 | |
| message: { usage: { input_tokens: 300, output_tokens: 150 } }, | |
| costUSD: 0.03, | |
| }, | |
| ]; | |
| await using fixture = await createFixture({ | |
| projects: { | |
| project1: { | |
| session1: { | |
| 'chat.jsonl': mockData.map(d => JSON.stringify(d)).join('\n'), | |
| }, | |
| }, | |
| }, | |
| }); | |
| const result = await loadSessionWindowData({ claudePath: fixture.path }); | |
| expect(result).toHaveLength(1); // One month (2024-01) | |
| expect(result[0]?.month).toBe('2024-01'); | |
| expect(result[0]?.totalSessions).toBe(2); // Two 5-hour windows | |
| expect(result[0]?.windows).toHaveLength(2); | |
| const windows = result[0]?.windows ?? []; | |
| // Windows are sorted by startTime desc by default | |
| // The logic groups by first occurrence, so all messages from same conversation | |
| // Check total aggregation instead of individual windows | |
| const totalInputTokens = windows.reduce((sum, w) => sum + w.inputTokens, 0); | |
| const totalOutputTokens = windows.reduce((sum, w) => sum + w.outputTokens, 0); | |
| const totalCost = windows.reduce((sum, w) => sum + w.totalCost, 0); | |
| const totalMessages = windows.reduce((sum, w) => sum + w.messageCount, 0); | |
| expect(totalInputTokens).toBe(600); // 100 + 200 + 300 | |
| expect(totalOutputTokens).toBe(300); // 50 + 100 + 150 | |
| expect(totalCost).toBe(0.06); // 0.01 + 0.02 + 0.03 | |
| expect(totalMessages).toBe(3); | |
| }); | |
| test('calculates session utilization and remaining sessions', async () => { | |
| // Create test data with 3 sessions | |
| const sessions = Array.from({ length: 3 }, (_, i) => ({ | |
| timestamp: `2024-01-${String(i + 1).padStart(2, '0')}T00:00:00Z`, | |
| message: { usage: { input_tokens: 100, output_tokens: 50 } }, | |
| costUSD: 0.01, | |
| })); | |
| await using fixture = await createFixture({ | |
| projects: { | |
| project1: Object.fromEntries( | |
| sessions.map((session, i) => [ | |
| `session${i + 1}`, | |
| { 'chat.jsonl': JSON.stringify(session) }, | |
| ]), | |
| ), | |
| }, | |
| }); | |
| const result = await loadSessionWindowData({ claudePath: fixture.path }); | |
| expect(result).toHaveLength(1); | |
| expect(result[0]?.totalSessions).toBe(3); | |
| expect(result[0]?.remainingSessions).toBe(47); // 50 - 3 | |
| expect(result[0]?.utilizationPercent).toBe(6); // (3 / 50) * 100 | |
| }); | |
| test('handles sessions across multiple months', async () => { | |
| const mockData: UsageData[] = [ | |
| { | |
| timestamp: '2024-01-15T00:00:00Z', | |
| message: { usage: { input_tokens: 100, output_tokens: 50 } }, | |
| costUSD: 0.01, | |
| }, | |
| { | |
| timestamp: '2024-02-15T00:00:00Z', | |
| message: { usage: { input_tokens: 200, output_tokens: 100 } }, | |
| costUSD: 0.02, | |
| }, | |
| { | |
| timestamp: '2024-03-15T00:00:00Z', | |
| message: { usage: { input_tokens: 300, output_tokens: 150 } }, | |
| costUSD: 0.03, | |
| }, | |
| ]; | |
| await using fixture = await createFixture({ | |
| projects: { | |
| project1: Object.fromEntries( | |
| mockData.map((data, i) => [ | |
| `session${i + 1}`, | |
| { 'chat.jsonl': JSON.stringify(data) }, | |
| ]), | |
| ), | |
| }, | |
| }); | |
| const result = await loadSessionWindowData({ claudePath: fixture.path }); | |
| expect(result).toHaveLength(3); // Three months | |
| // Should be sorted by month descending (default) | |
| expect(result[0]?.month).toBe('2024-03'); | |
| expect(result[1]?.month).toBe('2024-02'); | |
| expect(result[2]?.month).toBe('2024-01'); | |
| // Each month should have 1 session | |
| for (const monthData of result) { | |
| expect(monthData.totalSessions).toBe(1); | |
| expect(monthData.remainingSessions).toBe(49); | |
| } | |
| }); | |
| test('tracks conversation count per window', async () => { | |
| const mockData1: UsageData = { | |
| timestamp: '2024-01-01T00:00:00Z', | |
| message: { usage: { input_tokens: 100, output_tokens: 50 } }, | |
| costUSD: 0.01, | |
| }; | |
| const mockData2: UsageData = { | |
| timestamp: '2024-01-01T01:00:00Z', // Same window, different conversation | |
| message: { usage: { input_tokens: 200, output_tokens: 100 } }, | |
| costUSD: 0.02, | |
| }; | |
| await using fixture = await createFixture({ | |
| projects: { | |
| project1: { | |
| conversation1: { | |
| 'chat.jsonl': JSON.stringify(mockData1), | |
| }, | |
| conversation2: { | |
| 'chat.jsonl': JSON.stringify(mockData2), | |
| }, | |
| }, | |
| }, | |
| }); | |
| const result = await loadSessionWindowData({ claudePath: fixture.path }); | |
| expect(result).toHaveLength(1); | |
| const window = result[0]?.windows[0]; | |
| expect(window?.conversationCount).toBe(2); // Two different conversations | |
| expect(window?.messageCount).toBe(2); // Two total messages | |
| }); | |
| test('calculates average costs and tokens per session', async () => { | |
| const sessions = [ | |
| { | |
| timestamp: '2024-01-01T00:00:00Z', | |
| message: { usage: { input_tokens: 100, output_tokens: 50 } }, | |
| costUSD: 0.01, | |
| }, | |
| { | |
| timestamp: '2024-01-02T00:00:00Z', | |
| message: { usage: { input_tokens: 300, output_tokens: 150 } }, | |
| costUSD: 0.03, | |
| }, | |
| ]; | |
| await using fixture = await createFixture({ | |
| projects: { | |
| project1: Object.fromEntries( | |
| sessions.map((session, i) => [ | |
| `session${i + 1}`, | |
| { 'chat.jsonl': JSON.stringify(session) }, | |
| ]), | |
| ), | |
| }, | |
| }); | |
| const result = await loadSessionWindowData({ claudePath: fixture.path }); | |
| expect(result).toHaveLength(1); | |
| const monthData = result[0]; | |
| expect(monthData?.totalSessions).toBe(2); | |
| expect(monthData?.totalCost).toBe(0.04); // 0.01 + 0.03 | |
| expect(monthData?.totalTokens).toBe(600); // 150 + 450 | |
| expect(monthData?.averageCostPerSession).toBe(0.02); // 0.04 / 2 | |
| expect(monthData?.averageTokensPerSession).toBe(300); // 600 / 2 | |
| }); | |
| test('handles cache tokens correctly', async () => { | |
| const mockData: UsageData = { | |
| timestamp: '2024-01-01T00:00:00Z', | |
| message: { | |
| usage: { | |
| input_tokens: 100, | |
| output_tokens: 50, | |
| cache_creation_input_tokens: 25, | |
| cache_read_input_tokens: 10, | |
| }, | |
| }, | |
| costUSD: 0.01, | |
| }; | |
| await using fixture = await createFixture({ | |
| projects: { | |
| project1: { | |
| session1: { | |
| 'chat.jsonl': JSON.stringify(mockData), | |
| }, | |
| }, | |
| }, | |
| }); | |
| const result = await loadSessionWindowData({ claudePath: fixture.path }); | |
| expect(result).toHaveLength(1); | |
| const window = result[0]?.windows[0]; | |
| expect(window?.inputTokens).toBe(100); | |
| expect(window?.outputTokens).toBe(50); | |
| expect(window?.cacheCreationTokens).toBe(25); | |
| expect(window?.cacheReadTokens).toBe(10); | |
| }); | |
| test('filters by date range', async () => { | |
| const sessions = [ | |
| { | |
| timestamp: '2024-01-01T00:00:00Z', | |
| message: { usage: { input_tokens: 100, output_tokens: 50 } }, | |
| costUSD: 0.01, | |
| }, | |
| { | |
| timestamp: '2024-01-15T00:00:00Z', | |
| message: { usage: { input_tokens: 200, output_tokens: 100 } }, | |
| costUSD: 0.02, | |
| }, | |
| { | |
| timestamp: '2024-01-31T00:00:00Z', | |
| message: { usage: { input_tokens: 300, output_tokens: 150 } }, | |
| costUSD: 0.03, | |
| }, | |
| ]; | |
| await using fixture = await createFixture({ | |
| projects: { | |
| project1: Object.fromEntries( | |
| sessions.map((session, i) => [ | |
| `session${i + 1}`, | |
| { 'chat.jsonl': JSON.stringify(session) }, | |
| ]), | |
| ), | |
| }, | |
| }); | |
| const result = await loadSessionWindowData({ | |
| claudePath: fixture.path, | |
| since: '20240110', | |
| until: '20240125', | |
| }); | |
| expect(result).toHaveLength(1); | |
| expect(result[0]?.totalSessions).toBe(1); // Only the middle session | |
| expect(result[0]?.windows[0]?.inputTokens).toBe(200); | |
| }); | |
| test('sorts monthly stats by month order', async () => { | |
| const sessions = [ | |
| { | |
| timestamp: '2024-02-01T00:00:00Z', | |
| message: { usage: { input_tokens: 200, output_tokens: 100 } }, | |
| costUSD: 0.02, | |
| }, | |
| { | |
| timestamp: '2024-01-01T00:00:00Z', | |
| message: { usage: { input_tokens: 100, output_tokens: 50 } }, | |
| costUSD: 0.01, | |
| }, | |
| { | |
| timestamp: '2024-03-01T00:00:00Z', | |
| message: { usage: { input_tokens: 300, output_tokens: 150 } }, | |
| costUSD: 0.03, | |
| }, | |
| ]; | |
| await using fixture = await createFixture({ | |
| projects: { | |
| project1: Object.fromEntries( | |
| sessions.map((session, i) => [ | |
| `session${i + 1}`, | |
| { 'chat.jsonl': JSON.stringify(session) }, | |
| ]), | |
| ), | |
| }, | |
| }); | |
| // Test descending order (default) | |
| const descResult = await loadSessionWindowData({ | |
| claudePath: fixture.path, | |
| order: 'desc', | |
| }); | |
| expect(descResult.map(r => r.month)).toEqual(['2024-03', '2024-02', '2024-01']); | |
| // Test ascending order | |
| const ascResult = await loadSessionWindowData({ | |
| claudePath: fixture.path, | |
| order: 'asc', | |
| }); | |
| expect(ascResult.map(r => r.month)).toEqual(['2024-01', '2024-02', '2024-03']); | |
| }); | |
| test('handles edge case with exactly 50 sessions', async () => { | |
| // Create exactly 50 sessions | |
| const sessions = Array.from({ length: 50 }, (_, i) => ({ | |
| timestamp: `2024-01-${String(Math.floor(i / 2) + 1).padStart(2, '0')}T${String((i % 2) * 12).padStart(2, '0')}:00:00Z`, | |
| message: { usage: { input_tokens: 100, output_tokens: 50 } }, | |
| costUSD: 0.01, | |
| })); | |
| await using fixture = await createFixture({ | |
| projects: { | |
| project1: Object.fromEntries( | |
| sessions.map((session, i) => [ | |
| `session${i + 1}`, | |
| { 'chat.jsonl': JSON.stringify(session) }, | |
| ]), | |
| ), | |
| }, | |
| }); | |
| const result = await loadSessionWindowData({ claudePath: fixture.path }); | |
| expect(result).toHaveLength(1); | |
| expect(result[0]?.totalSessions).toBe(50); | |
| expect(result[0]?.remainingSessions).toBe(0); // Exactly at limit | |
| expect(result[0]?.utilizationPercent).toBe(100); // 100% utilization | |
| }); | |
| }); | |
| // … lines above unchanged … | |
| test('calculates session utilization and remaining sessions', async () => { | |
| const sessionLimit = 50; // Make this configurable based on plan type | |
| // Create test data with 3 sessions | |
| const sessions = Array.from({ length: 3 }, (_, i) => ({ | |
| timestamp: `2024-01-${String(i + 1).padStart(2, '0')}T00:00:00Z`, | |
| message: { usage: { input_tokens: 100, output_tokens: 50 } }, | |
| costUSD: 0.01, | |
| })); | |
| await using fixture = await createFixture({ | |
| projects: { | |
| project1: Object.fromEntries( | |
| sessions.map((session, i) => [ | |
| `session${i + 1}`, | |
| { 'chat.jsonl': JSON.stringify(session) }, | |
| ]), | |
| ), | |
| }, | |
| }); | |
| const result = await loadSessionWindowData({ | |
| claudePath: fixture.path, | |
| sessionLimit: sessionLimit | |
| }); | |
| expect(result).toHaveLength(1); | |
| expect(result[0]?.totalSessions).toBe(3); | |
| expect(result[0]?.remainingSessions).toBe(sessionLimit - 3); | |
| expect(result[0]?.utilizationPercent).toBe((3 / sessionLimit) * 100); | |
| }); | |
| // … other tests … | |
| test.each([ | |
| { planName: '$100 plan', sessionLimit: 50 }, | |
| { planName: '$200 plan', sessionLimit: 100 }, // Adjust based on actual limit | |
| ])('handles edge case with exactly maximum sessions for %s', async ({ sessionLimit }) => { | |
| // Create exactly sessionLimit sessions | |
| const sessions = Array.from({ length: sessionLimit }, (_, i) => ({ | |
| timestamp: `2024-01-${String(Math.floor(i / 2) + 1).padStart(2, '0')}T${String((i % 2) * 12).padStart(2, '0')}:00:00Z`, | |
| message: { usage: { input_tokens: 100, output_tokens: 50 } }, | |
| costUSD: 0.01, | |
| })); | |
| await using fixture = await createFixture({ | |
| projects: { | |
| project1: Object.fromEntries( | |
| sessions.map((session, i) => [ | |
| `session${i + 1}`, | |
| { 'chat.jsonl': JSON.stringify(session) }, | |
| ]), | |
| ), | |
| }, | |
| }); | |
| const result = await loadSessionWindowData({ | |
| claudePath: fixture.path, | |
| sessionLimit: sessionLimit | |
| }); | |
| expect(result).toHaveLength(1); | |
| expect(result[0]?.totalSessions).toBe(sessionLimit); | |
| expect(result[0]?.remainingSessions).toBe(0); | |
| expect(result[0]?.utilizationPercent).toBe(100); | |
| }); |
🧰 Tools
🪛 ESLint
[error] 1809-1809: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1810-1810: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1811-1813: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 1811-1811: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1815-1815: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 1815-1815: Unsafe member access .path on an error typed value.
(ts/no-unsafe-member-access)
[error] 1816-1816: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1816-1816: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1816-1816: Unsafe member access .toEqual on an error typed value.
(ts/no-unsafe-member-access)
[error] 1819-1819: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1839-1847: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 1839-1839: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1849-1849: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 1849-1849: Unsafe member access .path on an error typed value.
(ts/no-unsafe-member-access)
[error] 1851-1851: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1851-1851: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1851-1851: Unsafe member access .toHaveLength on an error typed value.
(ts/no-unsafe-member-access)
[error] 1852-1852: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1852-1852: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1852-1852: Unsafe member access .month on an error typed value.
(ts/no-unsafe-member-access)
[error] 1852-1852: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 1853-1853: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1853-1853: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1853-1853: Unsafe member access .totalSessions on an error typed value.
(ts/no-unsafe-member-access)
[error] 1853-1853: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 1854-1854: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1854-1854: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1854-1854: Unsafe member access .windows on an error typed value.
(ts/no-unsafe-member-access)
[error] 1854-1854: Unsafe member access .toHaveLength on an error typed value.
(ts/no-unsafe-member-access)
[error] 1856-1856: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 1856-1856: Unsafe member access .windows on an error typed value.
(ts/no-unsafe-member-access)
[error] 1860-1860: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 1860-1860: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1860-1860: Unsafe member access .reduce on an error typed value.
(ts/no-unsafe-member-access)
[error] 1860-1860: Unsafe return of a value of type any.
(ts/no-unsafe-return)
[error] 1860-1860: Unsafe member access .inputTokens on an any value.
(ts/no-unsafe-member-access)
[error] 1861-1861: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 1861-1861: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1861-1861: Unsafe member access .reduce on an error typed value.
(ts/no-unsafe-member-access)
[error] 1861-1861: Unsafe return of a value of type any.
(ts/no-unsafe-return)
[error] 1861-1861: Unsafe member access .outputTokens on an any value.
(ts/no-unsafe-member-access)
[error] 1862-1862: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 1862-1862: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1862-1862: Unsafe member access .reduce on an error typed value.
(ts/no-unsafe-member-access)
[error] 1862-1862: Unsafe return of a value of type any.
(ts/no-unsafe-return)
[error] 1862-1862: Unsafe member access .totalCost on an any value.
(ts/no-unsafe-member-access)
[error] 1863-1863: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 1863-1863: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1863-1863: Unsafe member access .reduce on an error typed value.
(ts/no-unsafe-member-access)
[error] 1863-1863: Unsafe return of a value of type any.
(ts/no-unsafe-return)
[error] 1863-1863: Unsafe member access .messageCount on an any value.
(ts/no-unsafe-member-access)
[error] 1865-1865: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1865-1865: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1865-1865: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 1866-1866: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1866-1866: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1866-1866: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 1867-1867: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1867-1867: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1867-1867: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 1868-1868: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1868-1868: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1868-1868: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 1871-1871: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1879-1888: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 1879-1879: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1890-1890: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 1890-1890: Unsafe member access .path on an error typed value.
(ts/no-unsafe-member-access)
[error] 1892-1892: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1892-1892: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1892-1892: Unsafe member access .toHaveLength on an error typed value.
(ts/no-unsafe-member-access)
[error] 1893-1893: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1893-1893: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1893-1893: Unsafe member access .totalSessions on an error typed value.
(ts/no-unsafe-member-access)
[error] 1893-1893: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 1894-1894: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1894-1894: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1894-1894: Unsafe member access .remainingSessions on an error typed value.
(ts/no-unsafe-member-access)
[error] 1894-1894: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 1895-1895: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1895-1895: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1895-1895: Unsafe member access .utilizationPercent on an error typed value.
(ts/no-unsafe-member-access)
[error] 1895-1895: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 1898-1898: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1917-1926: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 1917-1917: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1928-1928: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 1928-1928: Unsafe member access .path on an error typed value.
(ts/no-unsafe-member-access)
[error] 1930-1930: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1930-1930: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1930-1930: Unsafe member access .toHaveLength on an error typed value.
(ts/no-unsafe-member-access)
[error] 1933-1933: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1933-1933: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1933-1933: Unsafe member access .month on an error typed value.
(ts/no-unsafe-member-access)
[error] 1933-1933: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 1934-1934: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1934-1934: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1934-1934: Unsafe member access .month on an error typed value.
(ts/no-unsafe-member-access)
[error] 1934-1934: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 1935-1935: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1935-1935: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1935-1935: Unsafe member access .month on an error typed value.
(ts/no-unsafe-member-access)
[error] 1935-1935: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 1939-1939: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1939-1939: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1939-1939: Unsafe member access .totalSessions on an error typed value.
(ts/no-unsafe-member-access)
[error] 1939-1939: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 1940-1940: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1940-1940: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1940-1940: Unsafe member access .remainingSessions on an error typed value.
(ts/no-unsafe-member-access)
[error] 1940-1940: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 1944-1944: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1957-1968: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 1957-1957: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1970-1970: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 1970-1970: Unsafe member access .path on an error typed value.
(ts/no-unsafe-member-access)
[error] 1972-1972: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1972-1972: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1972-1972: Unsafe member access .toHaveLength on an error typed value.
(ts/no-unsafe-member-access)
[error] 1973-1973: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 1973-1973: Unsafe member access .windows on an error typed value.
(ts/no-unsafe-member-access)
[error] 1974-1974: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1974-1974: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1974-1974: Unsafe member access .conversationCount on an error typed value.
(ts/no-unsafe-member-access)
[error] 1974-1974: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 1975-1975: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1975-1975: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1975-1975: Unsafe member access .messageCount on an error typed value.
(ts/no-unsafe-member-access)
[error] 1975-1975: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 1978-1978: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 1992-2001: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 1992-1992: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2003-2003: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 2003-2003: Unsafe member access .path on an error typed value.
(ts/no-unsafe-member-access)
[error] 2005-2005: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2005-2005: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2005-2005: Unsafe member access .toHaveLength on an error typed value.
(ts/no-unsafe-member-access)
[error] 2006-2006: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 2007-2007: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2007-2007: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2007-2007: Unsafe member access .totalSessions on an error typed value.
(ts/no-unsafe-member-access)
[error] 2007-2007: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 2008-2008: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2008-2008: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2008-2008: Unsafe member access .totalCost on an error typed value.
(ts/no-unsafe-member-access)
[error] 2008-2008: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 2009-2009: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2009-2009: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2009-2009: Unsafe member access .totalTokens on an error typed value.
(ts/no-unsafe-member-access)
[error] 2009-2009: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 2010-2010: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2010-2010: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2010-2010: Unsafe member access .averageCostPerSession on an error typed value.
(ts/no-unsafe-member-access)
[error] 2010-2010: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 2011-2011: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2011-2011: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2011-2011: Unsafe member access .averageTokensPerSession on an error typed value.
(ts/no-unsafe-member-access)
[error] 2011-2011: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 2014-2014: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2028-2036: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 2028-2028: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2038-2038: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 2038-2038: Unsafe member access .path on an error typed value.
(ts/no-unsafe-member-access)
[error] 2040-2040: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2040-2040: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2040-2040: Unsafe member access .toHaveLength on an error typed value.
(ts/no-unsafe-member-access)
[error] 2041-2041: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 2041-2041: Unsafe member access .windows on an error typed value.
(ts/no-unsafe-member-access)
[error] 2042-2042: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2042-2042: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2042-2042: Unsafe member access .inputTokens on an error typed value.
(ts/no-unsafe-member-access)
[error] 2042-2042: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 2043-2043: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2043-2043: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2043-2043: Unsafe member access .outputTokens on an error typed value.
(ts/no-unsafe-member-access)
[error] 2043-2043: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 2044-2044: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2044-2044: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2044-2044: Unsafe member access .cacheCreationTokens on an error typed value.
(ts/no-unsafe-member-access)
[error] 2044-2044: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 2045-2045: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2045-2045: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2045-2045: Unsafe member access .cacheReadTokens on an error typed value.
(ts/no-unsafe-member-access)
[error] 2045-2045: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 2048-2048: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2067-2076: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 2067-2067: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2079-2079: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 2079-2079: Unsafe member access .path on an error typed value.
(ts/no-unsafe-member-access)
[error] 2084-2084: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2084-2084: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2084-2084: Unsafe member access .toHaveLength on an error typed value.
(ts/no-unsafe-member-access)
[error] 2085-2085: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2085-2085: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2085-2085: Unsafe member access .totalSessions on an error typed value.
(ts/no-unsafe-member-access)
[error] 2085-2085: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 2086-2086: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2086-2086: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2086-2086: Unsafe member access .windows on an error typed value.
(ts/no-unsafe-member-access)
[error] 2086-2086: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 2089-2089: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2108-2117: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 2108-2108: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2121-2121: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 2121-2121: Unsafe member access .path on an error typed value.
(ts/no-unsafe-member-access)
[error] 2124-2124: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2124-2124: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2124-2124: Unsafe return of a value of type error.
(ts/no-unsafe-return)
[error] 2124-2124: Unsafe member access .month on an error typed value.
(ts/no-unsafe-member-access)
[error] 2124-2124: Unsafe member access .toEqual on an error typed value.
(ts/no-unsafe-member-access)
[error] 2128-2128: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 2128-2128: Unsafe member access .path on an error typed value.
(ts/no-unsafe-member-access)
[error] 2131-2131: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2131-2131: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2131-2131: Unsafe return of a value of type error.
(ts/no-unsafe-return)
[error] 2131-2131: Unsafe member access .month on an error typed value.
(ts/no-unsafe-member-access)
[error] 2131-2131: Unsafe member access .toEqual on an error typed value.
(ts/no-unsafe-member-access)
[error] 2134-2134: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2142-2151: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 2142-2142: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2153-2153: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 2153-2153: Unsafe member access .path on an error typed value.
(ts/no-unsafe-member-access)
[error] 2155-2155: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2155-2155: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2155-2155: Unsafe member access .toHaveLength on an error typed value.
(ts/no-unsafe-member-access)
[error] 2156-2156: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2156-2156: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2156-2156: Unsafe member access .totalSessions on an error typed value.
(ts/no-unsafe-member-access)
[error] 2156-2156: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 2157-2157: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2157-2157: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2157-2157: Unsafe member access .remainingSessions on an error typed value.
(ts/no-unsafe-member-access)
[error] 2157-2157: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
[error] 2158-2158: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2158-2158: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
[error] 2158-2158: Unsafe member access .utilizationPercent on an error typed value.
(ts/no-unsafe-member-access)
[error] 2158-2158: Unsafe member access .toBe on an error typed value.
(ts/no-unsafe-member-access)
🤖 Prompt for AI Agents
In src/data-loader.test.ts around lines 1871 and 2134, the tests assume a fixed
session limit of 50, but the session limit should be parameterized to reflect
different subscription plans. Modify the tests to accept a configurable session
limit parameter and use it in assertions and calculations instead of hardcoding
50. Update the test setup and expectations accordingly to verify behavior for
various session limits.
| const totalSessions = windows.length; | ||
| const sessionLimit = options?.sessionLimit ?? 50; | ||
| const remainingSessions = Math.max(0, sessionLimit - totalSessions); |
There was a problem hiding this comment.
Make session limit configurable based on subscription plan.
The session limit is currently hardcoded to 50, which only applies to the $100 plan. According to the PR objectives, different plans have different session limits. This should be made more flexible.
Consider:
- Passing the correct session limit based on the user's subscription plan
- Adding plan detection logic or accepting plan type as a parameter
- Documenting the session limits for each plan type
const totalSessions = windows.length;
-const sessionLimit = options?.sessionLimit ?? 50;
+// TODO: Determine session limit based on user's subscription plan
+// $100 plan: 50 sessions/month
+// $200 plan: different limit (needs clarification)
+const sessionLimit = options?.sessionLimit ?? 50;
const remainingSessions = Math.max(0, sessionLimit - totalSessions);Would you like me to help implement a solution that detects the user's subscription plan and applies the correct session limit automatically?
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const totalSessions = windows.length; | |
| const sessionLimit = options?.sessionLimit ?? 50; | |
| const remainingSessions = Math.max(0, sessionLimit - totalSessions); | |
| const totalSessions = windows.length; | |
| // TODO: Determine session limit based on user's subscription plan | |
| // $100 plan: 50 sessions/month | |
| // $200 plan: different limit (needs clarification) | |
| const sessionLimit = options?.sessionLimit ?? 50; | |
| const remainingSessions = Math.max(0, sessionLimit - totalSessions); |
🤖 Prompt for AI Agents
In src/data-loader.ts around lines 760 to 762, the session limit is hardcoded to
50, which only fits the $100 plan. To fix this, modify the code to determine the
session limit dynamically based on the user's subscription plan. Implement logic
to detect or accept the user's plan type as a parameter, then set the
sessionLimit accordingly for each plan. Also, update documentation to clearly
specify the session limits for each subscription plan.
|
so I think we think about the real limitation. there are conflicts btw, please mention me when you finish refactoring |
|
@EphemeralSapient I came up an idea. If you can do so, please do. Otherwise, I'll do it. |
|
ah sorry, been busy with college; and sure! i'll try and let you know |
|
after using it a while; I found inconsistent values on window start timing, I didn't notice it earlier Honestly I'm not sure what to do here 😖 |
OMG Thank you for investigating. Well if you cannot make sure that it is correct, we gonna suspend this PR. but thank you for you work |
|
sorry for the mess, I'll be closing this PR Have a nice day |
|
@EphemeralSapient thank you for your contribution! |
A huge mess, made mistake and don't look at this PR
My bad, I've learnt my lesson