@townco/debugger 0.1.66 → 0.1.68

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.
@@ -0,0 +1,424 @@
1
+ import type { LucideIcon } from "lucide-react";
2
+ import {
3
+ CheckSquare,
4
+ Code,
5
+ Eye,
6
+ FileText,
7
+ FolderOpen,
8
+ FoldVertical,
9
+ Globe,
10
+ Image,
11
+ ListTree,
12
+ MessageSquare,
13
+ Pencil,
14
+ Search,
15
+ Terminal,
16
+ Trash,
17
+ Wrench,
18
+ } from "lucide-react";
19
+
20
+ // ============================================================================
21
+ // Types
22
+ // ============================================================================
23
+
24
+ /**
25
+ * Category of tool operation
26
+ */
27
+ export type ToolCategory =
28
+ | "file" // File system operations
29
+ | "code" // Code analysis and search
30
+ | "web" // Web/browser operations
31
+ | "ai" // AI/LLM operations
32
+ | "task" // Task management and todos
33
+ | "subagent" // Subagent/delegation
34
+ | "compaction" // Context compression
35
+ | "sandbox" // Sandbox/execution
36
+ | "other"; // Unknown/other
37
+
38
+ /**
39
+ * Metadata for a tool
40
+ */
41
+ export interface ToolMetadata {
42
+ /** Display name for the tool */
43
+ name: string;
44
+ /** Icon to use in UI */
45
+ icon: LucideIcon;
46
+ /** Category for grouping/filtering */
47
+ category: ToolCategory;
48
+ /** Optional color override (defaults to category color) */
49
+ color?: string;
50
+ /** Optional description */
51
+ description?: string;
52
+ }
53
+
54
+ /**
55
+ * Pattern matcher for dynamic tool names
56
+ */
57
+ interface ToolPattern {
58
+ /** Test function to match tool names */
59
+ test: (toolName: string) => boolean;
60
+ /** Metadata to return if matched */
61
+ metadata: Omit<ToolMetadata, "name">;
62
+ }
63
+
64
+ // ============================================================================
65
+ // Tool Registry
66
+ // ============================================================================
67
+
68
+ /**
69
+ * Registry of known tools with their metadata
70
+ * Add new tools here as exact matches
71
+ */
72
+ const KNOWN_TOOLS: Record<string, Omit<ToolMetadata, "name">> = {
73
+ // Task management
74
+ todo_write: {
75
+ icon: CheckSquare,
76
+ category: "task",
77
+ description: "Create or update todo items",
78
+ },
79
+
80
+ // Subagents
81
+ Task: {
82
+ icon: ListTree,
83
+ category: "subagent",
84
+ description: "Delegate to a subagent",
85
+ },
86
+
87
+ // Web operations
88
+ WebSearch: {
89
+ icon: Search,
90
+ category: "web",
91
+ description: "Search the web",
92
+ },
93
+ WebFetch: {
94
+ icon: Globe,
95
+ category: "web",
96
+ description: "Fetch web page content",
97
+ },
98
+
99
+ // Document operations
100
+ document_extract: {
101
+ icon: FileText,
102
+ category: "file",
103
+ description: "Extract text from documents",
104
+ },
105
+
106
+ // File operations
107
+ Read: {
108
+ icon: FileText,
109
+ category: "file",
110
+ description: "Read file contents",
111
+ },
112
+ read_file: {
113
+ icon: FileText,
114
+ category: "file",
115
+ description: "Read file contents",
116
+ },
117
+ Write: {
118
+ icon: Pencil,
119
+ category: "file",
120
+ description: "Write to a file",
121
+ },
122
+ write: {
123
+ icon: Pencil,
124
+ category: "file",
125
+ description: "Write to a file",
126
+ },
127
+ search_replace: {
128
+ icon: Pencil,
129
+ category: "file",
130
+ description: "Search and replace in files",
131
+ },
132
+ delete_file: {
133
+ icon: Trash,
134
+ category: "file",
135
+ description: "Delete a file",
136
+ },
137
+ list_dir: {
138
+ icon: FolderOpen,
139
+ category: "file",
140
+ description: "List directory contents",
141
+ },
142
+
143
+ // Code operations
144
+ Grep: {
145
+ icon: Search,
146
+ category: "code",
147
+ description: "Search code with grep",
148
+ },
149
+ grep: {
150
+ icon: Search,
151
+ category: "code",
152
+ description: "Search code with grep",
153
+ },
154
+ codebase_search: {
155
+ icon: Search,
156
+ category: "code",
157
+ description: "Semantic code search",
158
+ },
159
+ read_lints: {
160
+ icon: Code,
161
+ category: "code",
162
+ description: "Read linter errors",
163
+ },
164
+
165
+ // Terminal operations
166
+ run_terminal_cmd: {
167
+ icon: Terminal,
168
+ category: "sandbox",
169
+ description: "Run terminal command",
170
+ },
171
+
172
+ // Image generation
173
+ Sandbox_GenerateImage: {
174
+ icon: Image,
175
+ category: "sandbox",
176
+ description: "Generate an image",
177
+ },
178
+ };
179
+
180
+ /**
181
+ * Pattern matchers for dynamic tool names
182
+ * These are checked in order if no exact match is found
183
+ */
184
+ const TOOL_PATTERNS: ToolPattern[] = [
185
+ // Sandbox operations (prefix-based)
186
+ {
187
+ test: (name) => name.startsWith("Sandbox_"),
188
+ metadata: {
189
+ icon: Terminal,
190
+ category: "sandbox",
191
+ description: "Sandbox operation",
192
+ },
193
+ },
194
+
195
+ // Browser operations (prefix-based)
196
+ {
197
+ test: (name) =>
198
+ name.startsWith("Browser") ||
199
+ name.toLowerCase().startsWith("mcp_cursor-browser"),
200
+ metadata: {
201
+ icon: Globe,
202
+ category: "web",
203
+ description: "Browser operation",
204
+ },
205
+ },
206
+
207
+ // Subagent tools (pattern-based)
208
+ {
209
+ test: (name) => name.toLowerCase().includes("subagent"),
210
+ metadata: {
211
+ icon: ListTree,
212
+ category: "subagent",
213
+ description: "Subagent operation",
214
+ },
215
+ },
216
+
217
+ // File operations (keyword-based)
218
+ {
219
+ test: (name) => {
220
+ const lower = name.toLowerCase();
221
+ return lower.includes("read") || lower.includes("file");
222
+ },
223
+ metadata: {
224
+ icon: FileText,
225
+ category: "file",
226
+ },
227
+ },
228
+ {
229
+ test: (name) => {
230
+ const lower = name.toLowerCase();
231
+ return lower.includes("write") || lower.includes("edit");
232
+ },
233
+ metadata: {
234
+ icon: Pencil,
235
+ category: "file",
236
+ },
237
+ },
238
+ {
239
+ test: (name) => name.toLowerCase().includes("delete"),
240
+ metadata: {
241
+ icon: Trash,
242
+ category: "file",
243
+ },
244
+ },
245
+ {
246
+ test: (name) => {
247
+ const lower = name.toLowerCase();
248
+ return lower.includes("list") || lower.includes("dir");
249
+ },
250
+ metadata: {
251
+ icon: FolderOpen,
252
+ category: "file",
253
+ },
254
+ },
255
+
256
+ // Code operations (keyword-based)
257
+ {
258
+ test: (name) => {
259
+ const lower = name.toLowerCase();
260
+ return (
261
+ lower.includes("grep") ||
262
+ lower.includes("search") ||
263
+ lower.includes("codebase")
264
+ );
265
+ },
266
+ metadata: {
267
+ icon: Search,
268
+ category: "code",
269
+ },
270
+ },
271
+ {
272
+ test: (name) =>
273
+ name.toLowerCase().includes("terminal") ||
274
+ name.toLowerCase().includes("run"),
275
+ metadata: {
276
+ icon: Terminal,
277
+ category: "sandbox",
278
+ },
279
+ },
280
+ {
281
+ test: (name) => {
282
+ const lower = name.toLowerCase();
283
+ return lower.includes("lint") || lower.includes("analyze");
284
+ },
285
+ metadata: {
286
+ icon: Code,
287
+ category: "code",
288
+ },
289
+ },
290
+
291
+ // Web operations (keyword-based)
292
+ {
293
+ test: (name) => name.toLowerCase().includes("web"),
294
+ metadata: {
295
+ icon: Globe,
296
+ category: "web",
297
+ },
298
+ },
299
+
300
+ // AI operations (keyword-based)
301
+ {
302
+ test: (name) => {
303
+ const lower = name.toLowerCase();
304
+ return lower.includes("chat") || lower.includes("message");
305
+ },
306
+ metadata: {
307
+ icon: MessageSquare,
308
+ category: "ai",
309
+ },
310
+ },
311
+
312
+ // View operations (keyword-based)
313
+ {
314
+ test: (name) => {
315
+ const lower = name.toLowerCase();
316
+ return lower.includes("view") || lower.includes("show");
317
+ },
318
+ metadata: {
319
+ icon: Eye,
320
+ category: "file",
321
+ },
322
+ },
323
+
324
+ // Compaction operations (keyword-based)
325
+ {
326
+ test: (name) => {
327
+ const lower = name.toLowerCase();
328
+ return (
329
+ lower.includes("compact") ||
330
+ lower.includes("compression") ||
331
+ lower.includes("summarize") ||
332
+ lower.includes("summarization")
333
+ );
334
+ },
335
+ metadata: {
336
+ icon: FoldVertical,
337
+ category: "compaction",
338
+ },
339
+ },
340
+ ];
341
+
342
+ /**
343
+ * Default icons by category
344
+ */
345
+ const CATEGORY_DEFAULTS: Record<ToolCategory, LucideIcon> = {
346
+ file: FileText,
347
+ code: Code,
348
+ web: Globe,
349
+ ai: MessageSquare,
350
+ task: CheckSquare,
351
+ subagent: ListTree,
352
+ compaction: FoldVertical,
353
+ sandbox: Terminal,
354
+ other: Wrench,
355
+ };
356
+
357
+ // ============================================================================
358
+ // Public API
359
+ // ============================================================================
360
+
361
+ /**
362
+ * Get metadata for a tool by name
363
+ *
364
+ * Lookup order:
365
+ * 1. Exact match in KNOWN_TOOLS
366
+ * 2. Pattern match in TOOL_PATTERNS
367
+ * 3. Fallback to "other" category
368
+ */
369
+ export function getToolMetadata(toolName: string): ToolMetadata {
370
+ // Check exact matches first
371
+ const exactMatch = KNOWN_TOOLS[toolName];
372
+ if (exactMatch) {
373
+ return {
374
+ name: toolName,
375
+ ...exactMatch,
376
+ };
377
+ }
378
+
379
+ // Check patterns
380
+ for (const pattern of TOOL_PATTERNS) {
381
+ if (pattern.test(toolName)) {
382
+ return {
383
+ name: toolName,
384
+ ...pattern.metadata,
385
+ };
386
+ }
387
+ }
388
+
389
+ // Fallback
390
+ return {
391
+ name: toolName,
392
+ icon: CATEGORY_DEFAULTS.other,
393
+ category: "other",
394
+ description: "Unknown tool",
395
+ };
396
+ }
397
+
398
+ /**
399
+ * Get just the icon for a tool (convenience method)
400
+ */
401
+ export function getToolIcon(toolName: string): LucideIcon {
402
+ return getToolMetadata(toolName).icon;
403
+ }
404
+
405
+ /**
406
+ * Get the default icon for a category
407
+ */
408
+ export function getCategoryIcon(category: ToolCategory): LucideIcon {
409
+ return CATEGORY_DEFAULTS[category];
410
+ }
411
+
412
+ /**
413
+ * Get all registered tool names (for autocomplete, documentation, etc.)
414
+ */
415
+ export function getRegisteredTools(): string[] {
416
+ return Object.keys(KNOWN_TOOLS);
417
+ }
418
+
419
+ /**
420
+ * Check if a tool is registered
421
+ */
422
+ export function isRegisteredTool(toolName: string): boolean {
423
+ return toolName in KNOWN_TOOLS;
424
+ }