Skip to content

5 hour session window usage info - #55

Closed
EphemeralSapient wants to merge 3 commits into
ccusage:mainfrom
EphemeralSapient:main
Closed

EphemeralSapient wants to merge 3 commits into
ccusage:mainfrom
EphemeralSapient:main

Conversation

@EphemeralSapient

@EphemeralSapient EphemeralSapient commented Jun 11, 2025 •

Copy link
Copy Markdown

A huge mess, made mistake and don't look at this PR

My bad, I've learnt my lesson

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 sessions command 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, --until for date filtering, --json for machine-readable output, --mode for cost calculation, and --order for 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

  1. 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. ↩

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread src/data-loader.ts

const totals = windows.reduce((acc, window) => ({
cost: acc.cost + window.totalCost,
tokens: acc.tokens + window.inputTokens + window.outputTokens,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

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,

Comment thread README.md
Comment on lines +223 to +224
ccusage sessions --order asc # Show oldest months first
ccusage sessions --order desc # Show newest months first (default)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

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:

  1. Changing the default for order in src/shared-args.internal.ts to desc if this is the preferred default for most/all commands.
  2. Overriding the default for the order argument specifically within the sessionsCommand definition in src/commands/sessions.ts.
  3. Updating this documentation to reflect asc as the default.

Comment thread src/data-loader.ts
Comment on lines +590 to +593
while (sessionWindows.has(newWindowId)) {
newWindowStart = new Date(newWindowStart.getTime() + 5 * 60 * 60 * 1000);
newWindowId = getSessionWindowId(newWindowStart.toISOString());
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

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.

Comment thread src/data-loader.ts
Comment on lines +679 to +683
const sortOrder = options?.order ?? 'desc';
const sortedStats = sort(monthlyStats);
return sortOrder === 'desc'
? sortedStats.desc(item => item.month)
: sortedStats.asc(item => item.month);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

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.

@ryoppippi

Copy link
Copy Markdown
Member

@EphemeralSapient Hi
Thank you for this PR. Awesome.

I found that there is a magic number remainingSessions. 50 session limit is only for $100 plan and $200 plan has different limitation, right? If I'm wrong explain it.

Comment thread src/commands/sessions.ts Outdated

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) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what does 5 mean?

Comment thread src/types.internal.ts Outdated
Comment on lines +14 to +55

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>;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can define those types in data-loader.ts because we don't use it in other files.
also you can stop exporting it

@pkg-pr-new

pkg-pr-new Bot commented Jun 11, 2025

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/ryoppippi/ccusage@55

commit: 94bd31e

@ryoppippi
ryoppippi requested a review from Copilot June 11, 2025 11:12

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 sessions command, 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

Comment thread src/data-loader.ts

const newWindow = {
windowId: newWindowId,
startTime: entry.timestamp,

Copilot AI Jun 11, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
startTime: entry.timestamp,
startTime: newWindowStart,

Copilot uses AI. Check for mistakes.
Comment thread src/commands/sessions.ts Outdated
+ window.cacheCreationTokens + window.cacheReadTokens;

windowsTable.push([
startTime.toLocaleString().substring(0, 16), // Remove seconds

Copilot AI Jun 11, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[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.

Suggested change
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

Copilot uses AI. Check for mistakes.
@EphemeralSapient

Copy link
Copy Markdown
Author

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

@coderabbitai

coderabbitai Bot commented Jun 11, 2025 •

Copy link
Copy Markdown

Walkthrough

A 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

File(s) Change Summary
README.md Added documentation for "Session Windows Report" and updated CLI usage, tool listings, and output examples.
package.json Reformatted file from tab to space indentation; no content changes.
src/commands/index.ts Imported and registered the new sessionsCommand in the CLI subCommands map.
src/commands/sessions.ts Added new CLI command for session window reporting, supporting JSON and formatted output, and session limit tracking.
src/data-loader.ts Added logic for 5-hour session window grouping, aggregation, statistics, and new types; extended loader options.
src/data-loader.test.ts Added extensive tests for session window data loading, aggregation, and edge cases.
src/shared-args.internal.ts Changed default sort order to 'desc'; added sessionLimit and warningThreshold arguments with defaults.

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
Loading

Poem

In five-hour windows, the sessions align,
Counting each token, each message, in time.
Fifty per month—watch the colors appear,
As limits approach, the warnings draw near.
Now Max plan users can clearly see,
Their session adventures in usage history!
🐇✨

✨ Finishing Touches
  • 📝 Generate Docstrings

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.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need 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)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

♻️ Duplicate comments (2)
src/data-loader.ts (2)

765-768: ⚠️ Potential issue

Include all token types in monthly total tokens calculation.

The totalTokens calculation currently only sums inputTokens and outputTokens, but cache tokens (cacheCreationTokens and cacheReadTokens) 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 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)


689-708: ⚠️ Potential issue

Fix window start time to match the computed window ID.

When a new window ID is computed after collision detection, the window's startTime should be set to newWindowStart to 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) 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)

🧹 Nitpick comments (3)
README.md (1)

365-394: Add language tag to fenced block

Markdown-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: totalTokens recomputed but already available

window.totalTokens exists 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 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)


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-DD

Maintains 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 error typed value.

(ts/no-unsafe-member-access)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6f9836d and 089a153.

📒 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 docs

Switching the default from asc to desc finally 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.json without altering dependencies, scripts, or configuration. This aligns with the project's style rules.

Comment thread src/commands/index.ts
Comment on lines +8 to 16
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);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ 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 windows

or 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.

Suggested change
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.

Comment on lines +67 to +76
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,
},

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ 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.

Suggested change
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.

Comment thread src/commands/sessions.ts
Comment on lines +29 to +37
if (sessionData.length === 0) {
if (ctx.values.json) {
log(JSON.stringify([]));
}
else {
logger.warn('No Claude usage data found.');
}
process.exit(0);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

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.

Suggested change
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.

Comment thread src/commands/sessions.ts
Comment on lines +14 to +27
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,
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ 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.

Suggested change
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.

Comment thread src/data-loader.test.ts
Comment on lines +1809 to +2160
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
});
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ 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.

Suggested change
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.

Comment thread src/data-loader.ts
Comment on lines +760 to +762
const totalSessions = windows.length;
const sessionLimit = options?.sessionLimit ?? 50;
const remainingSessions = Math.max(0, sessionLimit - totalSessions);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

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:

  1. Passing the correct session limit based on the user's subscription plan
  2. Adding plan detection logic or accepting plan type as a parameter
  3. 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.

Suggested change
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.

@ryoppippi

Copy link
Copy Markdown
Member

so I think we think about the real limitation.
5 hours limitation may be okay.

there are conflicts btw, please mention me when you finish refactoring

@ryoppippi

ryoppippi commented Jun 11, 2025 •

Copy link
Copy Markdown
Member

@EphemeralSapient I came up an idea.
Instead of creating new sub-command, how about add --current option to session sub-command?

If you can do so, please do. Otherwise, I'll do it.

@EphemeralSapient

Copy link
Copy Markdown
Author

ah sorry, been busy with college; and sure! i'll try and let you know

@EphemeralSapient

Copy link
Copy Markdown
Author

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 😖

@ryoppippi

Copy link
Copy Markdown
Member

after using it a while; I found inconsistent values on window start timing, I didn't notice it earlier

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

@EphemeralSapient

Copy link
Copy Markdown
Author

sorry for the mess, I'll be closing this PR

Have a nice day

@ryoppippi

Copy link
Copy Markdown
Member

@EphemeralSapient thank you for your contribution!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants