diff --git a/CHANGELOG.md b/CHANGELOG.md index a6abd875..6617bf41 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,11 @@ heading, and (b) bumping `pubspec.yaml` `version:` in the same commit. ### Changed +- Permission prompt cards render the tool input in the shape that fits the + tool โ€” Bash shows the command as a shell code block (with a footer for + `run_in_background` / `timeout`), Write shows the path plus the content + highlighted from its extension, Edit shows the path plus before/after + blocks. Unknown tools fall back to the indented-JSON dump. - Claude meta sidebar is now tabbed โ€” Activity / Team / Config (T-182). Activity shows usage stats plus the primary session's live runtime; Team holds the roster and auto-fronts when a team spawns; Config shows the diff --git a/lib/builtin/claude/src/prompt_card.dart b/lib/builtin/claude/src/prompt_card.dart index ade3db72..53078c51 100644 Binary files a/lib/builtin/claude/src/prompt_card.dart and b/lib/builtin/claude/src/prompt_card.dart differ diff --git a/test/builtin/claude/prompt_card_test.dart b/test/builtin/claude/prompt_card_test.dart index 15cc0c26..f911c915 100644 --- a/test/builtin/claude/prompt_card_test.dart +++ b/test/builtin/claude/prompt_card_test.dart @@ -101,6 +101,52 @@ void main() { expect(find.byType(ClideCodeBlock), findsOneWidget); }); + testWidgets('permission card: Bash renders the command as a shell code block, not JSON', (tester) async { + const prompt = ToolPrompt( + promptId: 'req-b', + toolName: 'Bash', + displayName: 'Bash', + description: 'Read IDE lock files', + input: {'command': 'cat ~/.claude/ide/97632.lock', 'description': 'Read IDE lock files'}, + ); + await tester.pumpWidget(harness(f, ToolPromptCard(prompt: prompt, onResolve: (_, __) {}))); + await tester.pump(); + + final block = tester.widget(find.byType(ClideCodeBlock)); + expect(block.language, 'bash'); + expect(block.source, 'cat ~/.claude/ide/97632.lock'); + // The raw `description` key shouldn't bleed into the body โ€” it's already + // shown above as the prompt's description line. + expect(find.textContaining('"description"'), findsNothing); + }); + + testWidgets('permission card: Bash shows background/timeout footer when set', (tester) async { + const prompt = ToolPrompt( + promptId: 'req-b2', + toolName: 'Bash', + displayName: 'Bash', + description: 'long task', + input: {'command': 'sleep 30', 'run_in_background': true, 'timeout': 60000}, + ); + await tester.pumpWidget(harness(f, ToolPromptCard(prompt: prompt, onResolve: (_, __) {}))); + await tester.pump(); + expect(find.text('background ยท timeout 60000ms'), findsOneWidget); + }); + + testWidgets('permission card: unknown tool falls back to JSON', (tester) async { + const prompt = ToolPrompt( + promptId: 'req-x', + toolName: 'NovelTool', + displayName: 'NovelTool', + input: {'foo': 'bar'}, + ); + await tester.pumpWidget(harness(f, ToolPromptCard(prompt: prompt, onResolve: (_, __) {}))); + await tester.pump(); + final block = tester.widget(find.byType(ClideCodeBlock)); + expect(block.language, 'json'); + expect(block.source, contains('"foo"')); + }); + testWidgets('permission card: Deny returns DenyTool with a message', (tester) async { ToolDecision? decision; await tester.pumpWidget(harness(