wave-code 0.0.4 → 0.0.6

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 (102) hide show
  1. package/README.md +2 -2
  2. package/dist/components/ChatInterface.d.ts.map +1 -1
  3. package/dist/components/ChatInterface.js +4 -24
  4. package/dist/components/CommandSelector.js +4 -4
  5. package/dist/components/DiffViewer.d.ts +1 -1
  6. package/dist/components/DiffViewer.d.ts.map +1 -1
  7. package/dist/components/DiffViewer.js +15 -15
  8. package/dist/components/FileSelector.js +2 -2
  9. package/dist/components/InputBox.d.ts.map +1 -1
  10. package/dist/components/InputBox.js +46 -101
  11. package/dist/components/Markdown.d.ts +6 -0
  12. package/dist/components/Markdown.d.ts.map +1 -0
  13. package/dist/components/Markdown.js +22 -0
  14. package/dist/components/MessageItem.d.ts +9 -0
  15. package/dist/components/MessageItem.d.ts.map +1 -0
  16. package/dist/components/MessageItem.js +15 -0
  17. package/dist/components/MessageList.d.ts +1 -1
  18. package/dist/components/MessageList.d.ts.map +1 -1
  19. package/dist/components/MessageList.js +33 -32
  20. package/dist/components/SubagentBlock.d.ts +1 -2
  21. package/dist/components/SubagentBlock.d.ts.map +1 -1
  22. package/dist/components/SubagentBlock.js +29 -20
  23. package/dist/components/ToolResultDisplay.js +5 -5
  24. package/dist/contexts/useChat.d.ts +1 -0
  25. package/dist/contexts/useChat.d.ts.map +1 -1
  26. package/dist/contexts/useChat.js +29 -2
  27. package/dist/hooks/useInputManager.d.ts +93 -0
  28. package/dist/hooks/useInputManager.d.ts.map +1 -0
  29. package/dist/hooks/useInputManager.js +332 -0
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/index.js +17 -10
  32. package/dist/managers/InputManager.d.ts +171 -0
  33. package/dist/managers/InputManager.d.ts.map +1 -0
  34. package/dist/managers/InputManager.js +826 -0
  35. package/dist/print-cli.d.ts +8 -0
  36. package/dist/print-cli.d.ts.map +1 -0
  37. package/dist/print-cli.js +128 -0
  38. package/dist/utils/constants.d.ts +1 -1
  39. package/dist/utils/constants.js +1 -1
  40. package/dist/utils/fileSearch.d.ts +20 -0
  41. package/dist/utils/fileSearch.d.ts.map +1 -0
  42. package/dist/utils/fileSearch.js +102 -0
  43. package/dist/utils/logger.js +3 -3
  44. package/dist/utils/usageSummary.d.ts +33 -0
  45. package/dist/utils/usageSummary.d.ts.map +1 -0
  46. package/dist/utils/usageSummary.js +154 -0
  47. package/package.json +10 -6
  48. package/src/components/ChatInterface.tsx +13 -43
  49. package/src/components/CommandSelector.tsx +5 -5
  50. package/src/components/DiffViewer.tsx +18 -16
  51. package/src/components/FileSelector.tsx +2 -2
  52. package/src/components/InputBox.tsx +78 -169
  53. package/src/components/Markdown.tsx +29 -0
  54. package/src/components/MessageItem.tsx +104 -0
  55. package/src/components/MessageList.tsx +142 -198
  56. package/src/components/SubagentBlock.tsx +56 -73
  57. package/src/components/ToolResultDisplay.tsx +6 -6
  58. package/src/contexts/useChat.tsx +34 -2
  59. package/src/hooks/useInputManager.ts +461 -0
  60. package/src/index.ts +20 -10
  61. package/src/managers/InputManager.ts +1132 -0
  62. package/src/print-cli.ts +160 -0
  63. package/src/utils/constants.ts +1 -1
  64. package/src/utils/fileSearch.ts +133 -0
  65. package/src/utils/logger.ts +3 -3
  66. package/src/utils/usageSummary.ts +234 -0
  67. package/dist/hooks/useBashHistorySelector.d.ts +0 -15
  68. package/dist/hooks/useBashHistorySelector.d.ts.map +0 -1
  69. package/dist/hooks/useBashHistorySelector.js +0 -61
  70. package/dist/hooks/useCommandSelector.d.ts +0 -24
  71. package/dist/hooks/useCommandSelector.d.ts.map +0 -1
  72. package/dist/hooks/useCommandSelector.js +0 -98
  73. package/dist/hooks/useFileSelector.d.ts +0 -16
  74. package/dist/hooks/useFileSelector.d.ts.map +0 -1
  75. package/dist/hooks/useFileSelector.js +0 -174
  76. package/dist/hooks/useImageManager.d.ts +0 -13
  77. package/dist/hooks/useImageManager.d.ts.map +0 -1
  78. package/dist/hooks/useImageManager.js +0 -46
  79. package/dist/hooks/useInputHistory.d.ts +0 -11
  80. package/dist/hooks/useInputHistory.d.ts.map +0 -1
  81. package/dist/hooks/useInputHistory.js +0 -64
  82. package/dist/hooks/useInputKeyboardHandler.d.ts +0 -83
  83. package/dist/hooks/useInputKeyboardHandler.d.ts.map +0 -1
  84. package/dist/hooks/useInputKeyboardHandler.js +0 -507
  85. package/dist/hooks/useInputState.d.ts +0 -14
  86. package/dist/hooks/useInputState.d.ts.map +0 -1
  87. package/dist/hooks/useInputState.js +0 -57
  88. package/dist/hooks/useMemoryTypeSelector.d.ts +0 -9
  89. package/dist/hooks/useMemoryTypeSelector.d.ts.map +0 -1
  90. package/dist/hooks/useMemoryTypeSelector.js +0 -27
  91. package/dist/plain-cli.d.ts +0 -7
  92. package/dist/plain-cli.d.ts.map +0 -1
  93. package/dist/plain-cli.js +0 -44
  94. package/src/hooks/useBashHistorySelector.ts +0 -77
  95. package/src/hooks/useCommandSelector.ts +0 -131
  96. package/src/hooks/useFileSelector.ts +0 -227
  97. package/src/hooks/useImageManager.ts +0 -64
  98. package/src/hooks/useInputHistory.ts +0 -74
  99. package/src/hooks/useInputKeyboardHandler.ts +0 -778
  100. package/src/hooks/useInputState.ts +0 -66
  101. package/src/hooks/useMemoryTypeSelector.ts +0 -40
  102. package/src/plain-cli.ts +0 -60
@@ -0,0 +1,160 @@
1
+ import { Agent, AgentCallbacks } from "wave-agent-sdk";
2
+ import { displayUsageSummary } from "./utils/usageSummary.js";
3
+
4
+ export interface PrintCliOptions {
5
+ restoreSessionId?: string;
6
+ continueLastSession?: boolean;
7
+ message?: string;
8
+ showStats?: boolean;
9
+ }
10
+
11
+ function displayTimingInfo(startTime: Date, showStats: boolean): void {
12
+ // Skip timing info in test environment or if stats are disabled
13
+ if (process.env.NODE_ENV === "test" || process.env.VITEST || !showStats) {
14
+ return;
15
+ }
16
+
17
+ const endTime = new Date();
18
+ const duration = endTime.getTime() - startTime.getTime();
19
+
20
+ process.stdout.write(`\n\n📅 Start time: ${startTime.toISOString()}\n`);
21
+ process.stdout.write(`📅 End time: ${endTime.toISOString()}\n`);
22
+ process.stdout.write(`⏱️ Duration: ${duration}ms\n`);
23
+ }
24
+
25
+ export async function startPrintCli(options: PrintCliOptions): Promise<void> {
26
+ const startTime = new Date();
27
+ const {
28
+ restoreSessionId,
29
+ continueLastSession,
30
+ message,
31
+ showStats = false,
32
+ } = options;
33
+
34
+ if (
35
+ (!message || message.trim() === "") &&
36
+ !continueLastSession &&
37
+ !restoreSessionId
38
+ ) {
39
+ console.error(
40
+ "Print mode requires a message: use --print 'your message' or -p 'your message'",
41
+ );
42
+ process.exit(1);
43
+ }
44
+
45
+ let agent: Agent;
46
+
47
+ // Setup callbacks for agent
48
+ const callbacks: AgentCallbacks = {
49
+ onAssistantMessageAdded: () => {
50
+ // Assistant message started - no content to output yet
51
+ process.stdout.write("\n");
52
+ },
53
+ onAssistantContentUpdated: (chunk: string) => {
54
+ // FR-001: Stream content updates for real-time display - output only the new chunk
55
+ process.stdout.write(chunk);
56
+ },
57
+
58
+ // Tool block callback - display tool name when tool starts
59
+ onToolBlockUpdated: (params) => {
60
+ // Print tool name only during 'running' stage (happens once per tool call)
61
+ if (params.stage === "running" && params.name) {
62
+ process.stdout.write(`\n🔧 ${params.name}`);
63
+ if (params.compactParams) {
64
+ process.stdout.write(` ${params.compactParams}`);
65
+ }
66
+ process.stdout.write(`\n`);
67
+ }
68
+ },
69
+
70
+ // Subagent block callbacks
71
+ onSubAgentBlockAdded: (subagentId: string, parameters) => {
72
+ // Display subagent creation with indentation
73
+ process.stdout.write(
74
+ `\n🤖 Subagent [${parameters.subagent_type}]: ${parameters.description}\n`,
75
+ );
76
+ },
77
+ onSubAgentBlockUpdated: (subagentId: string, status) => {
78
+ // Display subagent status updates
79
+ const statusIconMap = {
80
+ active: "🔄",
81
+ completed: "✅",
82
+ error: "❌",
83
+ aborted: "⚠️",
84
+ } as const;
85
+
86
+ const statusIcon = statusIconMap[status] ?? "🔄";
87
+ process.stdout.write(` ${statusIcon} Subagent status: ${status}\n`);
88
+ },
89
+ // Subagent message callbacks
90
+ onSubagentAssistantMessageAdded: () => {
91
+ // Subagent assistant message started - add indentation
92
+ process.stdout.write("\n ");
93
+ },
94
+ onSubagentAssistantContentUpdated: (_subagentId: string, chunk: string) => {
95
+ // Stream subagent content with indentation - output only the new chunk
96
+ process.stdout.write(chunk);
97
+ },
98
+ onSubagentUserMessageAdded: (_subagentId: string, params) => {
99
+ // Display subagent user messages with indentation
100
+ process.stdout.write(`\n 👤 User: ${params.content}\n`);
101
+ },
102
+ // Error block callback
103
+ onErrorBlockAdded: (error: string) => {
104
+ // Display error blocks with distinct formatting
105
+ process.stdout.write(`\n❌ Error: ${error}\n`);
106
+ },
107
+ };
108
+
109
+ try {
110
+ // Initialize agent
111
+ agent = await Agent.create({
112
+ callbacks,
113
+ restoreSessionId,
114
+ continueLastSession,
115
+ });
116
+
117
+ // Send message if provided and not empty
118
+ if (message && message.trim() !== "") {
119
+ await agent.sendMessage(message);
120
+ }
121
+
122
+ // Display usage summary before exit
123
+ if (showStats) {
124
+ try {
125
+ const usages = agent.usages;
126
+ const sessionFilePath = agent.sessionFilePath;
127
+ displayUsageSummary(usages, sessionFilePath);
128
+ } catch {
129
+ // Silently ignore usage summary errors
130
+ }
131
+ }
132
+
133
+ // Display timing information
134
+ displayTimingInfo(startTime, showStats);
135
+
136
+ // Destroy agent and exit after sendMessage completes
137
+ await agent.destroy();
138
+ process.exit(0);
139
+ } catch (error) {
140
+ console.error("Failed to send message:", error);
141
+ if (agent!) {
142
+ // Display usage summary even on error
143
+ if (showStats) {
144
+ try {
145
+ const usages = agent.usages;
146
+ const sessionFilePath = agent.sessionFilePath;
147
+ displayUsageSummary(usages, sessionFilePath);
148
+ } catch {
149
+ // Silently ignore usage summary errors
150
+ }
151
+ }
152
+
153
+ // Display timing information even on error
154
+ displayTimingInfo(startTime, showStats);
155
+
156
+ await agent.destroy();
157
+ }
158
+ process.exit(1);
159
+ }
160
+ }
@@ -19,4 +19,4 @@ export const LOG_FILE = path.join(DATA_DIRECTORY, "app.log");
19
19
  /**
20
20
  * Pagination related constants
21
21
  */
22
- export const MESSAGES_PER_PAGE = 20; // Number of messages displayed per page
22
+ export const MESSAGES_PER_PAGE = 15; // Number of messages displayed per page
@@ -0,0 +1,133 @@
1
+ import { glob } from "glob";
2
+ import { getGlobIgnorePatterns } from "wave-agent-sdk";
3
+ import * as fs from "fs";
4
+ import * as path from "path";
5
+
6
+ export interface FileItem {
7
+ path: string;
8
+ type: "file" | "directory";
9
+ }
10
+
11
+ /**
12
+ * Check if path is a directory
13
+ */
14
+ export const isDirectory = (filePath: string): boolean => {
15
+ try {
16
+ const fullPath = path.isAbsolute(filePath)
17
+ ? filePath
18
+ : path.join(process.cwd(), filePath);
19
+ return fs.statSync(fullPath).isDirectory();
20
+ } catch {
21
+ return false;
22
+ }
23
+ };
24
+
25
+ /**
26
+ * Convert string paths to FileItem objects
27
+ */
28
+ export const convertToFileItems = (paths: string[]): FileItem[] => {
29
+ return paths.map((filePath) => ({
30
+ path: filePath,
31
+ type: isDirectory(filePath) ? "directory" : "file",
32
+ }));
33
+ };
34
+
35
+ /**
36
+ * Search files and directories using glob patterns
37
+ */
38
+ export const searchFiles = async (
39
+ query: string,
40
+ options?: {
41
+ maxResults?: number;
42
+ workingDirectory?: string;
43
+ },
44
+ ): Promise<FileItem[]> => {
45
+ const { maxResults = 10, workingDirectory = process.cwd() } = options || {};
46
+
47
+ try {
48
+ let files: string[] = [];
49
+ let directories: string[] = [];
50
+
51
+ const globOptions = {
52
+ ignore: getGlobIgnorePatterns(workingDirectory),
53
+ maxDepth: 10,
54
+ nocase: true, // Case insensitive
55
+ dot: true, // Include hidden files and directories
56
+ cwd: workingDirectory, // Specify search root directory
57
+ };
58
+
59
+ if (!query.trim()) {
60
+ // When query is empty, show some common file types and directories
61
+ const commonPatterns = [
62
+ "**/*.ts",
63
+ "**/*.tsx",
64
+ "**/*.js",
65
+ "**/*.jsx",
66
+ "**/*.json",
67
+ ];
68
+
69
+ // Search files
70
+ const filePromises = commonPatterns.map((pattern) =>
71
+ glob(pattern, { ...globOptions, nodir: true }),
72
+ );
73
+
74
+ // Search directories (only search first level to avoid too many results)
75
+ const dirPromises = [glob("*/", { ...globOptions, maxDepth: 1 })];
76
+
77
+ const fileResults = await Promise.all(filePromises);
78
+ const dirResults = await Promise.all(dirPromises);
79
+
80
+ files = fileResults.flat();
81
+ directories = dirResults.flat().map((dir) => {
82
+ // glob returns string type paths, remove trailing slash
83
+ return String(dir).replace(/\/$/, "");
84
+ });
85
+ } else {
86
+ // Build multiple glob patterns to support more flexible search
87
+ const filePatterns = [
88
+ // Match files with filenames containing query
89
+ `**/*${query}*`,
90
+ // Match files with query in path (match directory names)
91
+ `**/${query}*/**/*`,
92
+ ];
93
+
94
+ const dirPatterns = [
95
+ // Match directory names containing query
96
+ `**/*${query}*/`,
97
+ // Match directories containing query in path
98
+ `**/${query}*/`,
99
+ ];
100
+
101
+ // Search files
102
+ const filePromises = filePatterns.map((pattern) =>
103
+ glob(pattern, { ...globOptions, nodir: true }),
104
+ );
105
+
106
+ // Search directories
107
+ const dirPromises = dirPatterns.map((pattern) =>
108
+ glob(pattern, { ...globOptions, nodir: false }),
109
+ );
110
+
111
+ const fileResults = await Promise.all(filePromises);
112
+ const dirResults = await Promise.all(dirPromises);
113
+
114
+ files = fileResults.flat();
115
+ directories = dirResults.flat().map((dir) => {
116
+ // glob returns string type paths, remove trailing slash
117
+ return String(dir).replace(/\/$/, "");
118
+ });
119
+ }
120
+
121
+ // Deduplicate and merge files and directories
122
+ const uniqueFiles = Array.from(new Set(files));
123
+ const uniqueDirectories = Array.from(new Set(directories));
124
+ const allPaths = [...uniqueDirectories, ...uniqueFiles]; // Directories first
125
+
126
+ // Limit to maximum results and convert to FileItem
127
+ const fileItems = convertToFileItems(allPaths.slice(0, maxResults));
128
+ return fileItems;
129
+ } catch (error) {
130
+ console.error("Glob search error:", error);
131
+ return [];
132
+ }
133
+ };
@@ -264,7 +264,7 @@ const truncateLogFileIfNeeded = (config: LogCleanupConfig): void => {
264
264
 
265
265
  // Record truncation operation
266
266
  const removedLines = lines.length - keepLines;
267
- logger.info(
267
+ logger.debug(
268
268
  `Log file truncated: removed ${removedLines} lines, kept last ${keepLines} lines`,
269
269
  );
270
270
  }
@@ -289,7 +289,7 @@ export const cleanupLogs = async (
289
289
 
290
290
  const config = { ...getCleanupConfig(), ...customConfig };
291
291
 
292
- logger.info("Starting log cleanup...", {
292
+ logger.debug("Starting log cleanup...", {
293
293
  maxFileSize: config.maxFileSize,
294
294
  keepLines: config.keepLines,
295
295
  });
@@ -297,5 +297,5 @@ export const cleanupLogs = async (
297
297
  // Truncate current log file (if needed)
298
298
  truncateLogFileIfNeeded(config);
299
299
 
300
- logger.info("Log cleanup completed");
300
+ logger.debug("Log cleanup completed");
301
301
  };
@@ -0,0 +1,234 @@
1
+ import type { Usage } from "wave-agent-sdk";
2
+
3
+ /**
4
+ * Token summary by model
5
+ */
6
+ export interface TokenSummary {
7
+ model: string;
8
+ prompt_tokens: number;
9
+ completion_tokens: number;
10
+ total_tokens: number;
11
+ operations: {
12
+ agent_calls: number;
13
+ compressions: number;
14
+ };
15
+ // Cache-related tokens (for Claude models)
16
+ cache_read_input_tokens?: number;
17
+ cache_creation_input_tokens?: number;
18
+ cache_creation?: {
19
+ ephemeral_5m_input_tokens: number;
20
+ ephemeral_1h_input_tokens: number;
21
+ };
22
+ }
23
+
24
+ /**
25
+ * Calculate token usage summary by model from usage array
26
+ * @param usages Array of usage data from agent operations
27
+ * @returns Array of token summaries grouped by model
28
+ */
29
+ export function calculateTokenSummary(
30
+ usages: Usage[],
31
+ ): Record<string, TokenSummary> {
32
+ const summaryMap = new Map<string, TokenSummary>();
33
+
34
+ for (const usage of usages) {
35
+ const model = usage.model || "unknown";
36
+
37
+ if (!summaryMap.has(model)) {
38
+ summaryMap.set(model, {
39
+ model,
40
+ prompt_tokens: 0,
41
+ completion_tokens: 0,
42
+ total_tokens: 0,
43
+ operations: {
44
+ agent_calls: 0,
45
+ compressions: 0,
46
+ },
47
+ });
48
+ }
49
+
50
+ const summary = summaryMap.get(model)!;
51
+ summary.prompt_tokens += usage.prompt_tokens;
52
+ summary.completion_tokens += usage.completion_tokens;
53
+ summary.total_tokens += usage.total_tokens;
54
+
55
+ // Handle cache tokens if present and non-zero
56
+ if (usage.cache_read_input_tokens && usage.cache_read_input_tokens > 0) {
57
+ summary.cache_read_input_tokens =
58
+ (summary.cache_read_input_tokens || 0) + usage.cache_read_input_tokens;
59
+ }
60
+ if (
61
+ usage.cache_creation_input_tokens &&
62
+ usage.cache_creation_input_tokens > 0
63
+ ) {
64
+ summary.cache_creation_input_tokens =
65
+ (summary.cache_creation_input_tokens || 0) +
66
+ usage.cache_creation_input_tokens;
67
+ }
68
+ if (
69
+ usage.cache_creation &&
70
+ (usage.cache_creation.ephemeral_5m_input_tokens > 0 ||
71
+ usage.cache_creation.ephemeral_1h_input_tokens > 0)
72
+ ) {
73
+ if (!summary.cache_creation) {
74
+ summary.cache_creation = {
75
+ ephemeral_5m_input_tokens: 0,
76
+ ephemeral_1h_input_tokens: 0,
77
+ };
78
+ }
79
+ summary.cache_creation.ephemeral_5m_input_tokens +=
80
+ usage.cache_creation.ephemeral_5m_input_tokens || 0;
81
+ summary.cache_creation.ephemeral_1h_input_tokens +=
82
+ usage.cache_creation.ephemeral_1h_input_tokens || 0;
83
+ }
84
+
85
+ // Track operation types
86
+ if (usage.operation_type === "agent") {
87
+ summary.operations.agent_calls += 1;
88
+ } else if (usage.operation_type === "compress") {
89
+ summary.operations.compressions += 1;
90
+ }
91
+ }
92
+
93
+ // Convert Map to Record and sort by total tokens
94
+ const result: Record<string, TokenSummary> = {};
95
+ const sortedEntries = Array.from(summaryMap.entries()).sort(
96
+ (a, b) => b[1].total_tokens - a[1].total_tokens,
97
+ );
98
+
99
+ for (const [model, summary] of sortedEntries) {
100
+ result[model] = summary;
101
+ }
102
+
103
+ return result;
104
+ }
105
+
106
+ /**
107
+ * Display usage summary in a formatted way
108
+ * @param usages Array of usage data from agent operations
109
+ * @param sessionFilePath Optional session file path to display
110
+ */
111
+ export function displayUsageSummary(
112
+ usages: Usage[],
113
+ sessionFilePath?: string,
114
+ ): void {
115
+ if (usages.length === 0) {
116
+ return; // No usage data to display
117
+ }
118
+
119
+ const summaries = calculateTokenSummary(usages);
120
+
121
+ console.log("\nToken Usage Summary:");
122
+ console.log("==================");
123
+
124
+ if (sessionFilePath) {
125
+ console.log(`Session: ${sessionFilePath}`);
126
+ }
127
+
128
+ let totalPrompt = 0;
129
+ let totalCompletion = 0;
130
+ let totalTokens = 0;
131
+ let totalAgentCalls = 0;
132
+ let totalCompressions = 0;
133
+ let totalCacheRead = 0;
134
+ let totalCacheCreation = 0;
135
+ let totalCache5m = 0;
136
+ let totalCache1h = 0;
137
+ let hasCacheData = false;
138
+
139
+ for (const [, summary] of Object.entries(summaries)) {
140
+ console.log(`Model: ${summary.model}`);
141
+ console.log(` Prompt tokens: ${summary.prompt_tokens.toLocaleString()}`);
142
+ console.log(
143
+ ` Completion tokens: ${summary.completion_tokens.toLocaleString()}`,
144
+ );
145
+ console.log(` Total tokens: ${summary.total_tokens.toLocaleString()}`);
146
+
147
+ // Display cache information if available
148
+ if (
149
+ summary.cache_read_input_tokens ||
150
+ summary.cache_creation_input_tokens ||
151
+ summary.cache_creation
152
+ ) {
153
+ hasCacheData = true;
154
+ console.log(" Cache Usage:");
155
+
156
+ if (
157
+ summary.cache_read_input_tokens &&
158
+ summary.cache_read_input_tokens > 0
159
+ ) {
160
+ console.log(
161
+ ` Read from cache: ${summary.cache_read_input_tokens.toLocaleString()} tokens`,
162
+ );
163
+ totalCacheRead += summary.cache_read_input_tokens;
164
+ }
165
+
166
+ if (
167
+ summary.cache_creation_input_tokens &&
168
+ summary.cache_creation_input_tokens > 0
169
+ ) {
170
+ console.log(
171
+ ` Created cache: ${summary.cache_creation_input_tokens.toLocaleString()} tokens`,
172
+ );
173
+ totalCacheCreation += summary.cache_creation_input_tokens;
174
+ }
175
+
176
+ if (summary.cache_creation) {
177
+ if (summary.cache_creation.ephemeral_5m_input_tokens > 0) {
178
+ console.log(
179
+ ` 5m cache: ${summary.cache_creation.ephemeral_5m_input_tokens.toLocaleString()} tokens`,
180
+ );
181
+ totalCache5m += summary.cache_creation.ephemeral_5m_input_tokens;
182
+ }
183
+ if (summary.cache_creation.ephemeral_1h_input_tokens > 0) {
184
+ console.log(
185
+ ` 1h cache: ${summary.cache_creation.ephemeral_1h_input_tokens.toLocaleString()} tokens`,
186
+ );
187
+ totalCache1h += summary.cache_creation.ephemeral_1h_input_tokens;
188
+ }
189
+ }
190
+ }
191
+
192
+ console.log(
193
+ ` Operations: ${summary.operations.agent_calls} agent calls, ${summary.operations.compressions} compressions`,
194
+ );
195
+ console.log();
196
+
197
+ totalPrompt += summary.prompt_tokens;
198
+ totalCompletion += summary.completion_tokens;
199
+ totalTokens += summary.total_tokens;
200
+ totalAgentCalls += summary.operations.agent_calls;
201
+ totalCompressions += summary.operations.compressions;
202
+ }
203
+
204
+ if (Object.keys(summaries).length > 1) {
205
+ console.log("Overall Total:");
206
+ console.log(` Prompt tokens: ${totalPrompt.toLocaleString()}`);
207
+ console.log(` Completion tokens: ${totalCompletion.toLocaleString()}`);
208
+ console.log(` Total tokens: ${totalTokens.toLocaleString()}`);
209
+
210
+ if (hasCacheData) {
211
+ console.log(" Cache Usage:");
212
+ if (totalCacheRead > 0) {
213
+ console.log(
214
+ ` Read from cache: ${totalCacheRead.toLocaleString()} tokens`,
215
+ );
216
+ }
217
+ if (totalCacheCreation > 0) {
218
+ console.log(
219
+ ` Created cache: ${totalCacheCreation.toLocaleString()} tokens`,
220
+ );
221
+ }
222
+ if (totalCache5m > 0) {
223
+ console.log(` 5m cache: ${totalCache5m.toLocaleString()} tokens`);
224
+ }
225
+ if (totalCache1h > 0) {
226
+ console.log(` 1h cache: ${totalCache1h.toLocaleString()} tokens`);
227
+ }
228
+ }
229
+
230
+ console.log(
231
+ ` Operations: ${totalAgentCalls} agent calls, ${totalCompressions} compressions`,
232
+ );
233
+ }
234
+ }
@@ -1,15 +0,0 @@
1
- export declare const useBashHistorySelector: () => {
2
- showBashHistorySelector: boolean;
3
- bashHistorySearchQuery: string;
4
- activateBashHistorySelector: (position: number) => void;
5
- handleBashHistorySelect: (command: string, inputText: string, cursorPosition: number) => {
6
- newInput: string;
7
- newCursorPosition: number;
8
- };
9
- handleBashHistoryExecute: (command: string) => string;
10
- handleCancelBashHistorySelect: () => void;
11
- updateBashHistorySearchQuery: (query: string) => void;
12
- checkForExclamationDeletion: (cursorPosition: number) => boolean;
13
- exclamationPosition: number;
14
- };
15
- //# sourceMappingURL=useBashHistorySelector.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useBashHistorySelector.d.ts","sourceRoot":"","sources":["../../src/hooks/useBashHistorySelector.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,sBAAsB;;;4CAK0B,MAAM;uCAOrD,MAAM,aAAa,MAAM,kBAAkB,MAAM;;;;wCAyBN,MAAM;;0CAOJ,MAAM;kDAK5C,MAAM;;CAyB1B,CAAC"}
@@ -1,61 +0,0 @@
1
- import { useState, useCallback } from "react";
2
- export const useBashHistorySelector = () => {
3
- const [showBashHistorySelector, setShowBashHistorySelector] = useState(false);
4
- const [exclamationPosition, setExclamationPosition] = useState(-1);
5
- const [bashHistorySearchQuery, setBashHistorySearchQuery] = useState("");
6
- const activateBashHistorySelector = useCallback((position) => {
7
- setShowBashHistorySelector(true);
8
- setExclamationPosition(position);
9
- setBashHistorySearchQuery("");
10
- }, []);
11
- const handleBashHistorySelect = useCallback((command, inputText, cursorPosition) => {
12
- if (exclamationPosition >= 0) {
13
- // Replace ! and search query with selected command
14
- const beforeExclamation = inputText.substring(0, exclamationPosition);
15
- const afterQuery = inputText.substring(cursorPosition);
16
- const newInput = beforeExclamation + `!${command}` + afterQuery;
17
- const newCursorPosition = beforeExclamation.length + command.length + 1;
18
- setShowBashHistorySelector(false);
19
- setExclamationPosition(-1);
20
- setBashHistorySearchQuery("");
21
- return { newInput, newCursorPosition };
22
- }
23
- return { newInput: inputText, newCursorPosition: cursorPosition };
24
- }, [exclamationPosition]);
25
- const handleCancelBashHistorySelect = useCallback(() => {
26
- setShowBashHistorySelector(false);
27
- setExclamationPosition(-1);
28
- setBashHistorySearchQuery("");
29
- }, []);
30
- const handleBashHistoryExecute = useCallback((command) => {
31
- setShowBashHistorySelector(false);
32
- setExclamationPosition(-1);
33
- setBashHistorySearchQuery("");
34
- return command; // Return command to execute
35
- }, []);
36
- const updateBashHistorySearchQuery = useCallback((query) => {
37
- setBashHistorySearchQuery(query);
38
- }, []);
39
- const checkForExclamationDeletion = useCallback((cursorPosition) => {
40
- if (showBashHistorySelector && cursorPosition <= exclamationPosition) {
41
- handleCancelBashHistorySelect();
42
- return true;
43
- }
44
- return false;
45
- }, [
46
- showBashHistorySelector,
47
- exclamationPosition,
48
- handleCancelBashHistorySelect,
49
- ]);
50
- return {
51
- showBashHistorySelector,
52
- bashHistorySearchQuery,
53
- activateBashHistorySelector,
54
- handleBashHistorySelect,
55
- handleBashHistoryExecute,
56
- handleCancelBashHistorySelect,
57
- updateBashHistorySearchQuery,
58
- checkForExclamationDeletion,
59
- exclamationPosition,
60
- };
61
- };
@@ -1,24 +0,0 @@
1
- export interface UseCommandSelectorParams {
2
- onShowBashManager?: () => void;
3
- onShowMcpManager?: () => void;
4
- sendMessage?: (content: string) => Promise<void>;
5
- hasSlashCommand?: (commandId: string) => boolean;
6
- }
7
- export declare const useCommandSelector: ({ onShowBashManager, onShowMcpManager, sendMessage, hasSlashCommand, }: UseCommandSelectorParams) => {
8
- showCommandSelector: boolean;
9
- commandSearchQuery: string;
10
- activateCommandSelector: (position: number) => void;
11
- handleCommandSelect: (command: string, inputText: string, cursorPosition: number) => {
12
- newInput: string;
13
- newCursorPosition: number;
14
- };
15
- handleCommandInsert: (command: string, inputText: string, cursorPosition: number) => {
16
- newInput: string;
17
- newCursorPosition: number;
18
- };
19
- handleCancelCommandSelect: () => void;
20
- updateCommandSearchQuery: (query: string) => void;
21
- checkForSlashDeletion: (cursorPosition: number) => boolean;
22
- slashPosition: number;
23
- };
24
- //# sourceMappingURL=useCommandSelector.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useCommandSelector.d.ts","sourceRoot":"","sources":["../../src/hooks/useCommandSelector.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,wBAAwB;IACvC,iBAAiB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC/B,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACjD,eAAe,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC;CAClD;AAED,eAAO,MAAM,kBAAkB,GAAI,wEAKhC,wBAAwB;;;wCAK8B,MAAM;mCA2BjD,MAAM,aAAa,MAAM,kBAAkB,MAAM;;;;mCApBjD,MAAM,aAAa,MAAM,kBAAkB,MAAM;;;;;sCA8ER,MAAM;4CAKxC,MAAM;;CAqB1B,CAAC"}