claude: live-tail terminal sub-card in expanded Bash cards (T-325, UI)
Wire the detection + follower core into the Bash tool card. A Bash card with a follow intent (`tail -f …`) gains a "live tail" segment below the result: an embedded read-only TerminalView fed by FileTailFollower on the file the command follows, resolved against the open workspace. Lazy lifecycle for free: the collapser builds its children only when expanded (clide_collapser_card.dart), so _BashLiveTail starts the follower in didChangeDependencies on expand and stops it in dispose on collapse — no follower runs until the card is expanded. No resolvable file-backed source → a muted "no independent source to follow" note, never an empty terminal. The workspace root comes from kernel.project.current, so no new plumbing through the conversation widget tree. Tests: a tail Bash card surfaces the segment (+ the muted note when no project/source); an ordinary `ls` card gets no segment; the segment only builds on expand. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -818,6 +818,29 @@ void main() {
|
||||
expect(copied, contains('question text'));
|
||||
expect(copied, contains('answer text'));
|
||||
});
|
||||
|
||||
testWidgets('a tail Bash card shows a live-tail segment; no workspace source → muted note (T-325)', (tester) async {
|
||||
await pumpWith(tester, [
|
||||
AssistantToolUse(uuid: 'b1', timestamp: _t, isSidechain: false, toolUseId: 'tb', name: 'Bash', input: const {'command': 'tail -f app.log'}),
|
||||
]);
|
||||
// Collapsed by default — the segment only builds (and connects) on expand.
|
||||
expect(find.text('live tail'), findsNothing);
|
||||
await tester.tap(find.bySemanticsLabel('Bash, 1 step, collapsed'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('live tail'), findsOneWidget); // segment surfaced for a tail command
|
||||
// No project open in the fixture → no resolvable source → the muted note,
|
||||
// never a broken/empty terminal.
|
||||
expect(find.text('no independent source to follow'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('an ordinary Bash card has no live-tail segment (T-325)', (tester) async {
|
||||
await pumpWith(tester, [
|
||||
AssistantToolUse(uuid: 'b2', timestamp: _t, isSidechain: false, toolUseId: 'tb2', name: 'Bash', input: const {'command': 'ls -la'}),
|
||||
]);
|
||||
await tester.tap(find.bySemanticsLabel('Bash, 1 step, collapsed'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('live tail'), findsNothing); // no tail intent → no segment
|
||||
});
|
||||
});
|
||||
|
||||
group('ClaudeBanner', () {
|
||||
|
||||
Reference in New Issue
Block a user