@tokscale/cli 1.0.17 → 1.0.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/dist/cli.js +214 -91
  2. package/dist/cli.js.map +1 -1
  3. package/dist/graph-types.d.ts +1 -1
  4. package/dist/graph-types.d.ts.map +1 -1
  5. package/dist/native-runner.d.ts +1 -2
  6. package/dist/native-runner.d.ts.map +1 -1
  7. package/dist/native-runner.js +11 -39
  8. package/dist/native-runner.js.map +1 -1
  9. package/dist/native.d.ts +9 -30
  10. package/dist/native.d.ts.map +1 -1
  11. package/dist/native.js +31 -138
  12. package/dist/native.js.map +1 -1
  13. package/dist/sessions/types.d.ts +1 -1
  14. package/dist/sessions/types.d.ts.map +1 -1
  15. package/dist/submit.d.ts +2 -0
  16. package/dist/submit.d.ts.map +1 -1
  17. package/dist/submit.js +32 -16
  18. package/dist/submit.js.map +1 -1
  19. package/dist/tui/App.d.ts.map +1 -1
  20. package/dist/tui/App.js +14 -7
  21. package/dist/tui/App.js.map +1 -1
  22. package/dist/tui/components/DailyView.d.ts.map +1 -1
  23. package/dist/tui/components/DailyView.js +25 -8
  24. package/dist/tui/components/DailyView.js.map +1 -1
  25. package/dist/tui/components/DateBreakdownPanel.js +2 -2
  26. package/dist/tui/components/DateBreakdownPanel.js.map +1 -1
  27. package/dist/tui/components/Footer.d.ts.map +1 -1
  28. package/dist/tui/components/Footer.js +2 -3
  29. package/dist/tui/components/Footer.js.map +1 -1
  30. package/dist/tui/components/LoadingSpinner.d.ts.map +1 -1
  31. package/dist/tui/components/LoadingSpinner.js +1 -2
  32. package/dist/tui/components/LoadingSpinner.js.map +1 -1
  33. package/dist/tui/components/ModelView.js +2 -2
  34. package/dist/tui/components/ModelView.js.map +1 -1
  35. package/dist/tui/config/settings.d.ts +4 -4
  36. package/dist/tui/config/settings.d.ts.map +1 -1
  37. package/dist/tui/config/settings.js +11 -4
  38. package/dist/tui/config/settings.js.map +1 -1
  39. package/dist/tui/hooks/useData.d.ts.map +1 -1
  40. package/dist/tui/hooks/useData.js +29 -42
  41. package/dist/tui/hooks/useData.js.map +1 -1
  42. package/dist/tui/types/index.d.ts +2 -2
  43. package/dist/tui/types/index.d.ts.map +1 -1
  44. package/dist/tui/types/index.js +3 -1
  45. package/dist/tui/types/index.js.map +1 -1
  46. package/dist/tui/utils/colors.d.ts +1 -0
  47. package/dist/tui/utils/colors.d.ts.map +1 -1
  48. package/dist/tui/utils/colors.js +7 -0
  49. package/dist/tui/utils/colors.js.map +1 -1
  50. package/dist/wrapped.d.ts.map +1 -1
  51. package/dist/wrapped.js +20 -48
  52. package/dist/wrapped.js.map +1 -1
  53. package/package.json +2 -2
  54. package/src/cli.ts +232 -97
  55. package/src/graph-types.ts +1 -1
  56. package/src/native-runner.js +4 -0
  57. package/src/native-runner.ts +12 -42
  58. package/src/native.ts +47 -207
  59. package/src/sessions/types.ts +1 -1
  60. package/src/submit.ts +36 -22
  61. package/src/tui/App.tsx +10 -7
  62. package/src/tui/components/DailyView.tsx +29 -11
  63. package/src/tui/components/DateBreakdownPanel.tsx +2 -2
  64. package/src/tui/components/Footer.tsx +7 -2
  65. package/src/tui/components/LoadingSpinner.tsx +1 -2
  66. package/src/tui/components/ModelView.tsx +2 -2
  67. package/src/tui/config/settings.ts +18 -9
  68. package/src/tui/hooks/useData.ts +36 -47
  69. package/src/tui/types/index.ts +5 -4
  70. package/src/tui/utils/colors.ts +7 -0
  71. package/src/wrapped.ts +21 -54
  72. package/dist/graph.d.ts +0 -29
  73. package/dist/graph.d.ts.map +0 -1
  74. package/dist/graph.js +0 -383
  75. package/dist/graph.js.map +0 -1
  76. package/dist/pricing.d.ts +0 -58
  77. package/dist/pricing.d.ts.map +0 -1
  78. package/dist/pricing.js +0 -232
  79. package/dist/pricing.js.map +0 -1
  80. package/dist/sessions/claudecode.d.ts +0 -8
  81. package/dist/sessions/claudecode.d.ts.map +0 -1
  82. package/dist/sessions/claudecode.js +0 -84
  83. package/dist/sessions/claudecode.js.map +0 -1
  84. package/dist/sessions/codex.d.ts +0 -8
  85. package/dist/sessions/codex.d.ts.map +0 -1
  86. package/dist/sessions/codex.js +0 -158
  87. package/dist/sessions/codex.js.map +0 -1
  88. package/dist/sessions/gemini.d.ts +0 -8
  89. package/dist/sessions/gemini.d.ts.map +0 -1
  90. package/dist/sessions/gemini.js +0 -66
  91. package/dist/sessions/gemini.js.map +0 -1
  92. package/dist/sessions/index.d.ts +0 -32
  93. package/dist/sessions/index.d.ts.map +0 -1
  94. package/dist/sessions/index.js +0 -96
  95. package/dist/sessions/index.js.map +0 -1
  96. package/dist/sessions/opencode.d.ts +0 -9
  97. package/dist/sessions/opencode.d.ts.map +0 -1
  98. package/dist/sessions/opencode.js +0 -69
  99. package/dist/sessions/opencode.js.map +0 -1
  100. package/dist/sessions/reports.d.ts +0 -58
  101. package/dist/sessions/reports.d.ts.map +0 -1
  102. package/dist/sessions/reports.js +0 -337
  103. package/dist/sessions/reports.js.map +0 -1
  104. package/src/graph.ts +0 -485
  105. package/src/pricing.ts +0 -309
  106. package/src/sessions/claudecode.ts +0 -119
  107. package/src/sessions/codex.ts +0 -227
  108. package/src/sessions/gemini.ts +0 -108
  109. package/src/sessions/index.ts +0 -126
  110. package/src/sessions/opencode.ts +0 -117
  111. package/src/sessions/reports.ts +0 -475
@@ -1,108 +0,0 @@
1
- /**
2
- * Gemini CLI session parser
3
- * Reads from ~/.gemini/tmp/{projectHash}/chats/session-*.json
4
- */
5
-
6
- import * as fs from "node:fs";
7
- import * as path from "node:path";
8
- import * as os from "node:os";
9
- import { createUnifiedMessage, type UnifiedMessage, type TokenBreakdown } from "./types.js";
10
-
11
- interface GeminiMessage {
12
- id: string;
13
- timestamp: string;
14
- type: "user" | "gemini";
15
- content: string;
16
- tokens?: {
17
- input: number;
18
- output: number;
19
- cached: number;
20
- thoughts: number;
21
- tool: number;
22
- total: number;
23
- };
24
- model?: string;
25
- }
26
-
27
- interface GeminiSession {
28
- sessionId: string;
29
- projectHash: string;
30
- startTime: string;
31
- lastUpdated: string;
32
- messages: GeminiMessage[];
33
- }
34
-
35
- export function getGeminiBasePath(): string {
36
- return path.join(os.homedir(), ".gemini");
37
- }
38
-
39
- export function parseGeminiMessages(): UnifiedMessage[] {
40
- const basePath = getGeminiBasePath();
41
- const tmpPath = path.join(basePath, "tmp");
42
-
43
- if (!fs.existsSync(tmpPath)) {
44
- return [];
45
- }
46
-
47
- const messages: UnifiedMessage[] = [];
48
-
49
- try {
50
- // Find all project directories
51
- const projectDirs = fs
52
- .readdirSync(tmpPath, { withFileTypes: true })
53
- .filter((d) => d.isDirectory())
54
- .map((d) => path.join(tmpPath, d.name));
55
-
56
- for (const projectDir of projectDirs) {
57
- const chatsDir = path.join(projectDir, "chats");
58
- if (!fs.existsSync(chatsDir)) continue;
59
-
60
- // Find all session JSON files
61
- const sessionFiles = fs
62
- .readdirSync(chatsDir)
63
- .filter((f) => f.startsWith("session-") && f.endsWith(".json"));
64
-
65
- for (const sessionFile of sessionFiles) {
66
- try {
67
- const content = fs.readFileSync(path.join(chatsDir, sessionFile), "utf-8");
68
- const session = JSON.parse(content) as GeminiSession;
69
-
70
- for (const msg of session.messages) {
71
- // Only process gemini messages with token data and timestamp
72
- if (msg.type !== "gemini" || !msg.tokens || !msg.model || !msg.timestamp) continue;
73
-
74
- const timestamp = new Date(msg.timestamp).getTime();
75
-
76
- // Skip invalid timestamps
77
- if (isNaN(timestamp)) continue;
78
-
79
- const tokens: TokenBreakdown = {
80
- input: msg.tokens.input || 0,
81
- output: msg.tokens.output || 0,
82
- cacheRead: msg.tokens.cached || 0,
83
- cacheWrite: 0, // Gemini doesn't track cache write
84
- reasoning: msg.tokens.thoughts || 0,
85
- };
86
-
87
- messages.push(
88
- createUnifiedMessage(
89
- "gemini",
90
- msg.model,
91
- "google",
92
- session.sessionId,
93
- timestamp,
94
- tokens
95
- )
96
- );
97
- }
98
- } catch {
99
- // Skip malformed files
100
- }
101
- }
102
- }
103
- } catch {
104
- // Skip inaccessible directories
105
- }
106
-
107
- return messages;
108
- }
@@ -1,126 +0,0 @@
1
- /**
2
- * Session parsers for different AI coding assistant formats
3
- *
4
- * This module provides TypeScript fallback parsers that match the Rust
5
- * implementations in packages/core/src/sessions/. Used when native module
6
- * is not available.
7
- */
8
-
9
- export * from "./types.js";
10
- export { parseOpenCodeMessages, getOpenCodeStoragePath } from "./opencode.js";
11
- export { parseClaudeCodeMessages, getClaudeCodeProjectsPath } from "./claudecode.js";
12
- export { parseCodexMessages, getCodexSessionsPath } from "./codex.js";
13
- export { parseGeminiMessages, getGeminiBasePath } from "./gemini.js";
14
-
15
- import type { UnifiedMessage, SourceType } from "./types.js";
16
- import { parseOpenCodeMessages } from "./opencode.js";
17
- import { parseClaudeCodeMessages } from "./claudecode.js";
18
- import { parseCodexMessages } from "./codex.js";
19
- import { parseGeminiMessages } from "./gemini.js";
20
-
21
- export interface ParsedMessages {
22
- messages: UnifiedMessage[];
23
- opencodeCount: number;
24
- claudeCount: number;
25
- codexCount: number;
26
- geminiCount: number;
27
- processingTimeMs: number;
28
- }
29
-
30
- export interface ParseOptions {
31
- sources?: SourceType[];
32
- since?: string;
33
- until?: string;
34
- year?: string;
35
- }
36
-
37
- /**
38
- * Check if a message date is within the filter range
39
- */
40
- function isDateInRange(date: string, since?: string, until?: string, year?: string): boolean {
41
- // Year filter
42
- if (year && !date.startsWith(year)) {
43
- return false;
44
- }
45
-
46
- // Since filter
47
- if (since && date < since) {
48
- return false;
49
- }
50
-
51
- // Until filter
52
- if (until && date > until) {
53
- return false;
54
- }
55
-
56
- return true;
57
- }
58
-
59
- /**
60
- * Parse all local session sources using TypeScript fallback parsers
61
- */
62
- export function parseLocalSources(options: ParseOptions = {}): ParsedMessages {
63
- const startTime = performance.now();
64
- const sources = options.sources;
65
-
66
- const allMessages: UnifiedMessage[] = [];
67
- let opencodeCount = 0;
68
- let claudeCount = 0;
69
- let codexCount = 0;
70
- let geminiCount = 0;
71
-
72
- // Parse OpenCode
73
- if (!sources || sources.includes("opencode")) {
74
- const messages = parseOpenCodeMessages();
75
- for (const msg of messages) {
76
- if (isDateInRange(msg.date, options.since, options.until, options.year)) {
77
- allMessages.push(msg);
78
- opencodeCount++;
79
- }
80
- }
81
- }
82
-
83
- // Parse Claude Code
84
- if (!sources || sources.includes("claude")) {
85
- const messages = parseClaudeCodeMessages();
86
- for (const msg of messages) {
87
- if (isDateInRange(msg.date, options.since, options.until, options.year)) {
88
- allMessages.push(msg);
89
- claudeCount++;
90
- }
91
- }
92
- }
93
-
94
- // Parse Codex
95
- if (!sources || sources.includes("codex")) {
96
- const messages = parseCodexMessages();
97
- for (const msg of messages) {
98
- if (isDateInRange(msg.date, options.since, options.until, options.year)) {
99
- allMessages.push(msg);
100
- codexCount++;
101
- }
102
- }
103
- }
104
-
105
- // Parse Gemini
106
- if (!sources || sources.includes("gemini")) {
107
- const messages = parseGeminiMessages();
108
- for (const msg of messages) {
109
- if (isDateInRange(msg.date, options.since, options.until, options.year)) {
110
- allMessages.push(msg);
111
- geminiCount++;
112
- }
113
- }
114
- }
115
-
116
- const processingTimeMs = performance.now() - startTime;
117
-
118
- return {
119
- messages: allMessages,
120
- opencodeCount,
121
- claudeCount,
122
- codexCount,
123
- geminiCount,
124
- processingTimeMs,
125
- };
126
- }
@@ -1,117 +0,0 @@
1
- /**
2
- * OpenCode session parser
3
- * Reads from ~/.local/share/opencode/storage/message/
4
- */
5
-
6
- import * as fs from "node:fs";
7
- import * as path from "node:path";
8
- import * as os from "node:os";
9
- import { createUnifiedMessage, type UnifiedMessage, type TokenBreakdown } from "./types.js";
10
-
11
- interface OpenCodeMessageFile {
12
- id: string;
13
- sessionID: string;
14
- role: "assistant" | "user";
15
- modelID?: string;
16
- providerID?: string;
17
- cost: number;
18
- tokens?: {
19
- input: number;
20
- output: number;
21
- reasoning: number;
22
- cache: {
23
- read: number;
24
- write: number;
25
- };
26
- };
27
- time: {
28
- created: number;
29
- completed?: number;
30
- };
31
- agent?: string;
32
- mode?: string;
33
- }
34
-
35
- export function normalizeAgentName(agent: string): string {
36
- const agentLower = agent.toLowerCase();
37
-
38
- if (agentLower.includes("plan")) {
39
- if (agentLower.includes("omo") || agentLower.includes("sisyphus")) {
40
- return "Planner-Sisyphus";
41
- }
42
- return agent;
43
- }
44
-
45
- if (agentLower === "omo" || agentLower === "sisyphus") {
46
- return "Sisyphus";
47
- }
48
-
49
- return agent;
50
- }
51
-
52
- export function getOpenCodeStoragePath(): string {
53
- const dataHome = process.env.XDG_DATA_HOME || path.join(os.homedir(), ".local", "share");
54
- return path.join(dataHome, "opencode", "storage");
55
- }
56
-
57
- export function parseOpenCodeMessages(): UnifiedMessage[] {
58
- const storagePath = getOpenCodeStoragePath();
59
- const messagePath = path.join(storagePath, "message");
60
-
61
- if (!fs.existsSync(messagePath)) {
62
- return [];
63
- }
64
-
65
- const messages: UnifiedMessage[] = [];
66
-
67
- try {
68
- const sessionDirs = fs
69
- .readdirSync(messagePath)
70
- .map((dir) => path.join(messagePath, dir))
71
- .filter((dir) => fs.statSync(dir).isDirectory());
72
-
73
- for (const sessionDir of sessionDirs) {
74
- const sessionId = path.basename(sessionDir);
75
- const files = fs.readdirSync(sessionDir).filter((f) => f.endsWith(".json"));
76
-
77
- for (const file of files) {
78
- try {
79
- const content = fs.readFileSync(path.join(sessionDir, file), "utf-8");
80
- const msg = JSON.parse(content) as OpenCodeMessageFile;
81
-
82
- if (msg.role === "assistant" && msg.tokens && msg.modelID) {
83
- const tokens: TokenBreakdown = {
84
- input: msg.tokens.input || 0,
85
- output: msg.tokens.output || 0,
86
- cacheRead: msg.tokens.cache?.read || 0,
87
- cacheWrite: msg.tokens.cache?.write || 0,
88
- reasoning: msg.tokens.reasoning || 0,
89
- };
90
-
91
- const agentOrMode = msg.mode || msg.agent;
92
- const agent = agentOrMode ? normalizeAgentName(agentOrMode) : undefined;
93
-
94
- messages.push(
95
- createUnifiedMessage(
96
- "opencode",
97
- msg.modelID,
98
- msg.providerID || "unknown",
99
- sessionId,
100
- msg.time.created,
101
- tokens,
102
- msg.cost || 0,
103
- agent
104
- )
105
- );
106
- }
107
- } catch {
108
- // Skip malformed files
109
- }
110
- }
111
- }
112
- } catch {
113
- // Skip inaccessible directories
114
- }
115
-
116
- return messages;
117
- }