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
@@ -1,13 +1,14 @@
1
1
  import { Agent, AgentCallbacks } from "wave-agent-sdk";
2
2
  import { logger } from "./utils/logger.js";
3
+ import { displayUsageSummary } from "./utils/usageSummary.js";
3
4
 
4
- export interface PlainCliOptions {
5
+ export interface PrintCliOptions {
5
6
  restoreSessionId?: string;
6
7
  continueLastSession?: boolean;
7
8
  message?: string;
8
9
  }
9
10
 
10
- export async function startPlainCli(options: PlainCliOptions): Promise<void> {
11
+ export async function startPrintCli(options: PrintCliOptions): Promise<void> {
11
12
  const { restoreSessionId, continueLastSession, message } = options;
12
13
 
13
14
  if (
@@ -16,7 +17,7 @@ export async function startPlainCli(options: PlainCliOptions): Promise<void> {
16
17
  !restoreSessionId
17
18
  ) {
18
19
  console.error(
19
- "Plain mode requires a message: use --plain 'your message' or -p 'your message'",
20
+ "Print mode requires a message: use --print 'your message' or -p 'your message'",
20
21
  );
21
22
  process.exit(1);
22
23
  }
@@ -47,12 +48,29 @@ export async function startPlainCli(options: PlainCliOptions): Promise<void> {
47
48
  await agent.sendMessage(message);
48
49
  }
49
50
 
51
+ // Display usage summary before exit
52
+ try {
53
+ const usages = agent.usages;
54
+ const sessionFilePath = agent.sessionFilePath;
55
+ displayUsageSummary(usages, sessionFilePath);
56
+ } catch {
57
+ // Silently ignore usage summary errors
58
+ }
59
+
50
60
  // Destroy agent and exit after sendMessage completes
51
61
  agent.destroy();
52
62
  process.exit(0);
53
63
  } catch (error) {
54
64
  console.error("Failed to send message:", error);
55
65
  if (agent!) {
66
+ // Display usage summary even on error
67
+ try {
68
+ const usages = agent.usages;
69
+ const sessionFilePath = agent.sessionFilePath;
70
+ displayUsageSummary(usages, sessionFilePath);
71
+ } catch {
72
+ // Silently ignore usage summary errors
73
+ }
56
74
  agent.destroy();
57
75
  }
58
76
  process.exit(1);
@@ -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,125 @@
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
+ }
16
+
17
+ /**
18
+ * Calculate token usage summary by model from usage array
19
+ * @param usages Array of usage data from agent operations
20
+ * @returns Array of token summaries grouped by model
21
+ */
22
+ export function calculateTokenSummary(
23
+ usages: Usage[],
24
+ ): Record<string, TokenSummary> {
25
+ const summaryMap = new Map<string, TokenSummary>();
26
+
27
+ for (const usage of usages) {
28
+ const model = usage.model || "unknown";
29
+
30
+ if (!summaryMap.has(model)) {
31
+ summaryMap.set(model, {
32
+ model,
33
+ prompt_tokens: 0,
34
+ completion_tokens: 0,
35
+ total_tokens: 0,
36
+ operations: {
37
+ agent_calls: 0,
38
+ compressions: 0,
39
+ },
40
+ });
41
+ }
42
+
43
+ const summary = summaryMap.get(model)!;
44
+ summary.prompt_tokens += usage.prompt_tokens;
45
+ summary.completion_tokens += usage.completion_tokens;
46
+ summary.total_tokens += usage.total_tokens;
47
+
48
+ // Track operation types
49
+ if (usage.operation_type === "agent") {
50
+ summary.operations.agent_calls += 1;
51
+ } else if (usage.operation_type === "compress") {
52
+ summary.operations.compressions += 1;
53
+ }
54
+ }
55
+
56
+ // Convert Map to Record and sort by total tokens
57
+ const result: Record<string, TokenSummary> = {};
58
+ const sortedEntries = Array.from(summaryMap.entries()).sort(
59
+ (a, b) => b[1].total_tokens - a[1].total_tokens,
60
+ );
61
+
62
+ for (const [model, summary] of sortedEntries) {
63
+ result[model] = summary;
64
+ }
65
+
66
+ return result;
67
+ }
68
+
69
+ /**
70
+ * Display usage summary in a formatted way
71
+ * @param usages Array of usage data from agent operations
72
+ * @param sessionFilePath Optional session file path to display
73
+ */
74
+ export function displayUsageSummary(
75
+ usages: Usage[],
76
+ sessionFilePath?: string,
77
+ ): void {
78
+ if (usages.length === 0) {
79
+ return; // No usage data to display
80
+ }
81
+
82
+ const summaries = calculateTokenSummary(usages);
83
+
84
+ console.log("\nToken Usage Summary:");
85
+ console.log("==================");
86
+
87
+ if (sessionFilePath) {
88
+ console.log(`Session: ${sessionFilePath}`);
89
+ }
90
+
91
+ let totalPrompt = 0;
92
+ let totalCompletion = 0;
93
+ let totalTokens = 0;
94
+ let totalAgentCalls = 0;
95
+ let totalCompressions = 0;
96
+
97
+ for (const [, summary] of Object.entries(summaries)) {
98
+ console.log(`Model: ${summary.model}`);
99
+ console.log(` Prompt tokens: ${summary.prompt_tokens.toLocaleString()}`);
100
+ console.log(
101
+ ` Completion tokens: ${summary.completion_tokens.toLocaleString()}`,
102
+ );
103
+ console.log(` Total tokens: ${summary.total_tokens.toLocaleString()}`);
104
+ console.log(
105
+ ` Operations: ${summary.operations.agent_calls} agent calls, ${summary.operations.compressions} compressions`,
106
+ );
107
+ console.log();
108
+
109
+ totalPrompt += summary.prompt_tokens;
110
+ totalCompletion += summary.completion_tokens;
111
+ totalTokens += summary.total_tokens;
112
+ totalAgentCalls += summary.operations.agent_calls;
113
+ totalCompressions += summary.operations.compressions;
114
+ }
115
+
116
+ if (Object.keys(summaries).length > 1) {
117
+ console.log("Overall Total:");
118
+ console.log(` Prompt tokens: ${totalPrompt.toLocaleString()}`);
119
+ console.log(` Completion tokens: ${totalCompletion.toLocaleString()}`);
120
+ console.log(` Total tokens: ${totalTokens.toLocaleString()}`);
121
+ console.log(
122
+ ` Operations: ${totalAgentCalls} agent calls, ${totalCompressions} compressions`,
123
+ );
124
+ }
125
+ }
@@ -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"}
@@ -1,98 +0,0 @@
1
- import { useState, useCallback } from "react";
2
- export const useCommandSelector = ({ onShowBashManager, onShowMcpManager, sendMessage, hasSlashCommand, }) => {
3
- const [showCommandSelector, setShowCommandSelector] = useState(false);
4
- const [slashPosition, setSlashPosition] = useState(-1);
5
- const [commandSearchQuery, setCommandSearchQuery] = useState("");
6
- const activateCommandSelector = useCallback((position) => {
7
- setShowCommandSelector(true);
8
- setSlashPosition(position);
9
- setCommandSearchQuery("");
10
- }, []);
11
- const handleCommandInsert = useCallback((command, inputText, cursorPosition) => {
12
- if (slashPosition >= 0) {
13
- // Replace content from / to current cursor position with /command_name + space
14
- const beforeSlash = inputText.substring(0, slashPosition);
15
- const afterQuery = inputText.substring(cursorPosition);
16
- const newInput = beforeSlash + `/${command} ` + afterQuery;
17
- const newCursorPosition = beforeSlash.length + command.length + 2; // +2 for "/" and " "
18
- setShowCommandSelector(false);
19
- setSlashPosition(-1);
20
- setCommandSearchQuery("");
21
- return { newInput, newCursorPosition };
22
- }
23
- return { newInput: inputText, newCursorPosition: cursorPosition };
24
- }, [slashPosition]);
25
- const handleCommandSelect = useCallback((command, inputText, cursorPosition) => {
26
- if (slashPosition >= 0) {
27
- // Replace command part, keep other content
28
- const beforeSlash = inputText.substring(0, slashPosition);
29
- const afterQuery = inputText.substring(cursorPosition);
30
- const newInput = beforeSlash + afterQuery;
31
- const newCursorPosition = beforeSlash.length;
32
- // Execute command asynchronously
33
- (async () => {
34
- // First check if it's an agent command
35
- let commandExecuted = false;
36
- if (sendMessage && hasSlashCommand && hasSlashCommand(command)) {
37
- // Execute complete command (replace partial input with complete command name)
38
- const fullCommand = `/${command}`;
39
- try {
40
- await sendMessage(fullCommand);
41
- commandExecuted = true;
42
- }
43
- catch (error) {
44
- console.error("Failed to execute slash command:", error);
45
- }
46
- }
47
- // If not an agent command or execution failed, check local commands
48
- if (!commandExecuted) {
49
- if (command === "bashes" && onShowBashManager) {
50
- onShowBashManager();
51
- commandExecuted = true;
52
- }
53
- else if (command === "mcp" && onShowMcpManager) {
54
- onShowMcpManager();
55
- commandExecuted = true;
56
- }
57
- }
58
- })();
59
- setShowCommandSelector(false);
60
- setSlashPosition(-1);
61
- setCommandSearchQuery("");
62
- return { newInput, newCursorPosition };
63
- }
64
- return { newInput: inputText, newCursorPosition: cursorPosition };
65
- }, [
66
- slashPosition,
67
- onShowBashManager,
68
- onShowMcpManager,
69
- sendMessage,
70
- hasSlashCommand,
71
- ]);
72
- const handleCancelCommandSelect = useCallback(() => {
73
- setShowCommandSelector(false);
74
- setSlashPosition(-1);
75
- setCommandSearchQuery("");
76
- }, []);
77
- const updateCommandSearchQuery = useCallback((query) => {
78
- setCommandSearchQuery(query);
79
- }, []);
80
- const checkForSlashDeletion = useCallback((cursorPosition) => {
81
- if (showCommandSelector && cursorPosition <= slashPosition) {
82
- handleCancelCommandSelect();
83
- return true;
84
- }
85
- return false;
86
- }, [showCommandSelector, slashPosition, handleCancelCommandSelect]);
87
- return {
88
- showCommandSelector,
89
- commandSearchQuery,
90
- activateCommandSelector,
91
- handleCommandSelect,
92
- handleCommandInsert,
93
- handleCancelCommandSelect,
94
- updateCommandSearchQuery,
95
- checkForSlashDeletion,
96
- slashPosition,
97
- };
98
- };
@@ -1,16 +0,0 @@
1
- import { FileItem } from "../components/FileSelector.js";
2
- export declare const useFileSelector: () => {
3
- showFileSelector: boolean;
4
- filteredFiles: FileItem[];
5
- searchQuery: string;
6
- activateFileSelector: (position: number) => void;
7
- handleFileSelect: (filePath: string, inputText: string, cursorPosition: number) => {
8
- newInput: string;
9
- newCursorPosition: number;
10
- };
11
- handleCancelFileSelect: () => void;
12
- updateSearchQuery: (query: string) => void;
13
- checkForAtDeletion: (cursorPosition: number) => boolean;
14
- atPosition: number;
15
- };
16
- //# sourceMappingURL=useFileSelector.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useFileSelector.d.ts","sourceRoot":"","sources":["../../src/hooks/useFileSelector.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AAEzD,eAAO,MAAM,eAAe;;;;qCA2Jb,MAAM;iCAWN,MAAM,aAAa,MAAM,kBAAkB,MAAM;;;;;+BA2BhB,MAAM;yCAKjC,MAAM;;CAqB1B,CAAC"}