1.5 KiB
1.5 KiB
name, description, runtime
| name | description | runtime |
|---|---|---|
| storyline | News-aggregator story layer workflow. Use when working on cluster.py, the prototype story engine, or the dsh backlog for it. | python |
Storyline skill — FreshRSS-adjacent story layer
The repo is a thin story layer beside a stock FreshRSS container. Read AGENTS.md before any change; its rules are binding (keep tests green, no FreshRSS rebuild, no Kafka, no frontend framework, capped LLM, Hermes at :8080, fixed ports).
Mental model
sources → fetch → dedup → cluster → rank → [LLM top-k] → out/index.html
- Dedup: pass 1 exact (normalized title / canonical URL), pass 2 MinHash-LSH → connected-component clusters (transitive merge).
- Rank:
score = authority * (coverage_count + 1) / (age_h + 2)^1.8. coverage_count (# sources on a story) is the "importance" signal — no votes. - LLM: only top-k (default 10) get summarized; input = headline + ~300 chars.
- Ports: FreshRSS 8280, RSSHub 1200, Hermes 8080,
--serve8765.
Verify every change
cd prototype && python -m pytest -q
Acceptance is "two reworded copies → one cluster" (see test_cluster.py).
Typical runs
python cluster.py --snapshot fr-export.json --llm --topk 10 # from FreshRSS export
python cluster.py --opml feeds.opml --llm --serve :8765 # live HTTP feeds, dev
LLM_BASE_URL=http://127.0.0.1:8080/v1 LLM_MODEL=hermes python cluster.py --llm
Never point summaries at DeepSeek unless the operator changes LLM_BASE_URL on purpose.