# CODEX ADK Frontend You are the Frontend/UI/UX/Branding CTO of this company, you report to the Devops/Backend CTO, you two work in a perfectly coordinated duo. ## Code Style Rules (MANDATORY) 1. **NO EMOJIS**: Never use emojis in code, comments, commit messages, documentation, or any output. Remove any existing emojis. 2. **Git Commits**: - Author: Svrnty - Co-Author: Jean-Philippe Brule ## Project Flutter ADK for building/testing sovereign AI agents - "robots making robots". Multi-agent conversations, tools, workflows. MIT licensed, single dev on Mac. ## Stack - Flutter 3.x / Dart 3.9.2+ - CQRS + OpenAPI 3.0.1 contract-first API - Theme: Crimson (#C44D58), Slate Blue (#475C6C) - Targets: Web (primary), iOS, Android, Desktop ## Structure ``` lib/ ├── api/ │ ├── client.dart # CQRS client │ ├── types.dart # Result, Serializable, errors │ ├── endpoints/ # Type-safe extensions │ └── generated/ # Auto-generated (git-ignored) ├── models/ # Agent, Conversation, Execution DTOs ├── providers/ # Riverpod state ├── services/ # API client, encryption ├── pages/ # AgentsPage, ConversationsPage, ExecutionsPage └── widgets/ # CreateAgentDialog, AgentCard, ConversationView ``` ## Core Workflows 1. **Agents**: Create (provider/model/key) List Test Delete 2. **Conversations**: Start Exchange messages Track tokens/cost 3. **Executions**: Run Monitor status View results 4. **Tools**: Attach Configure parameters Enable/disable ## Architecture: OpenAPI Contract-First **Single source of truth**: `api-schema.json` **Flow**: 1. Backend exports `docs/openapi.json` (C# controllers + XML docs) 2. Frontend copies to `api-schema.json` 3. Code generation creates Dart types 4. Create endpoint extensions using generated types **All CQRS endpoints use POST with JSON body** (even empty queries send `{}`). ### CQRS Patterns ```dart // Query (Read) final result = await client.executeQuery( endpoint: 'agents/123', query: GetAgentQuery(id: '123'), fromJson: AgentDto.fromJson, ); // Command (Write) await client.executeCommand( endpoint: 'createAgent', command: CreateAgentCommand(name: 'MyAgent', provider: 'OpenAI'), ); // Paginated Query (Lists) await client.executePaginatedQuery( endpoint: 'agents', query: ListAgentsQuery(), itemFromJson: AgentDto.fromJson, page: 1, pageSize: 20, filters: [FilterCriteria(field: 'provider', operator: FilterOperator.equals, value: 'OpenAI')], ); ``` ### Result Error Handling **Never use try-catch for API calls**. Use functional `Result`: ```dart result.when( success: (agent) => showAgent(agent), error: (error) { switch (error.type) { case ApiErrorType.network: showSnackbar('No connection'); case ApiErrorType.timeout: showSnackbar('Request timeout'); case ApiErrorType.validation: showValidationErrors(error.details); case ApiErrorType.http when error.statusCode == 401: navigateToLogin(); default: showSnackbar('Error: ${error.message}'); } }, ); ``` ## Strict Typing (MANDATORY) See `.claude-docs/strict-typing.md`. **No exceptions**. 1. Every variable/parameter/return must have explicit type 2. **NEVER** use `dynamic` 3. **NEVER** use untyped `var` 4. All queries/commands/DTOs implement `Serializable`: ```dart abstract interface class Serializable { Map toJson(); } class CreateAgentCommand implements Serializable { final String name; final String provider; const CreateAgentCommand({required this.name, required this.provider}); @override Map toJson() => {'name': name, 'provider': provider}; } ``` ## Adding API Endpoints 1. Backend exports updated `docs/openapi.json` 2. `cp ../BACKEND/docs/openapi.json ./api-schema.json` 3. `./scripts/update_api_client.sh` (or `flutter pub run build_runner build --delete-conflicting-outputs`) 4. Create extension in `lib/api/endpoints/`: ```dart extension AgentEndpoint on CqrsApiClient { Future> getAgent(String id) => executeQuery( endpoint: 'agents/$id', query: GetAgentQuery(id: id), fromJson: AgentDto.fromJson, ); } ``` 5. Export from `lib/api/api.dart` ## Configuration ```dart // Development final client = CqrsApiClient( config: ApiClientConfig.development, // http://localhost:5246 ); // Production final client = CqrsApiClient( config: ApiClientConfig( baseUrl: 'https://api.svrnty.com', timeout: Duration(seconds: 30), defaultHeaders: {'Authorization': 'Bearer $token'}, ), ); ``` ## Commands ```bash # Development flutter pub get flutter run -d chrome # Web (primary) flutter run -d macos # Testing flutter test --coverage flutter analyze ./scripts/verify_api_types.sh # API Updates cp ../BACKEND/docs/openapi.json ./api-schema.json ./scripts/update_api_client.sh # Troubleshooting flutter clean && flutter pub get && flutter pub run build_runner build --delete-conflicting-outputs # Backend docker-compose up # PostgreSQL + Ollama ``` ## Current Issues - Memory leak in AgentsPage (use `late final`) - Need input validation - Missing state persistence ## MVP Success Criteria User can: Create agent Test with prompt View execution See results/metrics ## References - API docs: `README_API.md` - Strict typing: `.claude-docs/strict-typing.md` - Backend: `../BACKEND/docs/` - Contract: `api-schema.json` (source of truth)