From b913941e4fc4c074a708cb5e6b94615ca12e7737 Mon Sep 17 00:00:00 2001 From: William Valentin Date: Thu, 5 Feb 2026 15:51:50 -0800 Subject: [PATCH] docs: add README and AGENTS.md documentation --- AGENTS.md | 87 +++++++++++++++++++++++ README.md | 205 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 292 insertions(+) create mode 100644 AGENTS.md create mode 100644 README.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..622649f --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,87 @@ +# Flynn AGENTS.md + +## Build, Lint, and Test Commands + +```bash +# Build +pnpm build # Compile TypeScript to dist/ + +# Development +pnpm dev # Run daemon with watch mode +pnpm tui # Run TUI in minimal mode (readline) +pnpm tui:fs # Run TUI in fullscreen mode (React/Ink) +pnpm tui:dev # Run TUI with watch mode + +# Run +pnpm start # Start production build + +# Testing +pnpm test # Run tests in watch mode +pnpm test:run # Run tests once (no watch) + +# Linting and Type Checking +pnpm lint # Run ESLint +pnpm typecheck # Run TypeScript compiler (no emit) +``` + +## Code Style Guidelines + +### Imports + +- Use `.js` extensions for imports (e.g., `import { readFileSync } from 'fs';`) +- Use `type` keyword for type-only imports: `import type { Config } from './schema.js';` +- Group imports: stdlib → third-party → local +- Export all public APIs from `index.ts` + +### Naming Conventions + +- **Classes/Interfaces/Types**: PascalCase (`AnthropicClient`, `NativeAgentConfig`) +- **Functions**: camelCase (`loadConfig`, `expandEnvVars`) +- **Private fields**: camelCase with underscore (`_client`, `_model`) +- **Files**: camelCase for .ts files, PascalCase for .tsx files +- **Test files**: `*.test.ts` suffix + +### TypeScript Configuration + +- `tsconfig.json` uses strict mode +- Target: ES2022 +- Module resolution: NodeNext +- Module format: NodeNext +- Enables `declaration`, `declarationMap`, and `sourceMap` for all builds + +### Error Handling + +- Throw errors with descriptive messages +- Check for undefined/null with context: `throw new Error('Environment variable ${envVar} is not set')` +- In stream handlers, wrap errors in try-catch and yield error events +- Use `instanceof Error` for error type checking: `error instanceof Error ? error.message : 'Unknown error'` +- Catch errors and convert to appropriate error types with context + +### React/Ink Patterns + +- Use `useCallback` for event handlers to prevent unnecessary re-renders +- Use `useRef` for mutable values that don't trigger re-renders +- Define interface props explicitly +- Event handlers receive `(inputChar: string, key: KeyInfo)` as arguments + +### Project Structure + +``` +src/ +├── config/ # YAML config + validation +├── models/ # Model providers + router +├── session/ # SQLite persistence +├── hooks/ # Confirmation engine +├── daemon/ # Lifecycle management +├── frontends/ # Telegram bot, TUI +└── backends/native/ # Agent implementation +``` + +## Testing + +- Use Vitest for testing +- Follow `describe`/`it` pattern +- Use `expect()` for assertions +- Test both success and failure cases +- Clean up test resources (files, dirs) in `afterEach` or `it` cleanup blocks +- Mock file system and environment variables when needed diff --git a/README.md b/README.md new file mode 100644 index 0000000..c12d7ac --- /dev/null +++ b/README.md @@ -0,0 +1,205 @@ +# Flynn + +Self-hosted personal AI assistant with Telegram and Terminal interfaces. + +## Features + +- **Multi-Frontend**: Telegram bot + Terminal UI (minimal & fullscreen modes) +- **Multi-Model**: Anthropic Claude, OpenAI, Ollama with intelligent routing +- **Model Switching**: Switch between cloud/local models on demand +- **Session Persistence**: SQLite-backed conversation history +- **Fallback Chains**: Automatic failover when primary model fails +- **Hook Engine**: Confirmation system for sensitive operations +- **Session Transfer**: Move conversations between frontends + +## Quick Start + +```bash +# Install dependencies +pnpm install + +# Copy and configure +cp config/default.yaml ~/.config/flynn/config.yaml +# Edit config with your API keys and Telegram bot token + +# Build and run +pnpm build +pnpm start +``` + +## Configuration + +Config location: `~/.config/flynn/config.yaml` (or set `FLYNN_CONFIG`) + +```yaml +telegram: + bot_token: "your-telegram-bot-token" + allowed_chat_ids: [123456789] # Your Telegram user ID + +models: + default: + provider: anthropic + model: claude-opus-4-5-20251101 + api_key: sk-ant-api03-... + local: + provider: ollama + model: qwen2.5:14b + fallback_chain: [local] + +hooks: + confirm: [shell.*, file.write] + log: [web.*, file.read] + silent: [notify] +``` + +### Model Providers + +| Provider | Config | +|----------|--------| +| Anthropic | `provider: anthropic`, `api_key` or `auth_token` | +| OpenAI | `provider: openai`, `api_key`, optional `endpoint` | +| Ollama | `provider: ollama`, `model`, optional `endpoint` | + +### Model Tiers + +Configure multiple models for different purposes: + +```yaml +models: + fast: { provider: anthropic, model: claude-sonnet-4-... } + default: { provider: anthropic, model: claude-opus-4-5-... } + complex: { provider: anthropic, model: claude-opus-4-5-... } + local: { provider: ollama, model: qwen2.5:14b } +``` + +## Telegram Commands + +| Command | Description | +|---------|-------------| +| `/start` | Initialize bot | +| `/reset` | Clear conversation history | +| `/status` | Show current model and status | +| `/local` | Switch to local model | +| `/cloud` | Switch to cloud model | +| `/model` | Show model info and options | + +## Terminal UI + +```bash +# Minimal mode (readline) +pnpm tui + +# Fullscreen mode (React/Ink) +pnpm tui:fs +``` + +### TUI Commands + +| Command | Description | +|---------|-------------| +| `/help` | Show help | +| `/reset` | Clear history | +| `/status` | Show session info | +| `/fullscreen` | Switch to fullscreen mode | +| `/transfer telegram` | Transfer session to Telegram | +| `/quit` | Exit | + +## Running as Service + +```bash +# Create systemd user service +mkdir -p ~/.config/systemd/user + +cat > ~/.config/systemd/user/flynn.service << 'EOF' +[Unit] +Description=Flynn Personal AI Assistant +After=network.target ollama.service + +[Service] +Type=simple +WorkingDirectory=/path/to/flynn +ExecStart=/usr/bin/pnpm start +Restart=on-failure +RestartSec=5 +Environment=NODE_ENV=production + +[Install] +WantedBy=default.target +EOF + +# Enable and start +systemctl --user daemon-reload +systemctl --user enable --now flynn + +# View logs +journalctl --user -u flynn -f +``` + +## Hook Engine + +Control sensitive operations with pattern matching: + +```yaml +hooks: + confirm: # Requires user approval via Telegram + - shell.* + - file.write + log: # Logs but doesn't block + - web.* + - file.read + silent: # Executes without notification + - notify +``` + +## Session Management + +- Sessions persist in `~/.local/share/flynn/sessions.db` +- Session ID format: `{frontend}:{userId}` (e.g., `telegram:123456789`) +- History survives restarts +- Transfer sessions between frontends with `/transfer` + +## Architecture + +``` +src/ +├── index.ts # Daemon entry +├── tui.ts # TUI entry +├── config/ # YAML config + validation +├── models/ # Model providers + router +├── backends/native/ # Agent implementation +├── session/ # SQLite persistence +├── hooks/ # Confirmation engine +├── daemon/ # Lifecycle management +└── frontends/ + ├── telegram/ # Telegram bot + └── tui/ # Terminal UI +``` + +## Development + +```bash +# Dev mode with watch +pnpm dev # Daemon +pnpm tui:dev # TUI + +# Type check +pnpm typecheck + +# Lint +pnpm lint + +# Test +pnpm test +``` + +## Environment Variables + +| Variable | Description | +|----------|-------------| +| `FLYNN_CONFIG` | Override config path | +| `ANTHROPIC_API_KEY` | Anthropic API key (fallback) | +| `OPENAI_API_KEY` | OpenAI API key (fallback) | + +## License + +MIT