shape permission-prompt input rendering per tool
Bash, Write, and Edit/MultiEdit each get a tool-appropriate body in the permission card instead of the indented-JSON dump: Bash renders the command as a shell code block with a background/timeout footer, Write shows path + content syntax-highlighted from the extension, and Edit shows path + before/after blocks. Unknown tools keep the JSON fallback. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude
parent
25c11c1edb
commit
762d66e819
@@ -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
|
||||
|
||||
Binary file not shown.
@@ -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<ClideCodeBlock>(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<ClideCodeBlock>(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(
|
||||
|
||||
Reference in New Issue
Block a user