@townco/debugger 0.1.67 → 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.
- package/package.json +3 -3
- package/src/App.tsx +9 -2
- package/src/components/ConversationPanel.tsx +392 -0
- package/src/components/DebuggerHeader.tsx +1 -1
- package/src/components/DiagnosticDetailsPanel.tsx +1095 -0
- package/src/components/DiagnosticPanel.tsx +111 -0
- package/src/components/NavBar.tsx +130 -0
- package/src/components/SpanDetailsPanel.tsx +2 -2
- package/src/components/SpanIcon.tsx +75 -24
- package/src/components/SpanTimeline.tsx +2 -3
- package/src/components/SpansLogsList.tsx +477 -0
- package/src/components/UnifiedTimeline.tsx +1 -2
- package/src/components/ViewControlBar.tsx +79 -0
- package/src/lib/segmentation.ts +391 -0
- package/src/lib/toolRegistry.ts +424 -0
- package/src/pages/SessionLogsView.tsx +585 -0
- package/src/pages/SessionView.tsx +24 -13
|
@@ -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
|
+
}
|