prosolis 69967b25c6 Plumb ctx through classifier and Ollama HTTP path
OllamaClient.Generate/GenerateText/call now take ctx and build the HTTP
request via NewRequestWithContext, so an in-flight LLM call is aborted
when the parent context is cancelled (Ctrl-C). Classifier.Classify and
its tier helpers take ctx too. ProcessFunc gets a ctx parameter so the
poller can forward its cancellable context down to classification.

Explainer.summarize manages its own 60s context since reaction-driven
flow has no parent ctx to inherit.
2026-05-22 18:55:43 -07:00
2026-05-22 17:25:27 -07:00
2026-05-22 17:25:27 -07:00
2026-05-22 17:25:27 -07:00
2026-05-22 17:25:27 -07:00
2026-05-22 17:25:27 -07:00
2026-05-22 17:25:27 -07:00

Pete

A Matrix news bot that ingests RSS feeds from curated sources, classifies stories using a local LLM, deduplicates semantically, and routes posts to the appropriate channel.

Features

  • RSS ingestion from configurable sources (Guardian, Ars Technica) with per-source polling intervals
  • Two-tier classification — Tier 1 sources use direct routing or lightweight LLM routing; Tier 2 (wire services) use a keyword gating pipeline before LLM
  • Semantic deduplication — GUID exact match + LLM-based cross-source duplicate detection
  • Metered release — per-channel post queues with minimum interval (5min) and burst cap (3/30min)
  • Reaction tracking — records emoji reactions on posts for classifier tuning
  • !explain via reaction — react with (or ❔ ⁉ 🤔 ?) on any post; Pete fetches the article body and replies in-thread with a 3-bullet Ollama-generated TL;DR
  • Paywall detection — if an article's visible body text is below threshold, Pete swaps in a Wayback Machine snapshot URL for both the lead image and the posted link
  • FTS5 search — full-text search across headlines and ledes
  • Image validation — HEAD-based checks filter tracking pixels, uploads valid images via MXC

Channels

Channel Purpose
tech Technology news, product/industry stories
politics Political, policy, current events (default/catch-all)
gaming Gaming news, releases, platform announcements (no active sources yet)

Requirements

  • Go 1.25+
  • Ollama running locally or on a reachable host
  • A Matrix account for Pete with access to target rooms
  • SQLite (bundled via pure Go driver, no CGo)
  • No CGo dependencies — E2EE uses pure Go crypto (goolm) via mautrix v0.28

Setup

# Clone and build
git clone <repo-url> && cd pete
go build -tags goolm .

# Create config from example
cp config.example.yaml config.yaml
# Edit config.yaml — fill in Matrix credentials, room IDs, Ollama endpoint

# First run: seed current feed items as seen (prevents flood)
./pete -config config.yaml -seed

# Post one story to verify the pipeline
./pete -config config.yaml -test

# Run
./pete -config config.yaml

Configuration

See config.example.yaml for the full structure. Key sections:

  • matrix — homeserver, credentials, channel room IDs, optional admin room
  • ollama — base URL, model name, timeout
  • posting — rate limiting (min interval, burst cap)
  • storage — database path, retention windows
  • sources — RSS feeds with tier, polling interval, feed hint, optional direct routing

Environment variables can be referenced with ${VAR} syntax in the YAML.

Flags

Flag Description
-config <path> Path to config file (default: config.yaml)
-seed Ingest all current feed items as seen without posting, then exit
-test Post one story to verify the full pipeline, then exit

Docker

docker compose up -d

Set PETE_PASSWORD in your environment or a .env file for the Matrix password.

Architecture

RSS Feed → Poller → GUID Dedup → Canonical/Headline Dedup → Article Fetch → Store → Classifier → Semantic Dedup → Image Validate → Queue → Matrix
                                                                ↓                       ↓
                                                    Paywall? → Wayback           Direct Route (no LLM)
                                                                                       or
                                                                                  Ollama /api/chat (Tier 1 routing)
                                                                                       or
                                                                                  Keyword Gating → Ollama (Tier 2)

Posted message ← ❓ reaction → Explainer → Article Fetch → Ollama summary → Threaded reply

Packages

Package Purpose
internal/config YAML config loading with ${ENV} expansion
internal/storage SQLite with WAL, FTS5, all queries
internal/ingestion Per-source RSS polling, feed parsing, image validation
internal/classifier Ollama client, Tier 1/2 prompts, JSON repair, keyword gating
internal/matrix Password auth with device persistence, posting, threaded replies, reaction listener
internal/poster Per-channel metered release queue, reaction tracking, callback hook
internal/explainer -reaction → article fetch → Ollama summary → threaded reply

Post Format

[lead image if valid]
**Headline** → article_url
Lede text from feed
`source name`

Gaming stories append platform tags: `source` · `nintendo-switch` · `pc`

Testing

go test ./...
Description
A Matrix news bot that ingests RSS feeds from curated sources, classifies stories using a local LLM, deduplicates semantically, and routes posts to the appropriate channel.
Readme 6.6 MiB
Languages
Go 67%
JavaScript 19.6%
HTML 8.6%
CSS 4.7%