wave-code 0.0.4 → 0.0.5

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 (78) hide show
  1. package/dist/components/InputBox.d.ts.map +1 -1
  2. package/dist/components/InputBox.js +69 -95
  3. package/dist/components/MessageList.d.ts.map +1 -1
  4. package/dist/components/MessageList.js +2 -1
  5. package/dist/components/SubagentBlock.d.ts +1 -1
  6. package/dist/components/SubagentBlock.d.ts.map +1 -1
  7. package/dist/components/SubagentBlock.js +12 -2
  8. package/dist/components/ToolResultDisplay.js +1 -1
  9. package/dist/contexts/useChat.d.ts +2 -1
  10. package/dist/contexts/useChat.d.ts.map +1 -1
  11. package/dist/contexts/useChat.js +18 -0
  12. package/dist/hooks/useInputManager.d.ts +91 -0
  13. package/dist/hooks/useInputManager.d.ts.map +1 -0
  14. package/dist/hooks/useInputManager.js +319 -0
  15. package/dist/index.js +9 -9
  16. package/dist/managers/InputManager.d.ts +169 -0
  17. package/dist/managers/InputManager.d.ts.map +1 -0
  18. package/dist/managers/InputManager.js +806 -0
  19. package/dist/print-cli.d.ts +7 -0
  20. package/dist/print-cli.d.ts.map +1 -0
  21. package/dist/{plain-cli.js → print-cli.js} +21 -2
  22. package/dist/utils/constants.d.ts +1 -1
  23. package/dist/utils/constants.js +1 -1
  24. package/dist/utils/fileSearch.d.ts +20 -0
  25. package/dist/utils/fileSearch.d.ts.map +1 -0
  26. package/dist/utils/fileSearch.js +102 -0
  27. package/dist/utils/logger.js +3 -3
  28. package/dist/utils/usageSummary.d.ts +27 -0
  29. package/dist/utils/usageSummary.d.ts.map +1 -0
  30. package/dist/utils/usageSummary.js +82 -0
  31. package/package.json +2 -2
  32. package/src/components/InputBox.tsx +114 -153
  33. package/src/components/MessageList.tsx +14 -10
  34. package/src/components/SubagentBlock.tsx +14 -3
  35. package/src/components/ToolResultDisplay.tsx +1 -1
  36. package/src/contexts/useChat.tsx +23 -0
  37. package/src/hooks/useInputManager.ts +443 -0
  38. package/src/index.ts +9 -9
  39. package/src/managers/InputManager.ts +1102 -0
  40. package/src/{plain-cli.ts → print-cli.ts} +21 -3
  41. package/src/utils/constants.ts +1 -1
  42. package/src/utils/fileSearch.ts +133 -0
  43. package/src/utils/logger.ts +3 -3
  44. package/src/utils/usageSummary.ts +125 -0
  45. package/dist/hooks/useBashHistorySelector.d.ts +0 -15
  46. package/dist/hooks/useBashHistorySelector.d.ts.map +0 -1
  47. package/dist/hooks/useBashHistorySelector.js +0 -61
  48. package/dist/hooks/useCommandSelector.d.ts +0 -24
  49. package/dist/hooks/useCommandSelector.d.ts.map +0 -1
  50. package/dist/hooks/useCommandSelector.js +0 -98
  51. package/dist/hooks/useFileSelector.d.ts +0 -16
  52. package/dist/hooks/useFileSelector.d.ts.map +0 -1
  53. package/dist/hooks/useFileSelector.js +0 -174
  54. package/dist/hooks/useImageManager.d.ts +0 -13
  55. package/dist/hooks/useImageManager.d.ts.map +0 -1
  56. package/dist/hooks/useImageManager.js +0 -46
  57. package/dist/hooks/useInputHistory.d.ts +0 -11
  58. package/dist/hooks/useInputHistory.d.ts.map +0 -1
  59. package/dist/hooks/useInputHistory.js +0 -64
  60. package/dist/hooks/useInputKeyboardHandler.d.ts +0 -83
  61. package/dist/hooks/useInputKeyboardHandler.d.ts.map +0 -1
  62. package/dist/hooks/useInputKeyboardHandler.js +0 -507
  63. package/dist/hooks/useInputState.d.ts +0 -14
  64. package/dist/hooks/useInputState.d.ts.map +0 -1
  65. package/dist/hooks/useInputState.js +0 -57
  66. package/dist/hooks/useMemoryTypeSelector.d.ts +0 -9
  67. package/dist/hooks/useMemoryTypeSelector.d.ts.map +0 -1
  68. package/dist/hooks/useMemoryTypeSelector.js +0 -27
  69. package/dist/plain-cli.d.ts +0 -7
  70. package/dist/plain-cli.d.ts.map +0 -1
  71. package/src/hooks/useBashHistorySelector.ts +0 -77
  72. package/src/hooks/useCommandSelector.ts +0 -131
  73. package/src/hooks/useFileSelector.ts +0 -227
  74. package/src/hooks/useImageManager.ts +0 -64
  75. package/src/hooks/useInputHistory.ts +0 -74
  76. package/src/hooks/useInputKeyboardHandler.ts +0 -778
  77. package/src/hooks/useInputState.ts +0 -66
  78. package/src/hooks/useMemoryTypeSelector.ts +0 -40
@@ -0,0 +1,7 @@
1
+ export interface PrintCliOptions {
2
+ restoreSessionId?: string;
3
+ continueLastSession?: boolean;
4
+ message?: string;
5
+ }
6
+ export declare function startPrintCli(options: PrintCliOptions): Promise<void>;
7
+ //# sourceMappingURL=print-cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"print-cli.d.ts","sourceRoot":"","sources":["../src/print-cli.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,eAAe;IAC9B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAsB,aAAa,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAmE3E"}
@@ -1,11 +1,12 @@
1
1
  import { Agent } from "wave-agent-sdk";
2
2
  import { logger } from "./utils/logger.js";
3
- export async function startPlainCli(options) {
3
+ import { displayUsageSummary } from "./utils/usageSummary.js";
4
+ export async function startPrintCli(options) {
4
5
  const { restoreSessionId, continueLastSession, message } = options;
5
6
  if ((!message || message.trim() === "") &&
6
7
  !continueLastSession &&
7
8
  !restoreSessionId) {
8
- console.error("Plain mode requires a message: use --plain 'your message' or -p 'your message'");
9
+ console.error("Print mode requires a message: use --print 'your message' or -p 'your message'");
9
10
  process.exit(1);
10
11
  }
11
12
  let agent;
@@ -30,6 +31,15 @@ export async function startPlainCli(options) {
30
31
  if (message && message.trim() !== "") {
31
32
  await agent.sendMessage(message);
32
33
  }
34
+ // Display usage summary before exit
35
+ try {
36
+ const usages = agent.usages;
37
+ const sessionFilePath = agent.sessionFilePath;
38
+ displayUsageSummary(usages, sessionFilePath);
39
+ }
40
+ catch {
41
+ // Silently ignore usage summary errors
42
+ }
33
43
  // Destroy agent and exit after sendMessage completes
34
44
  agent.destroy();
35
45
  process.exit(0);
@@ -37,6 +47,15 @@ export async function startPlainCli(options) {
37
47
  catch (error) {
38
48
  console.error("Failed to send message:", error);
39
49
  if (agent) {
50
+ // Display usage summary even on error
51
+ try {
52
+ const usages = agent.usages;
53
+ const sessionFilePath = agent.sessionFilePath;
54
+ displayUsageSummary(usages, sessionFilePath);
55
+ }
56
+ catch {
57
+ // Silently ignore usage summary errors
58
+ }
40
59
  agent.destroy();
41
60
  }
42
61
  process.exit(1);
@@ -13,5 +13,5 @@ export declare const LOG_FILE: string;
13
13
  /**
14
14
  * Pagination related constants
15
15
  */
16
- export declare const MESSAGES_PER_PAGE = 20;
16
+ export declare const MESSAGES_PER_PAGE = 15;
17
17
  //# sourceMappingURL=constants.d.ts.map
@@ -15,4 +15,4 @@ export const LOG_FILE = path.join(DATA_DIRECTORY, "app.log");
15
15
  /**
16
16
  * Pagination related constants
17
17
  */
18
- export const MESSAGES_PER_PAGE = 20; // Number of messages displayed per page
18
+ export const MESSAGES_PER_PAGE = 15; // Number of messages displayed per page
@@ -0,0 +1,20 @@
1
+ export interface FileItem {
2
+ path: string;
3
+ type: "file" | "directory";
4
+ }
5
+ /**
6
+ * Check if path is a directory
7
+ */
8
+ export declare const isDirectory: (filePath: string) => boolean;
9
+ /**
10
+ * Convert string paths to FileItem objects
11
+ */
12
+ export declare const convertToFileItems: (paths: string[]) => FileItem[];
13
+ /**
14
+ * Search files and directories using glob patterns
15
+ */
16
+ export declare const searchFiles: (query: string, options?: {
17
+ maxResults?: number;
18
+ workingDirectory?: string;
19
+ }) => Promise<FileItem[]>;
20
+ //# sourceMappingURL=fileSearch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fileSearch.d.ts","sourceRoot":"","sources":["../../src/utils/fileSearch.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;CAC5B;AAED;;GAEG;AACH,eAAO,MAAM,WAAW,GAAI,UAAU,MAAM,KAAG,OAS9C,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,kBAAkB,GAAI,OAAO,MAAM,EAAE,KAAG,QAAQ,EAK5D,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,WAAW,GACtB,OAAO,MAAM,EACb,UAAU;IACR,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B,KACA,OAAO,CAAC,QAAQ,EAAE,CAyFpB,CAAC"}
@@ -0,0 +1,102 @@
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
+ * Check if path is a directory
7
+ */
8
+ export const isDirectory = (filePath) => {
9
+ try {
10
+ const fullPath = path.isAbsolute(filePath)
11
+ ? filePath
12
+ : path.join(process.cwd(), filePath);
13
+ return fs.statSync(fullPath).isDirectory();
14
+ }
15
+ catch {
16
+ return false;
17
+ }
18
+ };
19
+ /**
20
+ * Convert string paths to FileItem objects
21
+ */
22
+ export const convertToFileItems = (paths) => {
23
+ return paths.map((filePath) => ({
24
+ path: filePath,
25
+ type: isDirectory(filePath) ? "directory" : "file",
26
+ }));
27
+ };
28
+ /**
29
+ * Search files and directories using glob patterns
30
+ */
31
+ export const searchFiles = async (query, options) => {
32
+ const { maxResults = 10, workingDirectory = process.cwd() } = options || {};
33
+ try {
34
+ let files = [];
35
+ let directories = [];
36
+ const globOptions = {
37
+ ignore: getGlobIgnorePatterns(workingDirectory),
38
+ maxDepth: 10,
39
+ nocase: true, // Case insensitive
40
+ dot: true, // Include hidden files and directories
41
+ cwd: workingDirectory, // Specify search root directory
42
+ };
43
+ if (!query.trim()) {
44
+ // When query is empty, show some common file types and directories
45
+ const commonPatterns = [
46
+ "**/*.ts",
47
+ "**/*.tsx",
48
+ "**/*.js",
49
+ "**/*.jsx",
50
+ "**/*.json",
51
+ ];
52
+ // Search files
53
+ const filePromises = commonPatterns.map((pattern) => glob(pattern, { ...globOptions, nodir: true }));
54
+ // Search directories (only search first level to avoid too many results)
55
+ const dirPromises = [glob("*/", { ...globOptions, maxDepth: 1 })];
56
+ const fileResults = await Promise.all(filePromises);
57
+ const dirResults = await Promise.all(dirPromises);
58
+ files = fileResults.flat();
59
+ directories = dirResults.flat().map((dir) => {
60
+ // glob returns string type paths, remove trailing slash
61
+ return String(dir).replace(/\/$/, "");
62
+ });
63
+ }
64
+ else {
65
+ // Build multiple glob patterns to support more flexible search
66
+ const filePatterns = [
67
+ // Match files with filenames containing query
68
+ `**/*${query}*`,
69
+ // Match files with query in path (match directory names)
70
+ `**/${query}*/**/*`,
71
+ ];
72
+ const dirPatterns = [
73
+ // Match directory names containing query
74
+ `**/*${query}*/`,
75
+ // Match directories containing query in path
76
+ `**/${query}*/`,
77
+ ];
78
+ // Search files
79
+ const filePromises = filePatterns.map((pattern) => glob(pattern, { ...globOptions, nodir: true }));
80
+ // Search directories
81
+ const dirPromises = dirPatterns.map((pattern) => glob(pattern, { ...globOptions, nodir: false }));
82
+ const fileResults = await Promise.all(filePromises);
83
+ const dirResults = await Promise.all(dirPromises);
84
+ files = fileResults.flat();
85
+ directories = dirResults.flat().map((dir) => {
86
+ // glob returns string type paths, remove trailing slash
87
+ return String(dir).replace(/\/$/, "");
88
+ });
89
+ }
90
+ // Deduplicate and merge files and directories
91
+ const uniqueFiles = Array.from(new Set(files));
92
+ const uniqueDirectories = Array.from(new Set(directories));
93
+ const allPaths = [...uniqueDirectories, ...uniqueFiles]; // Directories first
94
+ // Limit to maximum results and convert to FileItem
95
+ const fileItems = convertToFileItems(allPaths.slice(0, maxResults));
96
+ return fileItems;
97
+ }
98
+ catch (error) {
99
+ console.error("Glob search error:", error);
100
+ return [];
101
+ }
102
+ };
@@ -216,7 +216,7 @@ const truncateLogFileIfNeeded = (config) => {
216
216
  fs.writeFileSync(logFile, truncatedContent);
217
217
  // Record truncation operation
218
218
  const removedLines = lines.length - keepLines;
219
- logger.info(`Log file truncated: removed ${removedLines} lines, kept last ${keepLines} lines`);
219
+ logger.debug(`Log file truncated: removed ${removedLines} lines, kept last ${keepLines} lines`);
220
220
  }
221
221
  }
222
222
  catch (error) {
@@ -235,11 +235,11 @@ export const cleanupLogs = async (customConfig) => {
235
235
  return;
236
236
  }
237
237
  const config = { ...getCleanupConfig(), ...customConfig };
238
- logger.info("Starting log cleanup...", {
238
+ logger.debug("Starting log cleanup...", {
239
239
  maxFileSize: config.maxFileSize,
240
240
  keepLines: config.keepLines,
241
241
  });
242
242
  // Truncate current log file (if needed)
243
243
  truncateLogFileIfNeeded(config);
244
- logger.info("Log cleanup completed");
244
+ logger.debug("Log cleanup completed");
245
245
  };
@@ -0,0 +1,27 @@
1
+ import type { Usage } from "wave-agent-sdk";
2
+ /**
3
+ * Token summary by model
4
+ */
5
+ export interface TokenSummary {
6
+ model: string;
7
+ prompt_tokens: number;
8
+ completion_tokens: number;
9
+ total_tokens: number;
10
+ operations: {
11
+ agent_calls: number;
12
+ compressions: number;
13
+ };
14
+ }
15
+ /**
16
+ * Calculate token usage summary by model from usage array
17
+ * @param usages Array of usage data from agent operations
18
+ * @returns Array of token summaries grouped by model
19
+ */
20
+ export declare function calculateTokenSummary(usages: Usage[]): Record<string, TokenSummary>;
21
+ /**
22
+ * Display usage summary in a formatted way
23
+ * @param usages Array of usage data from agent operations
24
+ * @param sessionFilePath Optional session file path to display
25
+ */
26
+ export declare function displayUsageSummary(usages: Usage[], sessionFilePath?: string): void;
27
+ //# sourceMappingURL=usageSummary.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usageSummary.d.ts","sourceRoot":"","sources":["../../src/utils/usageSummary.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAE5C;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE;QACV,WAAW,EAAE,MAAM,CAAC;QACpB,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;CACH;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,KAAK,EAAE,GACd,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CA2C9B;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,KAAK,EAAE,EACf,eAAe,CAAC,EAAE,MAAM,GACvB,IAAI,CAgDN"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Calculate token usage summary by model from usage array
3
+ * @param usages Array of usage data from agent operations
4
+ * @returns Array of token summaries grouped by model
5
+ */
6
+ export function calculateTokenSummary(usages) {
7
+ const summaryMap = new Map();
8
+ for (const usage of usages) {
9
+ const model = usage.model || "unknown";
10
+ if (!summaryMap.has(model)) {
11
+ summaryMap.set(model, {
12
+ model,
13
+ prompt_tokens: 0,
14
+ completion_tokens: 0,
15
+ total_tokens: 0,
16
+ operations: {
17
+ agent_calls: 0,
18
+ compressions: 0,
19
+ },
20
+ });
21
+ }
22
+ const summary = summaryMap.get(model);
23
+ summary.prompt_tokens += usage.prompt_tokens;
24
+ summary.completion_tokens += usage.completion_tokens;
25
+ summary.total_tokens += usage.total_tokens;
26
+ // Track operation types
27
+ if (usage.operation_type === "agent") {
28
+ summary.operations.agent_calls += 1;
29
+ }
30
+ else if (usage.operation_type === "compress") {
31
+ summary.operations.compressions += 1;
32
+ }
33
+ }
34
+ // Convert Map to Record and sort by total tokens
35
+ const result = {};
36
+ const sortedEntries = Array.from(summaryMap.entries()).sort((a, b) => b[1].total_tokens - a[1].total_tokens);
37
+ for (const [model, summary] of sortedEntries) {
38
+ result[model] = summary;
39
+ }
40
+ return result;
41
+ }
42
+ /**
43
+ * Display usage summary in a formatted way
44
+ * @param usages Array of usage data from agent operations
45
+ * @param sessionFilePath Optional session file path to display
46
+ */
47
+ export function displayUsageSummary(usages, sessionFilePath) {
48
+ if (usages.length === 0) {
49
+ return; // No usage data to display
50
+ }
51
+ const summaries = calculateTokenSummary(usages);
52
+ console.log("\nToken Usage Summary:");
53
+ console.log("==================");
54
+ if (sessionFilePath) {
55
+ console.log(`Session: ${sessionFilePath}`);
56
+ }
57
+ let totalPrompt = 0;
58
+ let totalCompletion = 0;
59
+ let totalTokens = 0;
60
+ let totalAgentCalls = 0;
61
+ let totalCompressions = 0;
62
+ for (const [, summary] of Object.entries(summaries)) {
63
+ console.log(`Model: ${summary.model}`);
64
+ console.log(` Prompt tokens: ${summary.prompt_tokens.toLocaleString()}`);
65
+ console.log(` Completion tokens: ${summary.completion_tokens.toLocaleString()}`);
66
+ console.log(` Total tokens: ${summary.total_tokens.toLocaleString()}`);
67
+ console.log(` Operations: ${summary.operations.agent_calls} agent calls, ${summary.operations.compressions} compressions`);
68
+ console.log();
69
+ totalPrompt += summary.prompt_tokens;
70
+ totalCompletion += summary.completion_tokens;
71
+ totalTokens += summary.total_tokens;
72
+ totalAgentCalls += summary.operations.agent_calls;
73
+ totalCompressions += summary.operations.compressions;
74
+ }
75
+ if (Object.keys(summaries).length > 1) {
76
+ console.log("Overall Total:");
77
+ console.log(` Prompt tokens: ${totalPrompt.toLocaleString()}`);
78
+ console.log(` Completion tokens: ${totalCompletion.toLocaleString()}`);
79
+ console.log(` Total tokens: ${totalTokens.toLocaleString()}`);
80
+ console.log(` Operations: ${totalAgentCalls} agent calls, ${totalCompressions} compressions`);
81
+ }
82
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wave-code",
3
- "version": "0.0.4",
3
+ "version": "0.0.5",
4
4
  "description": "CLI-based code assistant powered by AI, built with React and Ink",
5
5
  "keywords": [
6
6
  "ai",
@@ -29,7 +29,7 @@
29
29
  "yargs": "^17.7.2",
30
30
  "diff": "^8.0.2",
31
31
  "glob": "^11.0.3",
32
- "wave-agent-sdk": "0.0.4"
32
+ "wave-agent-sdk": "0.0.7"
33
33
  },
34
34
  "devDependencies": {
35
35
  "@types/react": "^19.1.8",