diff --git a/AGENTS.md b/AGENTS.md index e3d81904..748ee7ab 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -76,3 +76,54 @@ When closing issues via commit: ``` 5. **Add new [Unreleased] section** at top of CHANGELOG.md for next cycle, commit it + +## coding-agent Code Map + +``` +packages/coding-agent/src/ +├── cli.ts # CLI entry point +├── main.ts # Main orchestration, mode routing +├── index.ts # Public exports + +├── cli/ # CLI-specific utilities +│ ├── args.ts # Argument parsing, help display +│ ├── file-processor.ts # @file argument processing +│ └── session-picker.ts # TUI session selector for --resume + +├── core/ # Core business logic (mode-agnostic) +│ ├── agent-session.ts # AgentSession: unified session management +│ ├── bash-executor.ts # Bash command execution +│ ├── compaction.ts # Context compaction logic +│ ├── export-html.ts # HTML export functionality +│ ├── messages.ts # Message types and transformers +│ ├── model-config.ts # Model configuration loading +│ ├── model-resolver.ts # Model resolution and scoping +│ ├── session-manager.ts # Session persistence (JSONL) +│ ├── settings-manager.ts # User settings persistence +│ ├── slash-commands.ts # Slash command loading +│ ├── system-prompt.ts # System prompt construction +│ ├── oauth/ # OAuth authentication +│ └── tools/ # Tool implementations (read, bash, edit, write, etc.) + +├── modes/ # Run mode implementations +│ ├── index.ts # Mode exports +│ ├── print-mode.ts # Non-interactive print mode +│ ├── rpc-mode.ts # RPC/JSON mode for programmatic use +│ └── interactive/ # Interactive TUI mode +│ ├── interactive-mode.ts # InteractiveMode class +│ ├── components/ # TUI components +│ └── theme/ # Theme definitions + +└── utils/ # Generic utilities + ├── changelog.ts # Changelog parsing + ├── clipboard.ts # Clipboard operations + ├── config.ts # App configuration, paths + ├── fuzzy.ts # Fuzzy matching + ├── shell.ts # Shell detection + └── tools-manager.ts # External tool management (fd, etc.) +``` + +Key abstractions: +- `AgentSession` (core/agent-session.ts): Central session management, wraps Agent with persistence, compaction, model cycling +- `InteractiveMode` (modes/interactive/interactive-mode.ts): TUI rendering and user interaction +- `runPrintMode` / `runRpcMode`: Non-interactive output modes diff --git a/packages/coding-agent/DEVELOPMENT.md b/packages/coding-agent/DEVELOPMENT.md new file mode 100644 index 00000000..b4a5d7c0 --- /dev/null +++ b/packages/coding-agent/DEVELOPMENT.md @@ -0,0 +1,223 @@ +# coding-agent Development Guide + +This document describes the architecture and development workflow for the coding-agent package. + +## Architecture Overview + +The coding-agent is structured into distinct layers: + +``` +┌─────────────────────────────────────────────────────────────┐ +│ CLI Layer │ +│ cli.ts → main.ts → cli/args.ts, cli/file-processor.ts │ +└─────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ Mode Layer │ +│ modes/interactive/ modes/print-mode.ts modes/rpc-mode.ts │ +└─────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ Core Layer │ +│ core/agent-session.ts (central abstraction) │ +│ core/session-manager.ts, core/model-config.ts, etc. │ +└─────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ External Dependencies │ +│ @mariozechner/pi-agent-core (Agent, tools) │ +│ @mariozechner/pi-ai (models, providers) │ +│ @mariozechner/pi-tui (TUI components) │ +└─────────────────────────────────────────────────────────────┘ +``` + +## Directory Structure + +``` +src/ +├── cli.ts # CLI entry point (shebang, calls main) +├── main.ts # Main orchestration, argument handling, mode routing +├── index.ts # Public API exports + +├── cli/ # CLI-specific utilities +│ ├── args.ts # parseArgs(), printHelp(), Args interface +│ ├── file-processor.ts # processFileArguments() for @file args +│ └── session-picker.ts # selectSession() TUI for --resume + +├── core/ # Core business logic (mode-agnostic) +│ ├── agent-session.ts # AgentSession class - THE central abstraction +│ ├── bash-executor.ts # executeBash() with streaming, abort +│ ├── compaction.ts # Context compaction logic +│ ├── export-html.ts # exportSession(), exportFromFile() +│ ├── messages.ts # BashExecutionMessage, messageTransformer +│ ├── model-config.ts # findModel(), getAvailableModels(), getApiKeyForModel() +│ ├── model-resolver.ts # resolveModelScope(), restoreModelFromSession() +│ ├── session-manager.ts # SessionManager class - JSONL persistence +│ ├── settings-manager.ts # SettingsManager class - user preferences +│ ├── slash-commands.ts # loadSlashCommands() from ~/.pi/agent/commands/ +│ ├── system-prompt.ts # buildSystemPrompt(), loadProjectContextFiles() +│ ├── oauth/ # OAuth authentication (Anthropic, etc.) +│ │ ├── anthropic.ts +│ │ ├── storage.ts +│ │ └── index.ts +│ └── tools/ # Tool implementations +│ ├── bash.ts, edit.ts, find.ts, grep.ts, ls.ts, read.ts, write.ts +│ ├── truncate.ts # Output truncation utilities +│ └── index.ts # Tool exports, allTools, codingTools + +├── modes/ # Run mode implementations +│ ├── index.ts # Re-exports InteractiveMode, runPrintMode, runRpcMode +│ ├── print-mode.ts # Non-interactive: process messages, print output, exit +│ ├── rpc-mode.ts # JSON-RPC mode for programmatic control +│ └── interactive/ # Interactive TUI mode +│ ├── interactive-mode.ts # InteractiveMode class +│ ├── components/ # TUI components (editor, selectors, etc.) +│ │ ├── assistant-message.ts +│ │ ├── bash-execution.ts +│ │ ├── custom-editor.ts +│ │ ├── footer.ts +│ │ ├── model-selector.ts +│ │ ├── session-selector.ts +│ │ └── ... (other selectors) +│ └── theme/ +│ ├── theme.ts # Theme loading, getEditorTheme(), etc. +│ ├── dark.json +│ ├── light.json +│ └── theme-schema.json + +└── utils/ # Generic utilities + ├── changelog.ts # parseChangelog(), getNewEntries() + ├── clipboard.ts # copyToClipboard() + ├── config.ts # APP_NAME, VERSION, paths (getAgentDir, etc.) + ├── fuzzy.ts # Fuzzy string matching + ├── shell.ts # getShellConfig() + └── tools-manager.ts # ensureTool() - download fd, etc. +``` + +## Key Abstractions + +### AgentSession (core/agent-session.ts) + +The central abstraction that wraps the low-level `Agent` with: +- Session persistence (via SessionManager) +- Settings persistence (via SettingsManager) +- Model cycling with scoped models +- Context compaction +- Bash command execution +- Message queuing + +All three modes (interactive, print, rpc) use AgentSession. + +### InteractiveMode (modes/interactive/interactive-mode.ts) + +Handles TUI rendering and user interaction: +- Subscribes to AgentSession events +- Renders messages, tool executions, streaming +- Manages editor, selectors, key handlers +- Delegates all business logic to AgentSession + +### SessionManager (core/session-manager.ts) + +Handles session persistence: +- JSONL format for append-only writes +- Session file location management +- Message loading/saving +- Model/thinking level persistence + +### SettingsManager (core/settings-manager.ts) + +Handles user preferences: +- Default model/provider +- Theme selection +- Queue mode +- Thinking block visibility + +## Development Workflow + +### Running in Development + +```bash +# From monorepo root +npx tsx packages/coding-agent/src/cli.ts + +# With arguments +npx tsx packages/coding-agent/src/cli.ts --help +npx tsx packages/coding-agent/src/cli.ts -p "Hello" +``` + +### Type Checking + +```bash +# From monorepo root +npm run check +``` + +### Building + +```bash +# Build all packages +npm run build + +# Build standalone binary +cd packages/coding-agent +npm run build:binary +``` + +## Adding New Features + +### Adding a New Slash Command + +1. If it's a UI-only command (e.g., `/theme`), add handler in `interactive-mode.ts` `setupEditorSubmitHandler()` +2. If it needs session logic, add method to `AgentSession` and call from mode + +### Adding a New Tool + +1. Create tool in `core/tools/` following existing patterns +2. Export from `core/tools/index.ts` +3. Add to `allTools` and optionally `codingTools` +4. Add description to `toolDescriptions` in `core/system-prompt.ts` + +### Adding a New Selector + +1. Create component in `modes/interactive/components/` +2. Use `showSelector()` helper in `interactive-mode.ts`: + +```typescript +private showMySelector(): void { + this.showSelector((done) => { + const selector = new MySelectorComponent( + // ... params + (result) => { + // Handle selection + done(); + this.showStatus(`Selected: ${result}`); + }, + () => { + done(); + this.ui.requestRender(); + }, + ); + return { component: selector, focus: selector.getSelectList() }; + }); +} +``` + +## Testing + +The package uses E2E tests only (no unit tests by design). Tests are in `test/`: + +```bash +# Run tests +npm test +``` + +## Code Style + +- No `any` types unless absolutely necessary +- No inline dynamic imports +- Use `showStatus()` for dim status messages +- Use `showError()` / `showWarning()` for errors/warnings +- Keep InteractiveMode focused on UI, delegate logic to AgentSession diff --git a/packages/coding-agent/README.md b/packages/coding-agent/README.md index 1f778e8b..87e32623 100644 --- a/packages/coding-agent/README.md +++ b/packages/coding-agent/README.md @@ -27,6 +27,7 @@ Works on Linux, macOS, and Windows (needs a bash shell, see [Windows Shell Confi - [To-Dos](#to-dos) - [Planning](#planning) - [Background Bash](#background-bash) +- [Development](#development) - [License](#license) - [See Also](#see-also) @@ -1415,6 +1416,10 @@ The debug log includes: - Total number of rendered lines - Each line with its index, visible width, and JSON-escaped content showing all ANSI codes +## Development + +For architecture details, code organization, and contribution guidelines, see [DEVELOPMENT.md](./DEVELOPMENT.md). + ## License MIT