snow-ai 0.3.6 → 0.3.7

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 (101) hide show
  1. package/dist/agents/reviewAgent.d.ts +50 -0
  2. package/dist/agents/reviewAgent.js +264 -0
  3. package/dist/api/anthropic.js +104 -71
  4. package/dist/api/chat.d.ts +1 -1
  5. package/dist/api/chat.js +60 -41
  6. package/dist/api/gemini.js +97 -57
  7. package/dist/api/responses.d.ts +9 -1
  8. package/dist/api/responses.js +110 -70
  9. package/dist/api/systemPrompt.d.ts +1 -1
  10. package/dist/api/systemPrompt.js +36 -7
  11. package/dist/api/types.d.ts +8 -0
  12. package/dist/hooks/useCommandHandler.d.ts +1 -0
  13. package/dist/hooks/useCommandHandler.js +44 -1
  14. package/dist/hooks/useCommandPanel.js +13 -0
  15. package/dist/hooks/useConversation.d.ts +4 -1
  16. package/dist/hooks/useConversation.js +48 -6
  17. package/dist/hooks/useKeyboardInput.js +19 -0
  18. package/dist/hooks/useTerminalFocus.js +13 -3
  19. package/dist/mcp/aceCodeSearch.d.ts +2 -76
  20. package/dist/mcp/aceCodeSearch.js +31 -467
  21. package/dist/mcp/bash.d.ts +1 -8
  22. package/dist/mcp/bash.js +20 -40
  23. package/dist/mcp/filesystem.d.ts +3 -68
  24. package/dist/mcp/filesystem.js +32 -348
  25. package/dist/mcp/ideDiagnostics.js +2 -4
  26. package/dist/mcp/todo.d.ts +1 -17
  27. package/dist/mcp/todo.js +11 -15
  28. package/dist/mcp/types/aceCodeSearch.types.d.ts +92 -0
  29. package/dist/mcp/types/aceCodeSearch.types.js +4 -0
  30. package/dist/mcp/types/bash.types.d.ts +13 -0
  31. package/dist/mcp/types/bash.types.js +4 -0
  32. package/dist/mcp/types/filesystem.types.d.ts +44 -0
  33. package/dist/mcp/types/filesystem.types.js +4 -0
  34. package/dist/mcp/types/todo.types.d.ts +27 -0
  35. package/dist/mcp/types/todo.types.js +4 -0
  36. package/dist/mcp/types/websearch.types.d.ts +30 -0
  37. package/dist/mcp/types/websearch.types.js +4 -0
  38. package/dist/mcp/utils/aceCodeSearch/filesystem.utils.d.ts +34 -0
  39. package/dist/mcp/utils/aceCodeSearch/filesystem.utils.js +146 -0
  40. package/dist/mcp/utils/aceCodeSearch/language.utils.d.ts +14 -0
  41. package/dist/mcp/utils/aceCodeSearch/language.utils.js +99 -0
  42. package/dist/mcp/utils/aceCodeSearch/search.utils.d.ts +31 -0
  43. package/dist/mcp/utils/aceCodeSearch/search.utils.js +136 -0
  44. package/dist/mcp/utils/aceCodeSearch/symbol.utils.d.ts +20 -0
  45. package/dist/mcp/utils/aceCodeSearch/symbol.utils.js +141 -0
  46. package/dist/mcp/utils/bash/security.utils.d.ts +20 -0
  47. package/dist/mcp/utils/bash/security.utils.js +34 -0
  48. package/dist/mcp/utils/filesystem/code-analysis.utils.d.ts +18 -0
  49. package/dist/mcp/utils/filesystem/code-analysis.utils.js +165 -0
  50. package/dist/mcp/utils/filesystem/match-finder.utils.d.ts +16 -0
  51. package/dist/mcp/utils/filesystem/match-finder.utils.js +85 -0
  52. package/dist/mcp/utils/filesystem/similarity.utils.d.ts +22 -0
  53. package/dist/mcp/utils/filesystem/similarity.utils.js +75 -0
  54. package/dist/mcp/utils/todo/date.utils.d.ts +9 -0
  55. package/dist/mcp/utils/todo/date.utils.js +14 -0
  56. package/dist/mcp/utils/websearch/browser.utils.d.ts +8 -0
  57. package/dist/mcp/utils/websearch/browser.utils.js +58 -0
  58. package/dist/mcp/utils/websearch/text.utils.d.ts +16 -0
  59. package/dist/mcp/utils/websearch/text.utils.js +39 -0
  60. package/dist/mcp/websearch.d.ts +1 -31
  61. package/dist/mcp/websearch.js +21 -97
  62. package/dist/ui/components/ChatInput.d.ts +2 -1
  63. package/dist/ui/components/ChatInput.js +10 -3
  64. package/dist/ui/components/MarkdownRenderer.d.ts +1 -2
  65. package/dist/ui/components/MarkdownRenderer.js +16 -153
  66. package/dist/ui/components/MessageList.js +4 -4
  67. package/dist/ui/components/SessionListScreen.js +37 -17
  68. package/dist/ui/components/ToolResultPreview.js +6 -6
  69. package/dist/ui/components/UsagePanel.d.ts +2 -0
  70. package/dist/ui/components/UsagePanel.js +360 -0
  71. package/dist/ui/pages/ChatScreen.d.ts +4 -0
  72. package/dist/ui/pages/ChatScreen.js +70 -30
  73. package/dist/ui/pages/ConfigScreen.js +23 -19
  74. package/dist/ui/pages/HeadlessModeScreen.js +2 -4
  75. package/dist/ui/pages/SubAgentConfigScreen.js +17 -17
  76. package/dist/ui/pages/SystemPromptConfigScreen.js +7 -6
  77. package/dist/utils/commandExecutor.d.ts +3 -3
  78. package/dist/utils/commandExecutor.js +4 -4
  79. package/dist/utils/commands/home.d.ts +2 -0
  80. package/dist/utils/commands/home.js +12 -0
  81. package/dist/utils/commands/review.d.ts +2 -0
  82. package/dist/utils/commands/review.js +81 -0
  83. package/dist/utils/commands/role.d.ts +2 -0
  84. package/dist/utils/commands/role.js +37 -0
  85. package/dist/utils/commands/usage.d.ts +2 -0
  86. package/dist/utils/commands/usage.js +12 -0
  87. package/dist/utils/contextCompressor.js +99 -367
  88. package/dist/utils/fileUtils.js +3 -3
  89. package/dist/utils/mcpToolsManager.js +12 -12
  90. package/dist/utils/proxyUtils.d.ts +15 -0
  91. package/dist/utils/proxyUtils.js +50 -0
  92. package/dist/utils/retryUtils.d.ts +27 -0
  93. package/dist/utils/retryUtils.js +114 -2
  94. package/dist/utils/sessionManager.d.ts +2 -5
  95. package/dist/utils/sessionManager.js +16 -83
  96. package/dist/utils/terminal.js +4 -3
  97. package/dist/utils/usageLogger.d.ts +11 -0
  98. package/dist/utils/usageLogger.js +99 -0
  99. package/package.json +3 -7
  100. package/dist/agents/summaryAgent.d.ts +0 -31
  101. package/dist/agents/summaryAgent.js +0 -256
@@ -1,159 +1,22 @@
1
1
  import React from 'react';
2
- import { Box, Text } from 'ink';
2
+ import { Text } from 'ink';
3
3
  import { highlight } from 'cli-highlight';
4
- export default function MarkdownRenderer({ content, color }) {
5
- const blocks = parseMarkdown(content);
6
- return (React.createElement(Box, { flexDirection: "column" }, blocks.map((block, index) => {
7
- if (block.type === 'code') {
8
- return (React.createElement(Box, { key: index, flexDirection: "column", marginY: 0 },
9
- React.createElement(Box, { borderStyle: "round", borderColor: "blue" },
10
- React.createElement(Box, { flexDirection: "column" },
11
- block.language && (React.createElement(Text, { backgroundColor: "green", color: "white" }, block.language)),
12
- React.createElement(Text, null, highlightCode(block.code, block.language))))));
13
- }
14
- // Render heading
15
- if (block.type === 'heading') {
16
- const headingColors = ['cyan', 'blue', 'magenta', 'yellow'];
17
- const headingColor = headingColors[block.level - 1] || 'white';
18
- return (React.createElement(Box, { key: index, marginY: 0 },
19
- React.createElement(Text, { bold: true, color: headingColor }, renderInlineFormatting(block.content))));
20
- }
21
- // Render list
22
- if (block.type === 'list') {
23
- return (React.createElement(Box, { key: index, flexDirection: "column", marginY: 0 }, block.items.map((item, itemIndex) => (React.createElement(Box, { key: itemIndex },
24
- React.createElement(Text, { color: "yellow" }, "\u2022 "),
25
- React.createElement(Text, { color: color }, renderInlineFormatting(item)))))));
26
- }
27
- // Render text with inline formatting
28
- return (React.createElement(Box, { key: index, flexDirection: "column" }, block.content
29
- .split('\n')
30
- .map((line, lineIndex) => (React.createElement(Text, { key: lineIndex, color: color }, line === '' ? ' ' : renderInlineFormatting(line))))));
31
- })));
32
- }
33
- function parseMarkdown(content) {
34
- const blocks = [];
35
- const lines = content.split('\n');
36
- let i = 0;
37
- while (i < lines.length) {
38
- const line = lines[i] ?? '';
39
- // Check for code block - support ```language or just ```
40
- const codeBlockMatch = line.match(/^```(.*)$/);
41
- if (codeBlockMatch) {
42
- const language = codeBlockMatch[1]?.trim() || '';
43
- const codeLines = [];
44
- i++;
45
- // Collect code block lines
46
- while (i < lines.length) {
47
- const currentLine = lines[i] ?? '';
48
- if (currentLine.trim().startsWith('```')) {
49
- break;
50
- }
51
- codeLines.push(currentLine);
52
- i++;
53
- }
54
- blocks.push({
55
- type: 'code',
56
- language,
57
- code: codeLines.join('\n'),
58
- });
59
- i++; // Skip closing ```
60
- continue;
61
- }
62
- // Check for heading (# ## ### ####)
63
- const headingMatch = line.match(/^(#{1,6})\s+(.+)$/);
64
- if (headingMatch) {
65
- blocks.push({
66
- type: 'heading',
67
- level: headingMatch[1].length,
68
- content: headingMatch[2].trim(),
69
- });
70
- i++;
71
- continue;
72
- }
73
- // Check for list item (* or -)
74
- const listMatch = line.match(/^[\s]*[*\-]\s+(.+)$/);
75
- if (listMatch) {
76
- const listItems = [listMatch[1].trim()];
77
- i++;
78
- // Collect consecutive list items
79
- while (i < lines.length) {
80
- const currentLine = lines[i] ?? '';
81
- const nextListMatch = currentLine.match(/^[\s]*[*\-]\s+(.+)$/);
82
- if (!nextListMatch) {
83
- break;
84
- }
85
- listItems.push(nextListMatch[1].trim());
86
- i++;
4
+ // @ts-expect-error - cli-markdown doesn't have TypeScript definitions
5
+ import cliMarkdown from 'cli-markdown';
6
+ export default function MarkdownRenderer({ content }) {
7
+ // Use cli-markdown for elegant markdown rendering with syntax highlighting
8
+ const rendered = cliMarkdown(content, {
9
+ // Enable syntax highlighting for code blocks
10
+ code: (code, language) => {
11
+ if (!language)
12
+ return code;
13
+ try {
14
+ return highlight(code, { language, ignoreIllegals: true });
87
15
  }
88
- blocks.push({
89
- type: 'list',
90
- items: listItems,
91
- });
92
- continue;
93
- }
94
- // Collect text lines until next code block, heading, or list
95
- const textLines = [];
96
- while (i < lines.length) {
97
- const currentLine = lines[i] ?? '';
98
- if (currentLine.trim().startsWith('```') ||
99
- currentLine.match(/^#{1,6}\s+/) ||
100
- currentLine.match(/^[\s]*[*\-]\s+/)) {
101
- break;
16
+ catch {
17
+ return code;
102
18
  }
103
- textLines.push(currentLine);
104
- i++;
105
- }
106
- if (textLines.length > 0) {
107
- blocks.push({
108
- type: 'text',
109
- content: textLines.join('\n'),
110
- });
111
- }
112
- }
113
- return blocks;
114
- }
115
- function highlightCode(code, language) {
116
- try {
117
- // If no language specified, try to auto-detect or just return the code
118
- if (!language) {
119
- return code;
120
- }
121
- // Map common language aliases to cli-highlight supported names
122
- const languageMap = {
123
- js: 'javascript',
124
- ts: 'typescript',
125
- py: 'python',
126
- rb: 'ruby',
127
- sh: 'bash',
128
- shell: 'bash',
129
- cs: 'csharp',
130
- 'c#': 'csharp',
131
- cpp: 'cpp',
132
- 'c++': 'cpp',
133
- yml: 'yaml',
134
- md: 'markdown',
135
- };
136
- const mappedLanguage = languageMap[language.toLowerCase()] || language.toLowerCase();
137
- return highlight(code, { language: mappedLanguage, ignoreIllegals: true });
138
- }
139
- catch {
140
- // If highlighting fails, return the code as-is
141
- return code;
142
- }
143
- }
144
- function renderInlineFormatting(text) {
145
- // Handle inline code `code` - remove backticks
146
- text = text.replace(/`([^`]+)`/g, (_, code) => {
147
- // Use ANSI codes for inline code styling
148
- return `\x1b[36m${code}\x1b[0m`;
149
- });
150
- // Handle bold **text** or __text__ - remove markers
151
- text = text.replace(/(\*\*|__)([^*_]+)\1/g, (_, __, content) => {
152
- return `\x1b[1m${content}\x1b[0m`;
153
- });
154
- // Handle italic *text* or _text_ (but not part of bold) - remove markers
155
- text = text.replace(/(?<!\*)(\*)(?!\*)([^*]+)\1(?!\*)/g, (_, __, content) => {
156
- return `\x1b[3m${content}\x1b[0m`;
19
+ },
157
20
  });
158
- return text;
21
+ return React.createElement(Text, null, rendered);
159
22
  }
@@ -24,7 +24,7 @@ const MessageList = memo(({ messages, animationFrame, maxMessages = 6 }) => {
24
24
  : message.role === 'subagent'
25
25
  ? '◈'
26
26
  : '❆'),
27
- React.createElement(Box, { marginLeft: 1, marginBottom: 1, flexDirection: "column" }, message.role === 'command' ? (React.createElement(Text, { color: "gray" },
27
+ React.createElement(Box, { marginLeft: 1, flexDirection: "column" }, message.role === 'command' ? (React.createElement(Text, { color: "gray" },
28
28
  "\u2514\u2500 ",
29
29
  message.commandName)) : message.role === 'subagent' ? (React.createElement(React.Fragment, null,
30
30
  React.createElement(Text, { color: "magenta", dimColor: true },
@@ -32,12 +32,12 @@ const MessageList = memo(({ messages, animationFrame, maxMessages = 6 }) => {
32
32
  message.subAgent?.agentName,
33
33
  message.subAgent?.isComplete ? ' ✓' : ' ...'),
34
34
  React.createElement(Box, { marginLeft: 2 },
35
- React.createElement(MarkdownRenderer, { content: message.content || ' ', color: "gray" })))) : (React.createElement(React.Fragment, null,
36
- React.createElement(MarkdownRenderer, { content: message.content || ' ', color: message.role === 'user' ? 'gray' : undefined }),
35
+ React.createElement(Text, { color: "gray" }, message.content || ' ')))) : (React.createElement(React.Fragment, null,
36
+ message.role === 'user' ? (React.createElement(Text, { color: "gray" }, message.content || ' ')) : (React.createElement(MarkdownRenderer, { content: message.content || ' ' })),
37
37
  (message.systemInfo ||
38
38
  message.files ||
39
39
  message.files ||
40
- message.images) && (React.createElement(Box, { marginTop: 1, flexDirection: "column" },
40
+ message.images) && (React.createElement(Box, { flexDirection: "column" },
41
41
  message.systemInfo && (React.createElement(React.Fragment, null,
42
42
  React.createElement(Text, { color: "gray", dimColor: true },
43
43
  "\u2514\u2500 Platform: ",
@@ -3,7 +3,7 @@ import { Box, Text, useInput, useStdout } from 'ink';
3
3
  import Gradient from 'ink-gradient';
4
4
  import { Alert } from '@inkjs/ui';
5
5
  import ScrollableSelectInput from './ScrollableSelectInput.js';
6
- import { sessionManager } from '../../utils/sessionManager.js';
6
+ import { sessionManager, } from '../../utils/sessionManager.js';
7
7
  export default function SessionListScreen({ onBack, onSelectSession }) {
8
8
  const [sessions, setSessions] = useState([]);
9
9
  const [loading, setLoading] = useState(true);
@@ -53,22 +53,35 @@ export default function SessionListScreen({ onBack, onSelectSession }) {
53
53
  // Create select items with truncated labels
54
54
  const selectItems = useMemo(() => {
55
55
  const terminalWidth = stdout?.columns || 80;
56
- // Increase margin and ensure minimum width
57
- const maxLabelWidth = Math.max(20, terminalWidth - 20);
56
+ // Reserve space for indicators (✔ + ❯ + spacing) and margins
57
+ const reservedSpace = 30;
58
+ const maxLabelWidth = Math.max(30, terminalWidth - reservedSpace);
58
59
  return sessions.map(session => {
59
60
  const timeString = formatDate(session.updatedAt);
60
61
  const title = session.title || 'Untitled';
61
- const label = `${title} (${session.messageCount}) - ${timeString}`;
62
- // Truncate if too long with safer boundary check
63
- let truncatedLabel = label;
64
- if (label.length > maxLabelWidth) {
65
- const maxLength = Math.max(10, maxLabelWidth - 3);
66
- truncatedLabel = label.substring(0, maxLength) + '...';
62
+ // Format: "Title 5 msgs • 2h ago"
63
+ const messageInfo = `${session.messageCount} msg${session.messageCount !== 1 ? 's' : ''}`;
64
+ const fullLabel = `${title} • ${messageInfo} • ${timeString}`;
65
+ // Truncate if too long - prioritize showing the title
66
+ let truncatedLabel = fullLabel;
67
+ if (fullLabel.length > maxLabelWidth) {
68
+ const ellipsis = '...';
69
+ const suffixLength = messageInfo.length + timeString.length + 6; // " • " x2 + "..."
70
+ const availableForTitle = maxLabelWidth - suffixLength - ellipsis.length;
71
+ if (availableForTitle > 10) {
72
+ const truncatedTitle = title.substring(0, availableForTitle);
73
+ truncatedLabel = `${truncatedTitle}${ellipsis} • ${messageInfo} • ${timeString}`;
74
+ }
75
+ else {
76
+ // If terminal is too narrow, just truncate the whole thing
77
+ truncatedLabel =
78
+ fullLabel.substring(0, maxLabelWidth - ellipsis.length) + ellipsis;
79
+ }
67
80
  }
68
81
  return {
69
82
  label: truncatedLabel,
70
83
  value: session.id,
71
- isMarked: selectedSessions.has(session.id)
84
+ isMarked: selectedSessions.has(session.id),
72
85
  };
73
86
  });
74
87
  }, [sessions, formatDate, stdout?.columns, selectedSessions]);
@@ -96,10 +109,14 @@ export default function SessionListScreen({ onBack, onSelectSession }) {
96
109
  const ids = Array.from(selectedSessions);
97
110
  const deletionResults = await Promise.all(ids.map(async (id) => ({
98
111
  id,
99
- success: await sessionManager.deleteSession(id)
112
+ success: await sessionManager.deleteSession(id),
100
113
  })));
101
- const succeededIds = deletionResults.filter(result => result.success).map(result => result.id);
102
- const failedIds = deletionResults.filter(result => !result.success).map(result => result.id);
114
+ const succeededIds = deletionResults
115
+ .filter(result => result.success)
116
+ .map(result => result.id);
117
+ const failedIds = deletionResults
118
+ .filter(result => !result.success)
119
+ .map(result => result.id);
103
120
  if (succeededIds.length > 0) {
104
121
  setSessions(previous => previous.filter(session => !succeededIds.includes(session.id)));
105
122
  setSelectedSessions(previous => {
@@ -113,13 +130,13 @@ export default function SessionListScreen({ onBack, onSelectSession }) {
113
130
  if (failedIds.length > 0) {
114
131
  setActionMessage({
115
132
  type: 'error',
116
- text: `Failed to delete ${failedIds.length} conversation${failedIds.length > 1 ? 's' : ''}.`
133
+ text: `Failed to delete ${failedIds.length} conversation${failedIds.length > 1 ? 's' : ''}.`,
117
134
  });
118
135
  }
119
136
  else if (succeededIds.length > 0) {
120
137
  setActionMessage({
121
138
  type: 'info',
122
- text: `Deleted ${succeededIds.length} conversation${succeededIds.length > 1 ? 's' : ''}.`
139
+ text: `Deleted ${succeededIds.length} conversation${succeededIds.length > 1 ? 's' : ''}.`,
123
140
  });
124
141
  }
125
142
  else {
@@ -182,7 +199,8 @@ export default function SessionListScreen({ onBack, onSelectSession }) {
182
199
  sessions.length,
183
200
  " conversation",
184
201
  sessions.length !== 1 ? 's' : '',
185
- " available"))),
202
+ ' ',
203
+ "available"))),
186
204
  React.createElement(Box, { marginBottom: 1, flexShrink: 0 },
187
205
  React.createElement(ScrollableSelectInput, { items: selectItems, limit: listLimit, onSelect: handleSelect, onToggleItem: handleToggleItem, onDeleteSelection: handleDeleteSelected, selectedValues: selectedSessions, indicator: ({ isSelected }) => (React.createElement(Text, { color: isSelected ? 'green' : 'gray' }, isSelected ? '❯ ' : ' ')), renderItem: ({ isSelected, isMarked, label }) => (React.createElement(Text, null,
188
206
  React.createElement(Text, { color: isMarked ? 'green' : 'gray' }, isMarked ? '✔ ' : ' '),
@@ -192,5 +210,7 @@ export default function SessionListScreen({ onBack, onSelectSession }) {
192
210
  React.createElement(Alert, { variant: actionMessage.type }, actionMessage.text))) : null,
193
211
  React.createElement(Alert, { variant: "info" },
194
212
  "\u2191\u2193 navigate \u2022 Space mark \u2022 D delete \u2022 Enter select \u2022 Esc return \u2022 R refresh",
195
- selectedSessions.size > 0 ? ` • ${selectedSessions.size} selected` : ''))));
213
+ selectedSessions.size > 0
214
+ ? ` • ${selectedSessions.size} selected`
215
+ : ''))));
196
216
  }
@@ -97,7 +97,7 @@ function renderListPreview(data, maxLines) {
97
97
  }
98
98
  function renderACEPreview(toolName, data, maxLines) {
99
99
  // Handle ace-text-search results
100
- if (toolName === 'ace-text-search' || toolName === 'ace_text_search') {
100
+ if (toolName === 'ace-text-search' || toolName === 'ace-text_search') {
101
101
  if (!data || data.length === 0) {
102
102
  return (React.createElement(Box, { marginLeft: 2 },
103
103
  React.createElement(Text, { color: "gray", dimColor: true }, "\u2514\u2500 No matches found")));
@@ -120,7 +120,7 @@ function renderACEPreview(toolName, data, maxLines) {
120
120
  " more matches)"))));
121
121
  }
122
122
  // Handle ace-search-symbols results
123
- if (toolName === 'ace-search-symbols' || toolName === 'ace_search_symbols') {
123
+ if (toolName === 'ace-search-symbols' || toolName === 'ace-search_symbols') {
124
124
  const symbols = data.symbols || [];
125
125
  if (symbols.length === 0) {
126
126
  return (React.createElement(Box, { marginLeft: 2 },
@@ -144,7 +144,7 @@ function renderACEPreview(toolName, data, maxLines) {
144
144
  " more symbols)"))));
145
145
  }
146
146
  // Handle ace-find-references results
147
- if (toolName === 'ace-find-references' || toolName === 'ace_find_references') {
147
+ if (toolName === 'ace-find-references' || toolName === 'ace-find_references') {
148
148
  const references = Array.isArray(data) ? data : [];
149
149
  if (references.length === 0) {
150
150
  return (React.createElement(Box, { marginLeft: 2 },
@@ -166,7 +166,7 @@ function renderACEPreview(toolName, data, maxLines) {
166
166
  " more references)"))));
167
167
  }
168
168
  // Handle ace-find-definition result
169
- if (toolName === 'ace-find-definition' || toolName === 'ace_find_definition') {
169
+ if (toolName === 'ace-find-definition' || toolName === 'ace-find_definition') {
170
170
  if (!data) {
171
171
  return (React.createElement(Box, { marginLeft: 2 },
172
172
  React.createElement(Text, { color: "gray", dimColor: true }, "\u2514\u2500 Definition not found")));
@@ -183,7 +183,7 @@ function renderACEPreview(toolName, data, maxLines) {
183
183
  data.line)));
184
184
  }
185
185
  // Handle ace-file-outline result
186
- if (toolName === 'ace-file-outline' || toolName === 'ace_file_outline') {
186
+ if (toolName === 'ace-file-outline' || toolName === 'ace-file_outline') {
187
187
  const symbols = Array.isArray(data) ? data : [];
188
188
  if (symbols.length === 0) {
189
189
  return (React.createElement(Box, { marginLeft: 2 },
@@ -206,7 +206,7 @@ function renderACEPreview(toolName, data, maxLines) {
206
206
  " more symbols)"))));
207
207
  }
208
208
  // Handle ace-semantic-search result
209
- if (toolName === 'ace-semantic-search' || toolName === 'ace_semantic_search') {
209
+ if (toolName === 'ace-semantic-search' || toolName === 'ace-semantic_search') {
210
210
  const totalResults = (data.symbols?.length || 0) + (data.references?.length || 0);
211
211
  if (totalResults === 0) {
212
212
  return (React.createElement(Box, { marginLeft: 2 },
@@ -0,0 +1,2 @@
1
+ import React from 'react';
2
+ export default function UsagePanel(): React.JSX.Element;