Shared runtime
- One agent entry point (runtime.invoke_agent_for_user / prepare_agent_turn) for
web, email, iMessage, WhatsApp, scheduled and cron, so identity, permissions,
memories, summaries and metrics match across channels.
- Serialize turns per checkpoint thread; /query validates input and returns 409
while a durable run owns the conversation.
Reconnectable chat (durable runs)
- POST /runs creates an idempotent, owner-scoped run; GET .../events replays an
ordered SSE log by cursor, so generation survives refresh and device switches.
Stop cancels; disconnect only detaches. /stream-query is a compatibility adapter.
- Coalesce streamed deltas (150 ms) and wake same-process subscribers instead of
polling; keep buffered text when a run is stopped.
- Drain runs on shutdown; serve via Hypercorn with a shutdown timeout covering
the drain (and no longer in debug mode). CHAT_RUN_* settings are forwarded.
Scheduled messages and cron
- Atomic delivery claims, attempt history and explicit retries; ambiguous sends
become "uncertain" and are never resent automatically.
- Cron triggers need a run_id/Idempotency-Key; legacy jobs need an explicit owner.
- Cancelling never rewrites a started delivery; series stop via tombstones.
Legacy sent rows are not forked into new series. Malformed bodies return 400.
History, integrations and retrieval
- Message-content search, pinned conversations, JSON/Markdown export and a
memory editor.
- Integration status panel and YNAB data-freshness provenance.
- Date-filtered document/note search with stable citations and a source viewer.
Migration 20 is generated by aerich.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Fail startup on unsafe or malformed production settings (scripts/validate_config.py),
run it before migrations, and stop on a failed `aerich upgrade`.
- Forward the context-budget, timeout and metrics settings through Compose; accept
the historical TAVILIY_API_KEY spelling.
- Build the image from uv.lock and yarn.lock in a multi-stage Dockerfile.
- Add Gitea Actions CI: Ruff, unit tests, context evaluation, frontend tests,
typecheck and build.
- Update README and deployment/development docs to match the current stack.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adds a new cron blueprint with UUID-keyed jobs that Cronicle triggers via
HTTP POST with a shared secret header. Also adds scripts/migrate-new.sh so
migrations can be generated locally against a Docker postgres when no prod
container is running.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replaces the gws CLI subprocess approach with google-api-python-client.
Adds get_calendar_events, create_calendar_event, gmail_search_emails, and
gmail_get_email as LangChain tools; all admin-gated and auto-enabled when
token.json is present. Includes uv-runnable scripts/google_auth.py for
one-time OAuth2 setup.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Split the raggr service into raggr-blue (8080) and raggr-green (8081)
behind compose profiles, add a /api/health endpoint and container
healthcheck, and add scripts/deploy.sh to build the inactive color,
wait for it to become healthy, then gracefully stop the old one.
Makefile targets resolve the active color automatically.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Consolidate onto PostgreSQL by using pgvector instead of a separate
ChromaDB instance. This removes a Docker volume, a large dependency,
and simplifies the stack without meaningful performance impact at
our document scale.
- Swap langchain-chroma for langchain-postgres (PGVector)
- Use pgvector/pgvector:pg16 Docker image with init script
- Lazy-initialize vector store to avoid eager DB connections
- Add SQL helpers for stats/delete/list (replacing _collection access)
- Remove legacy main.py, chunker, petmd scraper, and /api/query endpoint
Re-index required after deploy (POST /api/rag/index + /index-obsidian).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Update llm.py to use OpenAI client with custom base_url for llama-server
- Update agents.py to use ChatOpenAI instead of ChatOllama
- Remove unused ollama imports from main.py, chunker.py, query.py
- Add LLAMA_SERVER_URL and LLAMA_MODEL_NAME env vars
- Remove ollama and langchain-ollama dependencies
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>