docs: add README and AGENTS.md documentation

This commit is contained in:
William Valentin
2026-02-05 15:51:50 -08:00
parent d2a597d49d
commit b913941e4f
2 changed files with 292 additions and 0 deletions
+87
View File
@@ -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
+205
View File
@@ -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