Skip to content

Conversation

@Norbert515
Copy link
Owner

Summary

  • Fixed permission-mode 'ask' bug in vide_server - sessions now correctly trigger permission-request events
  • Implemented event tracking for lastActiveAt and agentCount in vide_daemon via WebSocket monitoring
  • Added 76 unit tests for vide_daemon (previously had zero tests)
  • Added dart_test.yaml to define the integration tag

Test plan

  • dart analyze - no issues
  • vide_server tests - 172 passing
  • vide_daemon tests - 76 passing

🤖 Generated with Claude Code

…tCount

Add WebSocket client to SessionProcess that monitors the session's event
stream to populate tracking fields:

- lastActiveAt: Updated on any activity event (message, tool-use, status, etc.)
- agentCount: Incremented on agent-spawned, decremented on agent-terminated

Implementation approach:
- Lazy connection: WebSocket connects on first toSummary()/toDetails() call
- Auto-reconnect: Schedules reconnection after 5 seconds on disconnect
- Proper cleanup: Event monitoring stopped before process termination

Resolves TODOs in toSummary() and toDetails() methods.
When a session was created with permission-mode: 'ask', the permission
mode was passed to AgentNetworkManager.startNew() but never applied to
the agent configuration. The agent's config file had permissionMode:
'acceptEdits' which was used instead of the session's requested mode.

This fix applies the session-level permission mode override to the
agent configuration before creating the ClaudeClient, ensuring that
'ask' mode correctly triggers permission-request events over WebSocket.
Add unit tests for:
- Protocol messages (CreateSessionRequest, CreateSessionResponse,
  SessionSummary, ListSessionsResponse, SessionDetailsResponse,
  PersistedSessionState, DaemonState)
- Protocol events (SessionCreatedEvent, SessionStoppedEvent,
  SessionHealthEvent, DaemonStatusEvent)
- DaemonClient with mocked HTTP client (health checks, session
  CRUD operations, authentication)

Test files created:
- test/protocol/daemon_messages_test.dart (27 tests)
- test/protocol/daemon_events_test.dart (23 tests)
- test/client/daemon_client_test.dart (26 tests)

Total: 76 tests, all passing
- Add httpClient DI to DaemonClient for proper test mocking
- Extract SessionEventMonitor class for SRP compliance
- Implement exponential backoff reconnection (1s-30s) instead of fixed 5s
- Start event monitoring at spawn() time instead of lazily
- Add permission mode validation with proper Claude CLI modes
- Simplify daemon_client_test.dart by removing 160 lines of test infrastructure
- Change StreamSubscription type from List<ConnectivityResult> to single ConnectivityResult
- Update provider return types in app_providers.dart
- Fix CardTheme to CardThemeData for Flutter 3.32.4 compatibility
- Replace ProviderContainer with VideCore in vide_server.dart
- Rewrite session_routes.dart to use VideSession.events stream
- Delete 5 permission service files (~1100 lines):
  - session_permission_manager.dart
  - interactive_permission_service.dart
  - simple_permission_service.dart
  - rest_permission_service.dart
  - network_cache_manager.dart
- Add sessionLookupProvider setup in VideCore for permission callbacks
- Add askUserQuestion event type to session_dto.dart

vide_server is now a thin HTTP/WebSocket wrapper (~350 lines)
with all business logic flowing through VideSession.
…dler

Simplify late-binding permission handling by using a mutable handler
instead of a Riverpod lookup function:

- Add PermissionHandler class with setSession() for late binding
- Add permissionHandlerProvider (replaces sessionLookupProvider)
- Update ClaudeClientFactory to accept PermissionHandler
- Update VideCore to create handler and bind session after creation
- Update TUI to use PermissionHandler instead of sessionLookupProvider

This is cleaner because:
- No function indirection (lookup vs direct reference)
- Handler owns the session reference explicitly
- Simpler to understand and debug
Add debug-mode assertion to catch initialization bugs where permission
callbacks are invoked before setSession() is called. Production code
still auto-allows as fallback for safety.
Allow passing PermissionHandler directly to VideCore constructor instead
of requiring provider override. This makes the dependency explicit and
reduces Riverpod coupling for consumers.

- Add permissionHandler field to VideCoreConfig
- Add permissionHandler parameter to VideCore.fromContainer()
- Store handler in VideCore and use for all session creation
- TUI still needs provider override (uses AgentNetworkManager directly)
- Add goal, goalStream, and team getters to VideSession
- Add TaskNameChangedEvent for reactive goal updates
- Add currentSessionIdProvider for session tracking
- Migrate TUI to use VideCore.startSessionWithMessage()
- Use session.setWorktreePath() instead of direct provider access
- Fix container sharing in startSessionWithMessage for fromContainer() mode

This ensures TUI provider watchers stay in sync when using
VideCore.fromContainer() by using the shared container instead
of creating isolated containers.
Move RemoteVideSession from TUI (lib/modules/remote/) to vide_core
(packages/vide_core/lib/src/api/) to provide a canonical remote
session implementation.

This enables a two-layer composability design:
- vide_client.Session: thin WebSocket wrapper for simple consumers
- vide_core.RemoteVideSession: full VideSession interface with
  conversation state management

Changes:
- Add remote_vide_session.dart to vide_core/src/api/
- Export from vide_core.dart
- Add web_socket_channel and meta dependencies
- Update TUI imports to use vide_core.RemoteVideSession
- Delete old lib/modules/remote/remote_vide_session.dart
- Add vide_client dependency to vide_core
- Refactor RemoteVideSession to wrap vide_client.Session instead of
  reimplementing raw WebSocket handling
- New constructor: fromClientSession(vc.Session) for when client session
  is available
- Maintain pending() constructor with completePending(vc.Session) for
  optimistic navigation
- Create event adapter converting vide_client.VideEvent to vide_core
  business events
- Update TUI files (daemon_connection_service, daemon_sessions_dialog,
  session_picker_page) to use vide_client for session creation/connection
- Preserve handleWebSocketMessage test hook for backwards compatibility

Benefits:
- Single source of truth: vide_client owns wire protocol parsing
- No duplicate event hierarchies
- Cleaner composition over reimplementation
Update test helpers to include required fields expected by vide_client:
- _simulateToolResult: add tool-name field
- _simulateAgentTerminated: add terminated-by field

These fields are required by vide_client's event parser.
Change vide_core's dependencies on local packages from `any` (workspace
resolution) to explicit path dependencies. This allows external projects
that depend on vide_core via path to correctly resolve the dependencies.

The `any` version specifier relies on workspace resolution which only
works within the monorepo. External projects (like vide_minecraft)
would try to resolve vide_client from pub.dev, causing resolution
failures.
The TUI no longer has its own embedded HTTP/WebSocket server.
External clients should connect to the vide_daemon instead,
which provides a single unified interface for all remote access.

Removed:
- VideEmbeddedServer class from vide_core
- Server settings section from TUI settings dialog
- ServerIndicator component from bottom bar
- --serve mode from vide_cli_simple

This simplifies the architecture by having one system (daemon)
instead of two parallel remote access mechanisms.
Each session now has exactly one SessionBroadcaster that:
- Subscribes to VideSession.events once at session creation
- Stores events centrally with sequence numbers
- Broadcasts to all connected WebSocket clients

This fixes the duplicate events bug where multiple WebSocket clients
connecting to the same session would receive duplicated content.

Also includes:
- Daemon spawn config for compiled binaries
- Remote session history consolidation for streaming messages
- Optimistic message deduplication
- Initial status events for agent UI reactivity
- Use videCore.resumeSession() instead of legacy manager.resume()
- Set currentSessionIdProvider directly in NetworkExecutionPage.push()
- Remove TODO and legacy sync in currentSessionIdProvider

The TUI now uses VideCore as the single interface for session management.
The pending conversation from optimistic UI was not being migrated to
the real main agent ID because completePending() tried to migrate before
the ConnectedEvent had set the real agent ID. Now we store the pending
conversation and migrate it in _handleConnected() after the real agent
ID is known.

Also removes debug print statements from history handling.
- Delete unused StreamingDeltaHandler and its tests (218+443 lines)
- Remove /test-ws echo endpoint from server_main (dev scaffolding)
Events emitted during VideSession initialization (StatusEvent, initial
MessageEvent) weren't being captured by _BufferedEventStream because
broadcast StreamControllers deliver events asynchronously by default.
By the time the listener was added, the events had already been dropped.

Using sync: true ensures events are delivered synchronously to listeners,
allowing the buffer to capture early events for replay to late subscribers.
BREAKING CHANGE: permissionHandler is now required on VideCoreConfig

Previously, permissionHandler was optional and when not provided, all
tool permissions were auto-allowed. This was a security vulnerability.

Changes:
- Make permissionHandler required in VideCoreConfig
- Make permissionHandler required in VideCore.fromContainer()
- permissionHandlerProvider now throws StateError if not overridden
- Updated all callers (vide_server, vide_cli_simple, examples, TUI)
- Updated initialClaudeClientProvider to pass permission handler
- Updated README documentation with correct examples
- Fix missing initial message by processing all new messages in
  _handleConversation instead of only the latest
- Fix HistoryEvent type casting by parsing raw JSON maps with
  VideEvent.fromJson instead of direct cast
- Fix navigating to previous sessions by adding
  connectToExistingSession to SessionRepository
- Fix duplicate user messages with content-based deduplication
- Fix model initialization by setting model on AgentConfiguration
  before client creation
- Fix resume_session_test by adding missing permissionHandler override
- Update mobile UI theme and styling
@Norbert515 Norbert515 merged commit f6f21f0 into main Feb 3, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant