Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .opencode/opencode.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"dart": {
"type": "local",
"command": ["dart", "mcp-server"]
}
}
}
115 changes: 115 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# FLUTTER AGENT PANEL - PROJECT KNOWLEDGE BASE

**Generated:** 2026-01-08
**Commit:** b8ef0c5
**Branch:** main

## OVERVIEW
Cross-platform desktop terminal aggregator with AI agent integration. Built with Flutter + shadcn_ui, using BLoC/HydratedBloc for state persistence.

## STRUCTURE
```
flutter_agent_panel/
β”œβ”€β”€ lib/
β”‚ β”œβ”€β”€ main.dart # Entry: error handling, HydratedStorage init
β”‚ β”œβ”€β”€ app.dart # Root widget: MultiBlocProvider, theming
β”‚ β”œβ”€β”€ core/ # Cross-cutting: services, router, l10n, extensions
β”‚ β”œβ”€β”€ features/ # Feature modules (BLoC pattern)
β”‚ β”‚ β”œβ”€β”€ home/ # App shell layout
β”‚ β”‚ β”œβ”€β”€ info/ # About/Help dialogs
β”‚ β”‚ β”œβ”€β”€ settings/ # App configuration (879-line dialog)
β”‚ β”‚ β”œβ”€β”€ terminal/ # PTY management, themes
β”‚ β”‚ └── workspace/ # Multi-workspace organization
β”‚ └── shared/ # Utils, constants, common widgets
β”œβ”€β”€ packages/
β”‚ β”œβ”€β”€ flutter_pty/ # FFI PTY bindings (ConPTY/POSIX)
β”‚ └── xterm/ # Terminal emulator core (60fps render)
└── assets/ # Images, agent logos
```

## WHERE TO LOOK

| Task | Location | Notes |
|------|----------|-------|
| Add new feature | `lib/features/{name}/` | Create bloc/, models/, views/, widgets/ |
| Modify theming | `lib/app.dart` | ShadThemeData, colorScheme switching |
| Add localization | `lib/core/l10n/` | ARB files, regenerate with `flutter gen-l10n` |
| Configure routing | `lib/core/router/app_router.dart` | AutoRoute, regenerate with `lean_builder` |
| Add service | `lib/core/services/` | Singleton pattern, init in main.dart |
| Terminal rendering | `packages/xterm/lib/src/ui/` | Custom RenderBox, pixel-aligned painting |
| PTY native code | `packages/flutter_pty/src/` | C files per platform |

## CONVENTIONS

### State Management
- **HydratedBloc** for persistent state (workspace, settings)
- **Regular Bloc** for ephemeral state (terminal instances)
- Event/State in `part` files: `{name}_event.dart`, `{name}_state.dart`
- Always use `.copyWith()` for immutable updates

### UI Patterns
- **shadcn_ui** components: ShadDialog, ShadSelect, ShadInput, ShadTooltip
- **Context extensions**: `context.theme`, `context.t` (localization)
- **LucideIcons** throughout
- **Gap** widgets for spacing (not SizedBox)

### Code Style
- Single quotes for strings
- Trailing commas required
- Relative imports within lib/
- `@pragma('vm:prefer-inline')` on hot paths (xterm painter)

## ANTI-PATTERNS (THIS PROJECT)

| Forbidden | Reason |
|-----------|--------|
| Direct list mutation | Use `.copyWith()` or create new list |
| Heavy logic in `build()` | Move to Bloc or extract methods |
| Inline sorting | Delegate to Bloc events |
| Hardcoded strings | Use `context.t` localized strings |
| Manual mock edits | `*.mocks.dart` are generated |
| `flutter_pty_bindings_generated.dart` edits | Auto-generated by ffigen |
| Sub-pixel offsets in painter | Use `roundToDouble()` for crispness |
| Blocking PTY calls on main isolate | Use dedicated isolates |

## COMMANDS
```bash
# Development
flutter pub get
dart run lean_builder build # Generate routes
flutter gen-l10n # Generate localizations
flutter run -d windows # Run on Windows

# Packages (run from package dir)
flutter pub run ffigen --config ffigen.yaml # Regenerate PTY bindings

# Build
flutter build windows
flutter build macos
flutter build linux
```

## NOTES

### Desktop-Only
No Android/iOS directories - configured for Windows, macOS, Linux only.

### Monorepo Structure
Uses Flutter workspace with local packages:
- `packages/xterm` - forked/customized terminal emulator
- `packages/flutter_pty` - native PTY bindings

### Large File Hotspots
- `settings_dialog.dart` (879 lines) - Tab-based settings UI
- `workspace_drawer.dart` (541 lines) - Drag-drop with pin constraints
- `terminal_bloc.dart` (434 lines) - Cross-platform shell handling

### Platform-Specific Shell Logic
Terminal creation handles: PowerShell, pwsh, cmd, WSL, bash, zsh. See `TerminalServiceImpl` and `TerminalBloc._createTerminalNode()`.

### Inter-Feature Dependencies
```
workspace β†’ terminal (TerminalConfig model)
settings β†’ terminal (font/theme models)
terminal β†’ flutter_pty, xterm packages
```
73 changes: 73 additions & 0 deletions lib/core/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# lib/core - AGENT GUIDE

## OVERVIEW
Cross-cutting concerns: services, routing, localization, extensions.

## STRUCTURE
```
core/
β”œβ”€β”€ services/
β”‚ β”œβ”€β”€ terminal_service.dart # PTY startup abstraction
β”‚ β”œβ”€β”€ app_logger.dart # Singleton Logger wrapper
β”‚ β”œβ”€β”€ crash_log_service.dart # Error persistence to disk
β”‚ β”œβ”€β”€ user_config_service.dart # Config directory paths
β”‚ β”œβ”€β”€ app_version_service.dart # Version check + updates
β”‚ └── app_bloc_observer.dart # BLoC event/transition logging
β”œβ”€β”€ router/
β”‚ β”œβ”€β”€ app_router.dart # AutoRoute configuration
β”‚ └── app_router.gr.dart # GENERATED - do not edit
β”œβ”€β”€ l10n/
β”‚ β”œβ”€β”€ app_localizations.dart # GENERATED base class
β”‚ β”œβ”€β”€ app_localizations_en.dart # GENERATED
β”‚ └── app_localizations_zh.dart # GENERATED
β”œβ”€β”€ extensions/
β”‚ └── context_extension.dart # context.theme, context.t
β”œβ”€β”€ constants/
β”‚ └── assets.dart # Asset path constants
└── types/
└── typedefs.dart # Callback type definitions
```

## WHERE TO LOOK

| Task | File | Notes |
|------|------|-------|
| Add new service | `services/` | Singleton pattern, init in main.dart |
| Add route | `router/app_router.dart` | Run `dart run lean_builder build` |
| Add translation | `assets/l10n/*.arb` | Run `flutter gen-l10n` |
| Add extension | `extensions/context_extension.dart` | On BuildContext |

## CONVENTIONS

### Services
```dart
// Singleton pattern used throughout
class MyService {
MyService._();
static final MyService instance = MyService._();

Future<void> init() async { ... }
}
```

### Context Extensions
```dart
// Access anywhere in widget tree
context.theme // ShadThemeData
context.t // AppLocalizations
context.colorScheme
context.textTheme
```

### Generated Files (DO NOT EDIT)
- `app_router.gr.dart` - regenerate with `lean_builder`
- `app_localizations*.dart` - regenerate with `flutter gen-l10n`

## ANTI-PATTERNS

| Forbidden | Reason |
|-----------|--------|
| Edit `*.gr.dart` | Auto-generated by lean_builder |
| Edit `app_localizations*.dart` | Auto-generated by flutter gen-l10n |
| Service without singleton | Inconsistent state across app |
| Direct Logger() usage | Use AppLogger.instance.logger |
66 changes: 66 additions & 0 deletions lib/features/settings/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# lib/features/settings - AGENT GUIDE

## OVERVIEW
App configuration management: themes, fonts, shells, agents, localization.

## STRUCTURE
```
settings/
β”œβ”€β”€ bloc/
β”‚ β”œβ”€β”€ settings_bloc.dart # HydratedBloc (persistent)
β”‚ β”œβ”€β”€ settings_event.dart # 15+ event types
β”‚ └── settings_state.dart # AppSettings wrapper
β”œβ”€β”€ models/
β”‚ β”œβ”€β”€ app_settings.dart # Main config model (JSON serializable)
β”‚ β”œβ”€β”€ agent_config.dart # AI agent definitions
β”‚ β”œβ”€β”€ custom_shell_config.dart
β”‚ β”œβ”€β”€ terminal_font_settings.dart
β”‚ β”œβ”€β”€ app_theme.dart # Light/Dark enum
β”‚ └── shell_type.dart # PowerShell/Bash/WSL/Custom
β”œβ”€β”€ views/
β”‚ └── settings_dialog.dart # 879-line tab dialog (COMPLEXITY HOTSPOT)
└── widgets/
β”œβ”€β”€ agents_content.dart # Agent management + installation
β”œβ”€β”€ appearance_settings_content.dart
β”œβ”€β”€ general_settings_content.dart
β”œβ”€β”€ custom_shells_content.dart
β”œβ”€β”€ update_settings_content.dart
β”œβ”€β”€ agent_dialog.dart # Add/edit agent
β”œβ”€β”€ shell_dialog.dart # Add/edit custom shell
└── settings_section.dart # Reusable layout wrapper
```

## WHERE TO LOOK

| Task | File | Notes |
|------|------|-------|
| Add new setting | `models/app_settings.dart` | Add field + copyWith + JSON |
| Add settings tab | `views/settings_dialog.dart` | `_buildContentForIndex()` switch |
| New agent preset | `models/app_settings.dart` | `getDefaultAgents()` static |
| Persist new field | `bloc/settings_bloc.dart` | Add event handler + fromJson/toJson |

## CONVENTIONS

- **Persistence**: HydratedBloc auto-saves to `storage/` directory
- **Clear nullable fields**: Use `clearX: true` pattern in copyWith
- **Tab content**: Each tab is a separate `*_content.dart` widget
- **Dialogs**: ShadDialog with ShadInput/ShadSelect components
- **Validation**: Inline in dialog widgets before emitting events

## ANTI-PATTERNS

| Forbidden | Do Instead |
|-----------|------------|
| Add logic to settings_dialog.dart | Create new widget in widgets/ |
| Direct AppSettings mutation | Emit SettingsEvent through Bloc |
| Hardcode agent commands | Use AgentConfig model with env vars |

## COMPLEXITY NOTES

`settings_dialog.dart` is 879 lines due to 6 tab sections. Each section handles:
- Async font/theme loading
- File picker for custom themes
- Agent installation with toast feedback
- JSON validation for custom terminal themes

Consider splitting if adding more tabs.
72 changes: 72 additions & 0 deletions lib/features/terminal/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# lib/features/terminal - AGENT GUIDE

## OVERVIEW
PTY lifecycle management with cross-platform shell support and terminal theming.

## STRUCTURE
```
terminal/
β”œβ”€β”€ bloc/
β”‚ β”œβ”€β”€ terminal_bloc.dart # PTY creation, shell resolution (434 lines)
β”‚ β”œβ”€β”€ terminal_event.dart # Create/Kill/Restart/Resize events
β”‚ └── terminal_state.dart # TerminalNode map management
β”œβ”€β”€ models/
β”‚ β”œβ”€β”€ terminal_node.dart # PTY + Terminal + Controller bundle
β”‚ β”œβ”€β”€ terminal_config.dart # Shell type, working dir, env vars
β”‚ β”œβ”€β”€ terminal_theme_data.dart
β”‚ └── built_in_themes.dart # 20+ predefined color schemes
β”œβ”€β”€ services/
β”‚ β”œβ”€β”€ isolate_pty.dart # Background PTY I/O handling
β”‚ └── terminal_theme_service.dart # Theme JSON parsing
β”œβ”€β”€ views/
β”‚ β”œβ”€β”€ terminal_view.dart # BlocBuilder + TerminalComponent
β”‚ └── terminal_component.dart # xterm TerminalView wrapper
└── widgets/
β”œβ”€β”€ terminal_search_bar.dart # Regex search with navigation
β”œβ”€β”€ activity_indicator.dart # Output activity pulse
└── glowing_icon.dart # Agent status indicator
```

## WHERE TO LOOK

| Task | File | Notes |
|------|------|-------|
| Add shell type | `terminal_bloc.dart` | `_createTerminalNode()` switch |
| Custom theme | `terminal_theme_service.dart` | JSON parsing logic |
| PTY resize | `terminal_bloc.dart` | `_onResizeTerminal()` |
| Search feature | `widgets/terminal_search_bar.dart` | TerminalSearchController |

## CONVENTIONS

- **TerminalNode**: Bundles Pty + Terminal + TerminalController
- **Shell resolution**: Try pwsh β†’ powershell β†’ bash fallback
- **Environment**: Always set `TERM=xterm-256color`, `LANG=en_US.UTF-8`
- **Isolates**: PTY output streams on dedicated isolates

## PLATFORM-SPECIFIC LOGIC

```dart
// Windows shells
'powershell.exe' β†’ ['-NoLogo', '-ExecutionPolicy', 'Bypass']
'pwsh.exe' β†’ ['-NoLogo', '-ExecutionPolicy', 'Bypass']
'cmd.exe' β†’ []
'wsl.exe' β†’ ['--', 'bash', '-l']

// Unix shells
'/bin/bash' β†’ ['-l']
'/bin/zsh' β†’ ['-l']
```

## ANTI-PATTERNS

| Forbidden | Reason |
|-----------|--------|
| PTY calls on main isolate | UI jank - use IsolatePty |
| Direct Terminal state access | Use TerminalController |
| Hardcoded theme colors | Use TerminalThemeData model |

## INTER-FEATURE DEPENDENCIES

- **Imports from settings**: `TerminalFontSettings`, `AppSettings.terminalThemeName`
- **Used by workspace**: `TerminalConfig` stored in Workspace model
- **Uses packages**: `flutter_pty` (PTY), `xterm` (rendering)
6 changes: 6 additions & 0 deletions lib/features/terminal/bloc/terminal_bloc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,12 @@ class TerminalBloc extends Bloc<TerminalEvent, TerminalState> {
pty.write(const Utf8Encoder().convert(data));
};

// Setup Terminal -> PTY (Resize)
// This is called by xterm's RenderTerminal when autoResize is enabled
terminal.onResize = (width, height, pixelWidth, pixelHeight) {
node.resize(width, height);
};

return node;
}

Expand Down
Loading