From 33f6f142bc1f0ebc6a455937b0f56721ee982250 Mon Sep 17 00:00:00 2001 From: William Valentin Date: Sat, 7 Feb 2026 15:45:41 -0800 Subject: [PATCH] docs: add file.patch and Gmail Pub/Sub watcher documentation - README: features list, Gmail config section with field reference and template variables, hook examples, architecture tree, CLI description - CHANGELOG: new Added entries for both features - SOUL.md: file.patch in capabilities list - config/default.yaml: file.patch in confirm hooks, commented-out automation section with cron, webhooks, gmail, heartbeat examples --- CHANGELOG.md | 8 ++++++ README.md | 65 ++++++++++++++++++++++++++++++++++++++++++--- SOUL.md | 1 + config/default.yaml | 42 +++++++++++++++++++++++++++++ 4 files changed, 112 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d176b31..458b114 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,14 @@ All notable changes to Flynn are documented in this file. ### Added +- **Agent Tool: file.patch** -- Multi-file, multi-hunk structured patch tool. Apply + line-based replacements, insertions, and deletions across multiple files in a single + tool call. Hunks are applied bottom-up to preserve line numbers. 10 tests. +- **Gmail Pub/Sub Watcher** -- Automation source monitoring Gmail via Google Cloud + Pub/Sub push notifications with polling fallback. OAuth2 auth, configurable watch + labels, template rendering with email metadata placeholders (`{{from}}`, `{{subject}}`, + `{{snippet}}`, `{{date}}`, `{{id}}`, `{{labels}}`). Wired into daemon lifecycle and + gateway (`POST /gmail/push` endpoint). 16 tests. - **Inbound Webhooks** -- HTTP endpoints (`POST /webhooks/:name`) that trigger agent processing. Config-driven with per-webhook HMAC signature verification, message template rendering (`{{body}}`, `{{json.field}}`), and output channel routing. diff --git a/README.md b/README.md index b600cef..b54ea52 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Self-hosted personal AI assistant with Telegram and Terminal interfaces. - **Session Persistence**: SQLite-backed conversation history - **Fallback Chains**: Automatic failover when primary model fails - **Hook Engine**: Confirmation system for sensitive operations -- **Tool Framework**: Shell, file, web-fetch, web-search, browser control, image analysis, media send +- **Tool Framework**: Shell, file, file patch, web-fetch, web-search, browser control, image analysis, media send - **Docker Sandboxing**: Per-session container isolation for tool execution - **Multi-Agent Routing**: Config-driven agent selection per sender/channel with tool profiles - **Media Pipeline**: Image analysis, outbound attachments, audio transcription across all channels @@ -21,6 +21,7 @@ Self-hosted personal AI assistant with Telegram and Terminal interfaces. - **Cron Scheduling**: Automated messages on cron schedules with output routing - **Inbound Webhooks**: HTTP endpoints that trigger agent processing with HMAC auth and template rendering - **Heartbeat Monitor**: Periodic health checks (gateway, model, channels, memory, disk) with failure notifications +- **Gmail Pub/Sub Watcher**: Monitor Gmail inbox via Google Cloud Pub/Sub push notifications with polling fallback - **Vector Memory Search**: Hybrid keyword + semantic search with embeddings (OpenAI, Gemini, Ollama, llama.cpp) - **Docker Deployment**: Multi-stage Dockerfile and docker-compose.yml for production containers - **Health Diagnostics**: `flynn doctor` validates config, connectivity, and system state @@ -51,7 +52,7 @@ Flynn provides a full CLI via the `flynn` binary (or `npx tsx src/cli/index.ts` | Command | Description | |---------|-------------| -| `flynn start` | Start the Flynn daemon (Telegram, WebChat, cron) | +| `flynn start` | Start the Flynn daemon (Telegram, WebChat, cron, Gmail watcher) | | `flynn tui` | Launch the interactive terminal UI | | `flynn send ` | Send a one-shot message and print the response | | `flynn sessions` | List active sessions | @@ -97,7 +98,7 @@ models: fallback_chain: [local] hooks: - confirm: [shell.*, file.write] + confirm: [shell.*, file.write, file.patch] log: [web.*, file.read] silent: [notify] ``` @@ -213,6 +214,7 @@ hooks: confirm: # Requires user approval via Telegram - shell.* - file.write + - file.patch log: # Logs but doesn't block - web.* - file.read @@ -339,6 +341,61 @@ The monitor sends a notification when failures reach the configured threshold an | `failure_threshold` | no | Consecutive failures before notifying (default: `2`) | | `disk_threshold_mb` | no | Disk space warning threshold in MB (default: `100`) | +## Gmail Pub/Sub Watcher + +Monitor a Gmail inbox via Google Cloud Pub/Sub push notifications. New emails trigger the agent pipeline and route responses to a configured output channel. Falls back to polling when push notifications are unavailable. + +### Prerequisites + +1. Create a Google Cloud project with the Gmail API and Pub/Sub API enabled +2. Create OAuth2 credentials (Desktop application type) and download the JSON file +3. Create a Pub/Sub topic (e.g. `projects/your-project/topics/gmail-push`) +4. Run `flynn gmail-auth` to complete the OAuth2 flow and store the refresh token + +### Configuration + +```yaml +automation: + gmail: + enabled: true + credentials_file: ~/.config/flynn/gmail-credentials.json + token_file: ~/.config/flynn/gmail-token.json # Default location + watch_labels: [INBOX] # Labels to watch + poll_interval: "60s" # Polling fallback interval + message: "New email from {{from}}: {{subject}}\n\n{{snippet}}" + output: + channel: telegram + peer: "123456789" +``` + +Push notifications arrive at `POST /gmail/push` on the gateway HTTP server (bypasses gateway auth). + +### Gmail Config Fields + +| Field | Required | Description | +|-------|----------|-------------| +| `enabled` | no | Enable the Gmail watcher (default: `false`) | +| `credentials_file` | yes | Path to Google OAuth2 credentials JSON | +| `token_file` | no | Path to stored OAuth2 refresh token (default: `~/.config/flynn/gmail-token.json`) | +| `watch_labels` | no | Gmail labels to watch (default: `[INBOX]`) | +| `poll_interval` | no | Polling fallback interval: `60s`, `5m` (default: `60s`) | +| `history_start` | no | ISO date string — only process emails received after this date | +| `message` | no | Template for the agent message (default: `New email from {{from}}: {{subject}}\n\n{{snippet}}`) | +| `output.channel` | yes | Channel name to route the response (e.g. `telegram`) | +| `output.peer` | yes | Peer/chat ID on the output channel | + +### Template Variables + +| Variable | Description | +|----------|-------------| +| `{{from}}` | Sender address | +| `{{to}}` | Recipient address | +| `{{subject}}` | Email subject line | +| `{{snippet}}` | Gmail-provided message snippet | +| `{{date}}` | Email date | +| `{{id}}` | Gmail message ID | +| `{{labels}}` | Comma-separated label names | + ## Vector Memory Search The memory system supports hybrid search combining keyword matching with semantic vector similarity. When embeddings are enabled, `memory.search` uses both approaches and merges results with configurable weighting. @@ -512,7 +569,7 @@ src/ ├── session/ # SQLite persistence ├── skills/ # Skill packages ├── tools/ # Builtin tools (shell, file, web, browser, process, media) -└── automation/ # Cron scheduler, webhooks, heartbeat monitor +└── automation/ # Cron scheduler, webhooks, heartbeat monitor, Gmail watcher ``` ## Development diff --git a/SOUL.md b/SOUL.md index b2864fe..4dad964 100644 --- a/SOUL.md +++ b/SOUL.md @@ -45,6 +45,7 @@ You have tools for interacting with your operator's system: - **file.read** -- Read file contents. Supports line ranges (offset/limit). - **file.write** -- Write or create files. Creates parent directories automatically. - **file.edit** -- Edit files via find-and-replace. Safer than rewriting entire files. +- **file.patch** -- Apply structured multi-hunk patches to one or more files. Line-based replacements, insertions, and deletions in a single call. - **file.list** -- List directory contents. Supports glob patterns. - **web.fetch** -- Fetch web pages. Use for looking things up, checking URLs, downloading content. diff --git a/config/default.yaml b/config/default.yaml index 9c04420..8c92447 100644 --- a/config/default.yaml +++ b/config/default.yaml @@ -66,8 +66,50 @@ hooks: confirm: - shell.* - file.write + - file.patch log: - web.* - file.read silent: - notify + +# ── Automation ────────────────────────────────────────────────────── +# Uncomment and configure any automation sources you need. + +# automation: +# cron: +# - name: daily-summary +# schedule: "0 9 * * *" +# message: "Give me a summary of today's tasks" +# output: +# channel: telegram +# peer: "123456789" +# +# webhooks: +# - name: github-push +# secret: "whsec_..." +# message: "GitHub push to {{json.repository.full_name}}: {{json.head_commit.message}}" +# output: +# channel: telegram +# peer: "123456789" +# +# gmail: +# enabled: false +# credentials_file: ~/.config/flynn/gmail-credentials.json +# token_file: ~/.config/flynn/gmail-token.json +# watch_labels: [INBOX] +# poll_interval: "60s" +# message: "New email from {{from}}: {{subject}}\n\n{{snippet}}" +# output: +# channel: telegram +# peer: "123456789" +# +# heartbeat: +# enabled: false +# interval: "5m" +# checks: [gateway, model, channels, memory, disk] +# notify: +# channel: telegram +# peer: "123456789" +# failure_threshold: 2 +# disk_threshold_mb: 100