show live per-member status in the team sidebar
test / unit + widget + golden + a11y (push) Failing after 31s
test / integration_test (xvfb) (push) Has been skipped
test / bundle smoke (xvfb 5s) (push) Has been skipped
test / daemon subprocess + web WASM smoke (push) Has been skipped
test / dart doc (lib API) (push) Failing after 29s
test / unit + widget + golden + a11y (push) Failing after 31s
test / integration_test (xvfb) (push) Has been skipped
test / bundle smoke (xvfb 5s) (push) Has been skipped
test / daemon subprocess + web WASM smoke (push) Has been skipped
test / dart doc (lib API) (push) Failing after 29s
The teammate status was emitted by each TranscriptPublisher's statusStream
but never reached the bus. The observer now forwards it onto a shared
member-status channel ({agentId, model, permissionMode, contextTokens});
the meta sidebar subscribes and folds each member's live permission-mode
and context-token count into its roster row. No re-tailing — reuses the
existing stream (D-75).
T-157.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
import 'package:clide/builtin/claude/src/claude_meta_sidebar.dart';
|
||||
import 'package:clide/builtin/claude/src/claude_stats.dart';
|
||||
import 'package:clide/builtin/claude/src/transcript_publisher.dart';
|
||||
import 'package:clide/builtin/claude/src/transcript_reader.dart';
|
||||
import 'package:clide/kernel/kernel.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
@@ -58,6 +60,35 @@ void main() {
|
||||
expect(find.text('No team active.'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('folds live per-member status (mode + context) into the roster row', (tester) async {
|
||||
await tester.pumpWidget(harness(f, sidebar()));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
f.services.events.emit(const TeamMemberJoined(
|
||||
team: 't',
|
||||
agentId: 'a1',
|
||||
name: 'Scout',
|
||||
agentType: 'explorer',
|
||||
paneId: '%1',
|
||||
color: 'blue',
|
||||
));
|
||||
await tester.pump();
|
||||
await tester.pump();
|
||||
|
||||
f.services.messages.publish(
|
||||
ClaudeConversation.publisher,
|
||||
ClaudeConversation.memberStatusChannel,
|
||||
ClaudeConversation.memberStatusData(
|
||||
'a1',
|
||||
const SessionStatus(model: 'claude-opus-4-7', permissionMode: 'acceptEdits', contextTokens: 21000),
|
||||
),
|
||||
);
|
||||
await tester.pump();
|
||||
await tester.pump();
|
||||
|
||||
expect(find.text('explorer · opus 4.7 · accept-edits · 21k ctx'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('degrades to a no-activity message with empty stats', (tester) async {
|
||||
await tester.pumpWidget(harness(f, sidebar()));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
@@ -79,5 +79,20 @@ void main() {
|
||||
test('teammateChannel namespaces by agentId', () {
|
||||
expect(ClaudeConversation.teammateChannel('coder@team-x'), 'conversation/coder@team-x');
|
||||
});
|
||||
|
||||
test('memberStatusData encodes agentId + present status fields (T-157)', () {
|
||||
final full = ClaudeConversation.memberStatusData(
|
||||
'coder@team-x',
|
||||
const SessionStatus(model: 'claude-opus-4-7', permissionMode: 'plan', contextTokens: 21000),
|
||||
);
|
||||
expect(full, {
|
||||
'agentId': 'coder@team-x',
|
||||
'model': 'claude-opus-4-7',
|
||||
'permissionMode': 'plan',
|
||||
'contextTokens': 21000,
|
||||
});
|
||||
// Absent fields are omitted (only agentId is always present).
|
||||
expect(ClaudeConversation.memberStatusData('a', const SessionStatus()), {'agentId': 'a'});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user