Merge pull request #183 from open-jarvis/feat/morning-digest-v2

feat: Morning Digest v2 — prompt tuning, new connectors, starter configs
This commit is contained in:
Jon Saad-Falcon
2026-04-03 17:39:54 -07:00
committed by GitHub
18 changed files with 1338 additions and 2 deletions
+45
View File
@@ -77,6 +77,51 @@ uv run jarvis ask "What is the capital of France?"
`jarvis init` auto-detects your hardware and recommends the best engine. Run `uv run jarvis doctor` at any time to diagnose issues.
## Starter Configs
Install any preset with one command:
```bash
jarvis init --preset morning-digest-mac # or any preset below
```
| Preset | Use Case | What it does |
|--------|----------|-------------|
| `morning-digest-mac` | Daily Briefing (Mac) | Spoken briefing from email, calendar, health, news with Jarvis voice |
| `morning-digest-linux` | Daily Briefing (Linux) | Same, with vLLM support for GPU servers |
| `morning-digest-minimal` | Daily Briefing (minimal) | Just Gmail + Calendar, runs on any machine |
| `deep-research` | Research Assistant | Multi-hop research across indexed docs with citations |
| `code-assistant` | Code Companion | Agent with code execution, file I/O, and shell access |
| `scheduled-monitor` | Persistent Monitor | Stateful agent that runs on a schedule with memory |
| `chat-simple` | Simple Chat | Lightweight conversation, no tools needed |
```bash
# Example: Morning Digest on Mac
jarvis init --preset morning-digest-mac
jarvis connect gdrive # one OAuth flow covers Gmail, Calendar, Tasks
jarvis digest --fresh # generate and play your first briefing
# Example: Deep Research
jarvis init --preset deep-research
jarvis memory index ./docs/ # index your documents
jarvis ask "Summarize all emails about Project X"
```
### Built-in Agents
| Agent | Type | What it does |
|-------|------|-------------|
| `morning_digest` | Scheduled | Daily briefing from email, calendar, health, news — with TTS audio |
| `deep_research` | On-demand | Multi-hop research with citations across web and local docs |
| `monitor_operative` | Continuous | Long-horizon monitoring with memory, compression, and retrieval |
| `orchestrator` | On-demand | Multi-turn reasoning with automatic tool selection |
| `native_react` | On-demand | ReAct (Thought-Action-Observation) loop agent |
| `operative` | Continuous | Persistent autonomous agent with state management |
| `native_openhands` | On-demand | CodeAct — generates and executes Python code |
| `simple` | On-demand | Single-turn chat, no tools |
See the [User Guide](https://open-jarvis.github.io/OpenJarvis/user-guide/morning-digest/) and [Tutorials](https://open-jarvis.github.io/OpenJarvis/tutorials/) for detailed setup instructions.
Full documentation — including Docker deployment, cloud engines, development setup, and tutorials — at **[open-jarvis.github.io/OpenJarvis](https://open-jarvis.github.io/OpenJarvis/)**.
## Contributing
@@ -0,0 +1,24 @@
# Simple Chat — lightweight conversational AI, no tools
# Copy to ~/.openjarvis/config.toml
#
# The fastest setup: just Ollama + a model.
#
# Usage:
# jarvis ask "What is quantum computing?"
# jarvis chat # interactive chat session
# jarvis serve # start API server for browser/desktop app
[engine]
default = "ollama"
[intelligence]
default_model = "qwen3.5:4b" # Fast and lightweight
# default_model = "qwen3.5:9b" # Better quality
# default_model = "llama3.1:8b" # Alternative model
[agent]
default_agent = "simple" # Single-turn, no tools
[server]
host = "0.0.0.0"
port = 8000
@@ -0,0 +1,21 @@
# Code Assistant — agent with code execution, file I/O, and shell access
# Copy to ~/.openjarvis/config.toml
#
# Usage:
# jarvis ask "Write a Python script that parses CSV files"
# jarvis ask "Read main.py and explain the architecture"
# jarvis ask --agent orchestrator "Find and fix the bug in test_utils.py"
[engine]
default = "ollama"
[intelligence]
default_model = "qwen3.5:9b"
# default_model = "qwen3.5:35b" # Better for complex code tasks
[agent]
default_agent = "orchestrator" # Multi-turn with tool selection
max_turns = 10
[tools]
enabled = ["code_interpreter", "file_read", "file_write", "shell_exec", "web_search", "think", "calculator"]
@@ -0,0 +1,27 @@
# Deep Research Agent — multi-hop research across your indexed documents
# Copy to ~/.openjarvis/config.toml
#
# First index your documents:
# jarvis memory index ./docs/
# jarvis memory index ~/Documents/papers/
#
# Then ask complex questions:
# jarvis ask --agent deep_research "Summarize all emails about Project X"
# jarvis ask --agent deep_research "What meetings did I have with Alice last month?"
[engine]
default = "ollama"
[intelligence]
default_model = "qwen3.5:9b"
temperature = 0.3 # Low temperature for factual research
[agent]
default_agent = "deep_research"
max_turns = 8 # Multi-hop reasoning steps
[tools]
enabled = ["knowledge_search", "knowledge_sql", "scan_chunks", "think", "web_search"]
[tools.storage]
default_backend = "sqlite"
@@ -0,0 +1,51 @@
# Morning Digest — Linux / Cloud GPU with Ollama or vLLM
# Copy to ~/.openjarvis/config.toml and customize
#
# Requirements:
# - Ollama or vLLM running locally
# - Cartesia or OpenAI API key for TTS
[engine]
default = "ollama"
# default = "vllm" # Use vLLM for GPU servers
[engine.ollama]
host = "http://localhost:11434"
# [engine.vllm]
# host = "http://localhost:8001"
[intelligence]
default_model = "qwen3.5:9b"
[agent]
default_agent = "simple"
[tools]
enabled = ["code_interpreter", "web_search", "file_read", "shell_exec", "digest_collect", "text_to_speech"]
# ─── Morning Digest ─────────────────────────────────────────
[digest]
enabled = true
schedule = "0 7 * * *"
timezone = "America/New_York" # Change to your timezone
persona = "jarvis"
honorific = "sir"
tts_backend = "openai" # OpenAI TTS works everywhere
voice_id = "onyx" # Deep male voice
voice_speed = 1.1
sections = ["health", "messages", "calendar", "world"]
[digest.health]
sources = ["oura"]
[digest.messages]
sources = ["gmail", "google_tasks", "slack"]
[digest.calendar]
sources = ["gcalendar"]
[digest.world]
sources = ["hackernews", "news_rss", "weather"]
@@ -0,0 +1,56 @@
# Morning Digest — Mac (Apple Silicon) with Ollama
# Copy to ~/.openjarvis/config.toml and customize
#
# Requirements:
# - Ollama installed (https://ollama.com)
# - ollama pull qwen3.5:9b
# - Cartesia API key (https://play.cartesia.ai) or OpenAI API key
[engine]
default = "ollama"
[intelligence]
default_model = "qwen3.5:9b" # Good balance of speed + quality on M1/M2/M3
# default_model = "qwen3.5:4b" # Faster, lower quality
# default_model = "qwen3.5:35b" # Slower, higher quality (needs 32GB+ RAM)
[agent]
default_agent = "simple"
[tools]
enabled = ["code_interpreter", "web_search", "file_read", "shell_exec", "digest_collect", "text_to_speech"]
# ─── Morning Digest ─────────────────────────────────────────
[digest]
enabled = true
schedule = "0 7 * * *" # 7 AM daily
timezone = "America/Los_Angeles" # Change to your timezone
persona = "jarvis"
honorific = "sir" # "sir", "ma'am", "boss", or any custom
tts_backend = "cartesia" # "cartesia" or "openai"
voice_id = "c8f7835e-28a3-4f0c-80d7-c1302ac62aae" # Alistair (British male)
voice_speed = 1.2 # 1.0 = normal, 1.2 = 20% faster
# Sections in order of priority (remove any you don't want):
sections = ["health", "messages", "calendar", "world"]
[digest.health]
sources = ["oura"] # Add "apple_health" if you export from iPhone
# sources = ["oura", "apple_health", "strava"]
[digest.messages]
sources = ["gmail", "google_tasks", "imessage"]
# Add any of: "slack", "notion", "github_notifications"
[digest.calendar]
sources = ["gcalendar"]
[digest.world]
sources = ["hackernews", "news_rss"]
# Add "weather" after setting up OpenWeatherMap API key
# ─── Optional: Music section ────────────────────────────────
# Uncomment and add "music" to sections list above
# [digest.music]
# sources = ["spotify", "apple_music"]
@@ -0,0 +1,31 @@
# Morning Digest — Minimal setup (just Ollama + Gmail)
# The simplest possible config to get a working digest.
# Copy to ~/.openjarvis/config.toml
#
# Requirements:
# - Ollama installed with any model
# - Google OAuth credentials (jarvis connect gdrive)
# - OpenAI API key for TTS (or skip audio with --text-only)
[engine]
default = "ollama"
[intelligence]
default_model = "qwen3.5:4b" # Small, fast, runs on any machine
[tools]
enabled = ["digest_collect", "text_to_speech"]
[digest]
enabled = true
persona = "jarvis"
honorific = "sir"
tts_backend = "openai"
voice_id = "onyx"
sections = ["messages", "calendar"]
[digest.messages]
sources = ["gmail"]
[digest.calendar]
sources = ["gcalendar"]
@@ -0,0 +1,35 @@
# Scheduled Monitor — persistent agent that runs on a schedule
# Copy to ~/.openjarvis/config.toml
#
# The operative agent maintains state across runs, making it ideal for:
# - Daily email/inbox monitoring
# - Recurring status checks
# - Long-running research projects
#
# Setup:
# 1. Index your data: jarvis memory index ~/Documents/
# 2. Start the scheduler: jarvis scheduler start
# 3. Create a task:
# jarvis scheduler create \
# --prompt "Check for new emails about Project X and update your notes" \
# --schedule "0 9 * * 1-5" \
# --agent operative \
# --tools "knowledge_search,knowledge_sql,memory_store,think"
[engine]
default = "ollama"
[intelligence]
default_model = "qwen3.5:9b"
temperature = 0.3
[agent]
default_agent = "operative"
max_turns = 20
context_from_memory = true # Inject relevant memory into context
[tools]
enabled = ["knowledge_search", "knowledge_sql", "scan_chunks", "memory_store", "memory_search", "think", "web_search"]
[tools.storage]
default_backend = "sqlite"
+58
View File
@@ -45,8 +45,66 @@ OpenJarvis is a modular AI assistant framework. Here's what developers build wit
# Now use any OpenAI-compatible client
```
=== "Morning Digest"
```bash
cp configs/openjarvis/examples/morning-digest-mac.toml ~/.openjarvis/config.toml
jarvis connect gdrive # one OAuth flow for Gmail, Calendar, Tasks
CARTESIA_API_KEY="..." jarvis digest --fresh
# Plays a spoken daily briefing with your email, calendar, health, and news
```
=== "Deep Research"
```bash
jarvis init --preset deep-research
jarvis memory index ~/Documents/papers/
jarvis ask "Summarize all documents about transformer architectures"
# Multi-hop search across your indexed docs with citations
```
=== "Code Assistant"
```bash
jarvis init --preset code-assistant
jarvis ask "Write a Python script that parses CSV files"
# Orchestrator agent with code execution, file I/O, and shell access
```
=== "Scheduled Monitor"
```bash
jarvis init --preset scheduled-monitor
jarvis memory index ~/Documents/
jarvis scheduler start
jarvis scheduler create \
--prompt "Check for new emails about Project X" \
--schedule "0 9 * * 1-5" --agent operative
# Persistent agent that runs on a cron schedule
```
For complete copy-paste patterns, see [Code Snippets](snippets.md).
## Starter Configs
Copy one of these to `~/.openjarvis/config.toml` to get a pre-configured setup:
| Config | For | What it does |
|--------|-----|-------------|
| [`chat-simple.toml`](https://github.com/open-jarvis/OpenJarvis/blob/main/configs/openjarvis/examples/chat-simple.toml) | Any machine | Lightweight chat, no tools -- simplest setup |
| [`code-assistant.toml`](https://github.com/open-jarvis/OpenJarvis/blob/main/configs/openjarvis/examples/code-assistant.toml) | Any machine | Orchestrator agent with code execution, file I/O, shell |
| [`deep-research.toml`](https://github.com/open-jarvis/OpenJarvis/blob/main/configs/openjarvis/examples/deep-research.toml) | Any machine | Multi-hop research across indexed documents with citations |
| [`scheduled-monitor.toml`](https://github.com/open-jarvis/OpenJarvis/blob/main/configs/openjarvis/examples/scheduled-monitor.toml) | Any machine | Persistent operative agent on a cron schedule |
| [`morning-digest-mac.toml`](https://github.com/open-jarvis/OpenJarvis/blob/main/configs/openjarvis/examples/morning-digest-mac.toml) | Mac (Apple Silicon) | Daily spoken briefing from email, calendar, health, news |
| [`morning-digest-linux.toml`](https://github.com/open-jarvis/OpenJarvis/blob/main/configs/openjarvis/examples/morning-digest-linux.toml) | Linux / GPU server | Same, with vLLM support |
| [`morning-digest-minimal.toml`](https://github.com/open-jarvis/OpenJarvis/blob/main/configs/openjarvis/examples/morning-digest-minimal.toml) | Any machine | Just Gmail + Calendar |
Or generate a config with digest included:
```bash
jarvis init --digest
```
This guide walks through the core workflows of OpenJarvis: the browser app, CLI, Python SDK, agents with tools, memory, benchmarks, and the API server.
!!! info "Prerequisites"
+1 -1
View File
@@ -169,7 +169,7 @@ OpenJarvis is built around five composable layers. Each has a clean interface an
---
CLI, Python SDK, agents, memory, tools, telemetry, and benchmarks.
CLI, Python SDK, and guides for [Morning Digest](user-guide/morning-digest.md), [Deep Research](user-guide/deep-research.md), [Code Assistant](user-guide/code-assistant.md), [Scheduled Monitor](user-guide/scheduled-monitor.md), [Simple Chat](user-guide/chat-simple.md), agents, memory, tools, and telemetry.
- **[Architecture](architecture/overview.md)**
+154
View File
@@ -0,0 +1,154 @@
# Simple Chat
A lightweight conversational AI with no tools and no agent overhead. This is the simplest possible OpenJarvis setup: just Ollama and a local model. Ideal for general-purpose chat, Q&A, brainstorming, and getting started quickly.
## Quickstart (3 minutes)
### 1. Install Ollama and pull a model
```bash
# Install Ollama: https://ollama.com
ollama pull qwen3.5:4b
```
### 2. Install and initialize OpenJarvis
```bash
git clone https://github.com/open-jarvis/OpenJarvis.git
cd OpenJarvis
uv sync
jarvis init --preset chat-simple
```
### 3. Ask a question
```bash
jarvis ask "What is quantum computing?"
```
That's it. No API keys, no tools, no cloud -- just a local model answering your questions.
## CLI Commands
```bash
# Single question
jarvis ask "Explain the difference between TCP and UDP"
# Interactive chat session (multi-turn conversation)
jarvis chat
# Start the API server for the browser or desktop app
jarvis serve
# Override the model for a single query
jarvis ask -m qwen3.5:9b "Explain general relativity"
# Adjust temperature (0.0 = deterministic, 1.0 = creative)
jarvis ask -t 0.2 "List the planets in our solar system"
# Output raw JSON
jarvis ask --json "What is 2+2?"
```
## Configuration Reference
The preset writes this to `~/.openjarvis/config.toml`:
```toml
[engine]
default = "ollama"
[intelligence]
default_model = "qwen3.5:4b" # Fast and lightweight
# default_model = "qwen3.5:9b" # Better quality
# default_model = "llama3.1:8b" # Alternative model
[agent]
default_agent = "simple" # Single-turn, no tools
[server]
host = "0.0.0.0"
port = 8000
```
### Model options
| Model | Parameters | Speed | Quality | Best for |
|-------|-----------|-------|---------|----------|
| `qwen3.5:4b` | 4B | Fast | Good | Quick answers, lightweight hardware |
| `qwen3.5:9b` | 9B | Balanced | Better | General-purpose chat, explanations |
| `qwen3.5:35b` | 35B | Slower | Best | Complex reasoning, detailed analysis |
| `llama3.1:8b` | 8B | Balanced | Good | Alternative if you prefer Meta models |
To switch models, either edit `~/.openjarvis/config.toml` or override per-query:
```bash
jarvis ask -m qwen3.5:35b "Write a detailed comparison of REST and GraphQL"
```
To pull a new model:
```bash
ollama pull qwen3.5:35b
```
## Using the Browser App
Start the backend server and the React frontend with one command:
```bash
./scripts/quickstart.sh
```
This opens [http://localhost:5173](http://localhost:5173) in your browser with a full chat interface, streaming responses, and an energy monitoring dashboard.
To run just the API server (for use with the desktop app or external clients):
```bash
jarvis serve
```
The server is OpenAI-compatible, so any client that works with the OpenAI API can point to `http://localhost:8000/v1`.
## Using the Desktop App
1. Start the backend: `jarvis serve` (or `./scripts/quickstart.sh`)
2. Download and open the desktop app from the [releases page](https://github.com/open-jarvis/OpenJarvis/releases)
3. The app connects to `http://localhost:8000` automatically
## Switching Models
You can change the default model at any time:
**Edit the config:**
```bash
# Open the config file
${EDITOR:-nano} ~/.openjarvis/config.toml
# Change default_model to your preferred model
```
**Pull and switch in one step:**
```bash
ollama pull deepseek-r1:14b
jarvis ask -m deepseek-r1:14b "Hello"
```
**Use an environment variable:**
```bash
OPENJARVIS_MODEL=qwen3.5:9b jarvis ask "Hello"
```
## Troubleshooting
**"No running engine found"** -- Make sure Ollama is running. Start it with `ollama serve` or open the Ollama desktop app.
**"Model not found"** -- Pull the model first with `ollama pull <model-name>`. List available models with `ollama list`.
**Slow responses** -- Use a smaller model (`qwen3.5:4b`). Check available memory; models need RAM roughly equal to their parameter count in GB (e.g., 9B model needs ~9 GB).
**Want to add tools later?** -- Switch to the [Code Assistant](code-assistant.md) or [Deep Research](deep-research.md) config. Simple chat is intentionally minimal.
**Browser app not loading** -- Make sure both the backend (`jarvis serve`) and frontend are running. The `./scripts/quickstart.sh` script starts both automatically.
+137
View File
@@ -0,0 +1,137 @@
# Code Assistant
An orchestrator agent with code execution, file I/O, and shell access. It can write scripts, read and explain code, run tests, fix bugs, and execute shell commands -- all locally on your machine.
## Quickstart (5 minutes)
### 1. Install and initialize
```bash
git clone https://github.com/open-jarvis/OpenJarvis.git
cd OpenJarvis
uv sync --extra dev
jarvis init --preset code-assistant
```
This writes a pre-configured `~/.openjarvis/config.toml` for the code assistant.
### 2. Start a local LLM via Ollama
```bash
# Install Ollama: https://ollama.com
ollama pull qwen3.5:9b
```
### 3. Ask a coding question
```bash
jarvis ask "Write a Python script that reads a CSV file and prints the top 5 rows"
```
The orchestrator agent will plan the approach, write the code, and can execute it if you approve.
## CLI Commands
```bash
# Ask a coding question (uses orchestrator agent by default with this config)
jarvis ask "Write a Python script that parses JSON from stdin"
# Read and explain existing code
jarvis ask "Read main.py and explain the architecture"
# Fix a bug
jarvis ask "Find and fix the bug in test_utils.py"
# Run tests
jarvis ask "Run the test suite and summarize any failures"
# Explicitly specify agent and tools
jarvis ask --agent orchestrator --tools code_interpreter "Calculate the first 20 Fibonacci numbers"
# Interactive chat for iterative coding
jarvis chat
```
## Configuration Reference
The preset writes this to `~/.openjarvis/config.toml`:
```toml
[engine]
default = "ollama"
[intelligence]
default_model = "qwen3.5:9b"
# default_model = "qwen3.5:35b" # Better for complex code tasks
[agent]
default_agent = "orchestrator" # Multi-turn with tool selection
max_turns = 10
[tools]
enabled = ["code_interpreter", "file_read", "file_write", "shell_exec", "web_search", "think", "calculator"]
```
### Key settings
| Setting | Default | Description |
|---------|---------|-------------|
| `intelligence.default_model` | `qwen3.5:9b` | The model for code generation. Use `qwen3.5:35b` for complex tasks like refactoring or multi-file changes. |
| `agent.default_agent` | `orchestrator` | Multi-turn agent that picks tools iteratively until it has an answer. |
| `agent.max_turns` | `10` | Maximum tool-calling iterations. Increase for multi-step tasks. |
| `tools.enabled` | 7 tools | `code_interpreter` (execute Python), `file_read`, `file_write`, `shell_exec` (run shell commands), `web_search`, `think`, `calculator`. |
### Tools explained
| Tool | What it does |
|------|-------------|
| `code_interpreter` | Executes Python code in a sandboxed environment and returns output. |
| `file_read` | Reads files with path validation. The agent can inspect source code, configs, logs. |
| `file_write` | Writes or modifies files. The agent can create scripts, patch code, write configs. |
| `shell_exec` | Runs shell commands (e.g., `git status`, `pytest`, `ls`). |
| `web_search` | Searches the web for documentation, Stack Overflow answers, etc. |
| `think` | Internal reasoning scratchpad for planning multi-step solutions. |
| `calculator` | Evaluates mathematical expressions. |
## Example Tasks
```bash
# Write a new script
jarvis ask "Write a Python script that converts YAML to JSON"
# Explain existing code
jarvis ask "Read src/openjarvis/core/events.py and explain the EventBus pattern"
# Debug a failing test
jarvis ask "Run pytest tests/test_memory.py -v and fix any failures"
# Refactor code
jarvis ask "Read utils.py and refactor the parse_config function to use dataclasses"
# Generate tests
jarvis ask "Read src/openjarvis/tools/calculator.py and write unit tests for it"
# Shell tasks
jarvis ask "Find all Python files larger than 100KB in this repo"
```
## Safety Notes
The `shell_exec` and `code_interpreter` tools execute real commands on your machine. Keep these in mind:
- **shell_exec** runs commands in your current user context. It can read, write, and delete files. Avoid running the agent on directories containing sensitive data without reviewing tool calls.
- **code_interpreter** executes Python code. It has access to your Python environment and installed packages.
- The agent asks for confirmation before executing potentially destructive commands when running in interactive mode (`jarvis chat`).
- For stronger isolation, use the sandboxed agent: `jarvis ask --agent sandboxed --tools code_interpreter "..."`, which runs inside a Docker/Podman container.
## Troubleshooting
**"Tool not found: code_interpreter"** -- Make sure your `config.toml` includes `code_interpreter` in the `tools.enabled` list.
**Agent loops without progress** -- Increase `max_turns` if the task is complex, or use a larger model (`qwen3.5:35b`). The 9b model handles most single-file tasks; multi-file refactoring benefits from more parameters.
**Shell command fails** -- The `shell_exec` tool runs commands relative to where you launched `jarvis`. Use `cd /path && command` in your prompt if needed, or run `jarvis` from the project directory.
**Web search not working** -- Install with `uv sync --extra tools-search` and set `TAVILY_API_KEY`.
**Code execution hangs** -- The `code_interpreter` has a default timeout. Long-running scripts will be terminated. Break large tasks into smaller steps.
+165
View File
@@ -0,0 +1,165 @@
# Deep Research
A multi-hop research agent that searches across your indexed documents, cross-references information, and returns answers with citations. It reasons through complex queries step by step, pulling context from multiple sources in your local knowledge base.
## Quickstart (5 minutes)
### 1. Install and initialize
```bash
git clone https://github.com/open-jarvis/OpenJarvis.git
cd OpenJarvis
uv sync --extra dev
jarvis init --preset deep-research
```
This writes a pre-configured `~/.openjarvis/config.toml` for the deep research agent.
### 2. Index your documents
```bash
# Install Ollama: https://ollama.com
ollama pull qwen3.5:9b
# Index a directory of files
jarvis memory index ./docs/
jarvis memory index ~/Documents/papers/
```
OpenJarvis chunks the content and stores it in a local SQLite/FTS5 database. Supported formats include `.txt`, `.md`, `.pdf`, `.py`, `.json`, `.csv`, and more.
### 3. Ask a research question
```bash
jarvis ask "Summarize all documents about transformer architectures"
```
The deep research agent will:
1. Search your indexed documents for relevant chunks
2. Reason across multiple sources (up to 8 hops)
3. Synthesize a coherent answer with references to source documents
## CLI Commands
```bash
# Ask a question (uses deep_research agent by default with this config)
jarvis ask "What meetings did I have with Alice last month?"
# Explicitly specify the agent
jarvis ask --agent deep_research "Compare the approaches described in paper-a.pdf and paper-b.pdf"
# Index more documents
jarvis memory index ~/Downloads/reports/
jarvis memory index ./notes.md
# Search memory directly
jarvis memory search "project timeline"
jarvis memory search -k 20 "budget estimates"
# Check what's indexed
jarvis memory stats
```
## Configuration Reference
The preset writes this to `~/.openjarvis/config.toml`:
```toml
[engine]
default = "ollama"
[intelligence]
default_model = "qwen3.5:9b"
temperature = 0.3 # Low temperature for factual research
[agent]
default_agent = "deep_research"
max_turns = 8 # Multi-hop reasoning steps
[tools]
enabled = ["knowledge_search", "knowledge_sql", "scan_chunks", "think", "web_search"]
[tools.storage]
default_backend = "sqlite"
```
### Key settings
| Setting | Default | Description |
|---------|---------|-------------|
| `intelligence.default_model` | `qwen3.5:9b` | The model used for reasoning. Larger models (e.g., `qwen3.5:35b`) give better results on complex queries. |
| `intelligence.temperature` | `0.3` | Low temperature keeps answers factual. Increase for more creative synthesis. |
| `agent.max_turns` | `8` | Maximum reasoning hops. Increase for deeply nested research tasks. |
| `tools.enabled` | 5 tools | `knowledge_search` (semantic), `knowledge_sql` (structured), `scan_chunks` (browse), `think` (reasoning scratchpad), `web_search` (online fallback). |
| `tools.storage.default_backend` | `sqlite` | FTS5-backed full-text search. Also supports `faiss`, `colbert`, `bm25`, and `hybrid`. |
## Example Queries
```bash
# Summarize across multiple documents
jarvis ask "Summarize all emails about the Q3 budget review"
# Cross-reference sources
jarvis ask "What do papers A and B agree on regarding attention mechanisms?"
# Find specific information
jarvis ask "What meetings did I have with Alice last month?"
# Extract structured data
jarvis ask "List all action items from the meeting notes in ~/Documents/meetings/"
# Research with web fallback
jarvis ask "Compare our internal benchmarks with the latest published results"
```
## Indexing Different Data Sources
### Local files and directories
```bash
# Recursively index a directory
jarvis memory index ~/Documents/
# Single file
jarvis memory index ./report.pdf
# Custom chunk size for long documents
jarvis memory index ./paper.pdf --chunk-size 1024 --chunk-overlap 128
```
### PDFs
PDFs are automatically extracted and chunked. For best results with scanned PDFs, ensure they have been OCR-processed.
```bash
jarvis memory index ~/Papers/*.pdf
```
### Web pages
Use the `web_search` tool (enabled by default in this config) to pull in online sources at query time. For persistent indexing of web content, download pages first:
```bash
curl -s https://example.com/article | jarvis memory index --stdin --source "example.com"
```
### Code repositories
```bash
jarvis memory index ./src/ --chunk-size 256
```
Smaller chunk sizes work better for code, where each function or class is a natural unit.
## Troubleshooting
**"No results found"** -- Make sure you have indexed documents first with `jarvis memory index`. Check indexed content with `jarvis memory stats`.
**Answers are too vague** -- Try increasing `max_turns` in the config (e.g., `12` or `15`) to give the agent more reasoning steps. You can also try a larger model like `qwen3.5:35b`.
**Slow responses** -- The agent makes multiple search passes. Each turn involves a model call. Reduce `max_turns` or use a smaller model (`qwen3.5:4b`) for faster but less thorough results.
**Web search not working** -- The `web_search` tool requires the Tavily API. Install with `uv sync --extra tools-search` and set `TAVILY_API_KEY`.
**Wrong chunks retrieved** -- Try re-indexing with different chunk sizes. For technical documents, smaller chunks (`256`) often retrieve more precisely. For narrative text, larger chunks (`1024`) preserve more context.
+218
View File
@@ -0,0 +1,218 @@
# Morning Digest
A personalized daily briefing that collects data from your connected services, synthesizes a spoken narrative with a local LLM, and delivers it as audio via text-to-speech.
## Quickstart (5 minutes)
### 1. Install and set up OpenJarvis
```bash
git clone https://github.com/open-jarvis/OpenJarvis.git
cd OpenJarvis
uv sync --extra dev
```
### 2. Start a local LLM via Ollama
```bash
# Install Ollama: https://ollama.com
ollama pull qwen3.5:9b # or any model you prefer
```
### 3. Configure the digest
Edit `~/.openjarvis/config.toml`:
```toml
[engine]
default = "ollama"
[intelligence]
default_model = "qwen3.5:9b"
[digest]
enabled = true
schedule = "0 6 * * *" # 6 AM daily (cron syntax)
timezone = "America/Los_Angeles"
persona = "jarvis"
honorific = "sir" # or "ma'am", "boss", etc.
tts_backend = "cartesia" # or "openai"
voice_id = "c8f7835e-28a3-4f0c-80d7-c1302ac62aae" # Alistair (British male)
voice_speed = 1.2
sections = ["health", "messages", "calendar", "world"]
[digest.health]
sources = ["oura"]
[digest.messages]
sources = ["gmail", "google_tasks", "slack", "imessage"]
[digest.calendar]
sources = ["gcalendar"]
[digest.world]
sources = ["weather", "hackernews", "news_rss"]
```
### 4. Connect your data sources
```bash
# Google (one flow covers Gmail, Calendar, Tasks, Contacts, Drive)
jarvis connect gdrive
# Paste: <client_id>:<client_secret> — browser opens automatically
# Oura Ring (personal access token)
jarvis connect oura
# Paste your token from https://cloud.ouraring.com/personal-access-tokens
# Spotify
jarvis connect spotify
# Strava
jarvis connect strava
```
For Weather, GitHub, and News — save credential files directly:
```bash
# Weather (OpenWeatherMap — free at https://openweathermap.org/api)
echo '{"api_key": "YOUR_KEY", "location": "San Francisco,CA,US"}' > ~/.openjarvis/connectors/weather.json
# GitHub notifications (token from https://github.com/settings/tokens)
echo '{"token": "ghp_YOUR_TOKEN"}' > ~/.openjarvis/connectors/github.json
# News RSS (no auth needed — configure your feeds)
cat > ~/.openjarvis/connectors/news_rss.json << 'EOF'
{"feeds": [
{"name": "Arxiv CS.AI", "url": "https://rss.arxiv.org/rss/cs.AI"},
{"name": "TechCrunch", "url": "https://techcrunch.com/feed/"},
{"name": "Bloomberg", "url": "https://feeds.bloomberg.com/markets/news.rss"},
{"name": "WSJ", "url": "https://feeds.a.dj.com/rss/RSSWorldNews.xml"}
]}
EOF
```
Hacker News, iMessage, and Apple Music work automatically on macOS with no setup.
### 5. Set your TTS API key
```bash
# Cartesia (sign up at https://play.cartesia.ai)
export CARTESIA_API_KEY="sk_car_..."
# Or OpenAI (https://platform.openai.com/api-keys)
export OPENAI_API_KEY="sk-proj-..."
```
### 6. Run your first digest
```bash
CARTESIA_API_KEY="sk_car_..." jarvis digest --fresh
```
The digest will:
1. Collect data from all connected sources
2. Synthesize a spoken briefing with Qwen3.5 9B
3. Generate audio with the Cartesia Alistair voice
4. Print the text and play the audio
## CLI Commands
```bash
jarvis digest --fresh # Generate a new digest now
jarvis digest # Show today's cached digest
jarvis digest --text-only # Print text without audio
jarvis digest --history # Show past digests
jarvis digest --schedule "0 6 * * *" # Set daily schedule
jarvis digest --schedule off # Disable schedule
jarvis digest --schedule # Show current schedule
```
## Saying "Good morning"
When chatting with Jarvis (via CLI, desktop, or browser), saying "Good morning" or "morning digest" automatically triggers the digest — no need to use the `digest` command explicitly.
## Configuration Reference
### Sections
The `sections` list controls what the digest covers, in order of priority:
| Section | Sources | What it provides |
|---------|---------|-----------------|
| `health` | `oura`, `apple_health`, `strava` | Sleep, readiness, activity, workouts |
| `messages` | `gmail`, `google_tasks`, `slack`, `notion`, `imessage`, `github_notifications` | Email triage, tasks, texts, Slack, PRs |
| `calendar` | `gcalendar` | Today's events and schedule |
| `world` | `weather`, `hackernews`, `news_rss` | Weather forecast, tech news, RSS feeds |
| `music` | `spotify`, `apple_music` | Recently played tracks (opt-in) |
### TTS Voices
**Cartesia** (recommended — natural, expressive):
| Voice | ID | Description |
|-------|----|-------------|
| Alistair | `c8f7835e-28a3-4f0c-80d7-c1302ac62aae` | Sophisticated British male |
| Benedict | `3c0f09d6-e0d7-499c-a594-70c5b7b93048` | Polished, formal British male |
| Harrison | `df89f42f-f285-4613-adbf-14eedcec4c9e` | Crisp, professional British male |
| Sterling | `b134c304-d095-4d2b-a77a-914f5e8e84e7` | Deep, commanding, dignified |
**OpenAI TTS**:
| Voice | Description |
|-------|-------------|
| `onyx` | Deep male |
| `nova` | Female, warm |
| `alloy` | Neutral |
| `shimmer` | Female, expressive |
### Persona
The `persona` field loads a prompt file from `configs/openjarvis/prompts/personas/{name}.md`. The default `jarvis` persona delivers briefings with dry British wit, prioritizes urgent items, and interprets health data as trends rather than raw numbers.
To create a custom persona, add a new `.md` file in the personas directory.
### News Feeds
Add any RSS or Atom feed to `~/.openjarvis/connectors/news_rss.json`:
```json
{"feeds": [
{"name": "Arxiv CS.AI", "url": "https://rss.arxiv.org/rss/cs.AI"},
{"name": "Arxiv CS.LG", "url": "https://rss.arxiv.org/rss/cs.LG"},
{"name": "NYT Top Stories", "url": "https://rss.nytimes.com/services/xml/rss/nyt/HomePage.xml"},
{"name": "TechCrunch", "url": "https://techcrunch.com/feed/"},
{"name": "Bloomberg Markets", "url": "https://feeds.bloomberg.com/markets/news.rss"},
{"name": "WSJ World News", "url": "https://feeds.a.dj.com/rss/RSSWorldNews.xml"},
{"name": "Hacker News", "url": "https://hnrss.org/frontpage"}
]}
```
## API Endpoints
The digest is also available via the FastAPI server:
```bash
jarvis serve # Start the server
# GET /api/digest — Get today's digest text
# GET /api/digest/audio — Stream the digest audio (MP3)
# POST /api/digest/generate — Force re-generation
# GET /api/digest/history — Past digests
# GET /api/digest/schedule — Current schedule config
# POST /api/digest/schedule — Update schedule {"enabled": true, "cron": "0 6 * * *"}
```
## Frontend
The desktop and browser apps show an inline audio player when a digest is generated. The "Connect" buttons in the setup wizard handle OAuth flows automatically — click to connect, authorize in the browser popup, done.
## Troubleshooting
**"No digest for today"** — Run `jarvis digest --fresh` to generate one.
**Empty sections** — Check connector status with `jarvis connect --list`. Ensure tokens haven't expired (Google/Spotify tokens expire after 1 hour and are auto-refreshed on next use).
**Weather not working** — OpenWeatherMap API keys can take up to 2 hours to activate after creation. Use the format `City,State,Country` (e.g., `Palo Alto,CA,US`).
**GitHub 403** — Your personal access token needs the `notifications` permission under Account permissions (not Repository permissions).
**Audio not playing** — Ensure `CARTESIA_API_KEY` or `OPENAI_API_KEY` is set. Check credits at https://play.cartesia.ai or https://platform.openai.com.
+201
View File
@@ -0,0 +1,201 @@
# Scheduled Monitor
A persistent operative agent that runs on a cron schedule, maintains state across runs, and uses memory to track changes over time. Ideal for daily inbox monitoring, recurring status checks, and long-running research projects.
## Quickstart (5 minutes)
### 1. Install and initialize
```bash
git clone https://github.com/open-jarvis/OpenJarvis.git
cd OpenJarvis
uv sync --extra dev
jarvis init --preset scheduled-monitor
```
This writes a pre-configured `~/.openjarvis/config.toml` for the operative agent with scheduling support.
### 2. Start a local LLM via Ollama
```bash
# Install Ollama: https://ollama.com
ollama pull qwen3.5:9b
```
### 3. Index your data
```bash
jarvis memory index ~/Documents/
```
The operative agent uses memory to track state across runs, so indexing your data gives it context for the first run.
### 4. Create a scheduled task
```bash
jarvis scheduler start
jarvis scheduler create \
--prompt "Check for new emails about Project X and update your notes" \
--schedule "0 9 * * 1-5" \
--agent operative \
--tools "knowledge_search,knowledge_sql,memory_store,think"
```
This creates a task that runs at 9 AM every weekday. The operative agent will search your indexed data, process new information, and store notes in memory for the next run.
## How Scheduling Works
The scheduler uses cron expressions to trigger agent runs at specified intervals. Each run is an independent agent session, but the operative agent persists state between sessions.
### Cron expression reference
```
.------------ minute (0-59)
| .---------- hour (0-23)
| | .-------- day of month (1-31)
| | | .------ month (1-12)
| | | | .---- day of week (0-6, 0=Sunday)
| | | | |
* * * * *
```
Common examples:
| Expression | Meaning |
|------------|---------|
| `0 9 * * 1-5` | 9 AM, Monday through Friday |
| `0 6 * * *` | 6 AM every day |
| `*/30 * * * *` | Every 30 minutes |
| `0 9,17 * * *` | 9 AM and 5 PM daily |
| `0 8 1 * *` | 8 AM on the 1st of every month |
### CLI commands
```bash
# Start the scheduler daemon
jarvis scheduler start
# Create a new scheduled task
jarvis scheduler create \
--prompt "Summarize any new research papers in my library" \
--schedule "0 8 * * *" \
--agent operative
# List all scheduled tasks
jarvis scheduler list
# View task details and run history
jarvis scheduler status <task-id>
# Pause / resume / delete a task
jarvis scheduler pause <task-id>
jarvis scheduler resume <task-id>
jarvis scheduler delete <task-id>
# Run a task immediately (outside its schedule)
jarvis scheduler run <task-id>
# Stop the scheduler daemon
jarvis scheduler stop
```
## Configuration Reference
The preset writes this to `~/.openjarvis/config.toml`:
```toml
[engine]
default = "ollama"
[intelligence]
default_model = "qwen3.5:9b"
temperature = 0.3
[agent]
default_agent = "operative"
max_turns = 20
context_from_memory = true # Inject relevant memory into context
[tools]
enabled = ["knowledge_search", "knowledge_sql", "scan_chunks", "memory_store", "memory_search", "think", "web_search"]
[tools.storage]
default_backend = "sqlite"
```
### Key settings
| Setting | Default | Description |
|---------|---------|-------------|
| `intelligence.default_model` | `qwen3.5:9b` | The model used for reasoning. |
| `intelligence.temperature` | `0.3` | Low temperature for consistent, factual outputs across runs. |
| `agent.default_agent` | `operative` | Persistent agent that maintains state between sessions. |
| `agent.max_turns` | `20` | High turn limit for thorough processing of accumulated data. |
| `agent.context_from_memory` | `true` | Automatically injects relevant memory chunks into the agent's context. |
| `tools.enabled` | 7 tools | Search, store, scan, and reason tools for reading and writing to the knowledge base. |
### Tools explained
| Tool | What it does |
|------|-------------|
| `knowledge_search` | Semantic search across indexed documents. |
| `knowledge_sql` | Structured queries against the document store. |
| `scan_chunks` | Browse through document chunks sequentially. |
| `memory_store` | Write new facts and notes to the knowledge base. |
| `memory_search` | Search previously stored agent notes. |
| `think` | Internal reasoning scratchpad for planning. |
| `web_search` | Search the web for supplementary information. |
## Example Use Cases
### Daily inbox monitor
```bash
jarvis scheduler create \
--prompt "Review my recent emails. Flag anything urgent and summarize the rest. Store a daily summary." \
--schedule "0 9 * * 1-5" \
--agent operative \
--tools "knowledge_search,memory_store,think"
```
### Research tracker
```bash
jarvis scheduler create \
--prompt "Search for new papers related to 'efficient transformers'. Compare with papers I've already indexed and note what's new." \
--schedule "0 8 * * 1" \
--agent operative \
--tools "knowledge_search,web_search,memory_store,think"
```
### Status reporter
```bash
jarvis scheduler create \
--prompt "Check the project status documents and generate a weekly progress summary. Note any blockers." \
--schedule "0 17 * * 5" \
--agent operative \
--tools "knowledge_search,knowledge_sql,memory_store,think"
```
## How State Persistence Works
The operative agent differs from other agents in that it maintains state across runs:
- **Memory storage**: The agent uses the `memory_store` tool to save notes, summaries, and observations. These persist in the local SQLite database and are available in future runs.
- **Context injection**: With `context_from_memory = true`, the agent automatically receives relevant context from previous runs when it starts a new session.
- **Accumulated knowledge**: Over time, the agent builds a progressively richer understanding of your data. A Monday run can reference notes from the previous Friday.
- **All data stays local**: State is stored in `~/.openjarvis/` using the configured memory backend. Nothing leaves your machine.
## Troubleshooting
**"Scheduler not running"** -- Start the scheduler daemon with `jarvis scheduler start`. It must be running for scheduled tasks to execute.
**Task doesn't run on time** -- Check that Ollama is running (`ollama serve`). The scheduler triggers the agent, but the agent needs an inference engine. Verify the schedule with `jarvis scheduler status <task-id>`.
**Agent produces inconsistent results** -- Keep `temperature` at `0.3` or lower for scheduled tasks. Higher temperatures introduce randomness that compounds across runs.
**Memory grows too large** -- Periodically review with `jarvis memory stats`. Clear old entries with `jarvis memory clear --before 2026-01-01` if needed.
**Agent runs too long** -- Reduce `max_turns` or simplify the prompt. The operative agent is thorough and may use all available turns.
+12
View File
@@ -165,8 +165,20 @@ nav:
- Design Principles: architecture/design-principles.md
- API Reference: api-reference/
- User Guide:
- CLI: user-guide/cli.md
- Python SDK: user-guide/python-sdk.md
- Morning Digest: user-guide/morning-digest.md
- Deep Research: user-guide/deep-research.md
- Code Assistant: user-guide/code-assistant.md
- Scheduled Monitor: user-guide/scheduled-monitor.md
- Simple Chat: user-guide/chat-simple.md
- Agents: user-guide/agents.md
- Channels & Connectors: user-guide/channels-and-connectors.md
- Tools: user-guide/tools.md
- Memory: user-guide/memory.md
- External MCP Servers: user-guide/mcp-external-servers.md
- Scheduler: user-guide/scheduler.md
- Telemetry: user-guide/telemetry.md
- Security: user-guide/security.md
- Leaderboard: leaderboard.md
- Roadmap: development/roadmap.md
+3 -1
View File
@@ -114,7 +114,9 @@ def _connect_source(registry: object, source: str, path: str = "") -> None:
console.print(f"[red]No OAuth provider configured for {source}.[/red]")
return
client_id, client_secret = get_client_credentials(provider)
creds = get_client_credentials(provider)
client_id = creds[0] if creds else ""
client_secret = creds[1] if creds else ""
if not client_id or not client_secret:
console.print(f"[cyan]First-time setup for {source}.[/cyan]")
+99
View File
@@ -257,6 +257,30 @@ def _do_download(engine: str, model: str, spec, console: Console) -> None:
default=None,
help="Remote engine host URL (e.g. http://192.168.1.50:11434).",
)
@click.option(
"--digest",
"enable_digest",
is_flag=True,
default=False,
help="Include Morning Digest config section.",
)
@click.option(
"--preset",
type=click.Choice(
[
"morning-digest-mac",
"morning-digest-linux",
"morning-digest-minimal",
"deep-research",
"code-assistant",
"scheduled-monitor",
"chat-simple",
],
case_sensitive=False,
),
default=None,
help="Use a pre-built starter config instead of generating one.",
)
def init(
force: bool,
config: Optional[Path],
@@ -265,6 +289,8 @@ def init(
no_download: bool = False,
skip_scan: bool = False,
host: Optional[str] = None,
enable_digest: bool = False,
preset: Optional[str] = None,
) -> None:
"""Detect hardware and generate ~/.openjarvis/config.toml."""
console = Console()
@@ -276,6 +302,42 @@ def init(
console.print("Use [bold]--force[/bold] to overwrite.")
raise SystemExit(1)
# Handle --preset: copy a starter config and return early
if preset:
examples_dir = (
Path(__file__).resolve().parents[2]
/ "configs"
/ "openjarvis"
/ "examples"
)
# Also check installed package location
if not examples_dir.exists():
examples_dir = (
Path(__file__).resolve().parents[3]
/ "configs"
/ "openjarvis"
/ "examples"
)
preset_path = examples_dir / f"{preset}.toml"
if not preset_path.exists():
console.print(f"[red]Preset '{preset}' not found.[/red]")
console.print(
f" Looked in: {examples_dir}"
)
raise SystemExit(1)
DEFAULT_CONFIG_DIR.mkdir(parents=True, exist_ok=True)
DEFAULT_CONFIG_PATH.write_text(preset_path.read_text())
console.print(
f"[green]Preset '{preset}' installed to "
f"{DEFAULT_CONFIG_PATH}[/green]"
)
console.print(
"\n Edit the config to customize, then run "
"[bold]jarvis doctor[/bold] to verify."
)
return
console.print("[bold]Detecting hardware...[/bold]")
hw = detect_hardware()
@@ -382,6 +444,43 @@ def init(
border_style="green",
)
)
# Append Morning Digest section if requested
if enable_digest:
digest_section = """
# ─── Morning Digest ─────────────────────────────────────────
[digest]
enabled = true
schedule = "0 7 * * *"
timezone = "America/Los_Angeles"
persona = "jarvis"
honorific = "sir"
tts_backend = "cartesia"
voice_id = "c8f7835e-28a3-4f0c-80d7-c1302ac62aae"
voice_speed = 1.2
sections = ["health", "messages", "calendar", "world"]
[digest.health]
sources = ["oura"]
[digest.messages]
sources = ["gmail", "google_tasks", "imessage"]
[digest.calendar]
sources = ["gcalendar"]
[digest.world]
sources = ["hackernews", "news_rss"]
"""
target = config if config else DEFAULT_CONFIG_PATH
existing = target.read_text()
target.write_text(existing + digest_section)
toml_content = target.read_text()
console.print(
"[green]Morning Digest config added.[/green] "
"Run [bold]jarvis connect gdrive[/bold] to connect "
"Google services, then [bold]jarvis digest --fresh[/bold]."
)
console.print("[green]Config written successfully.[/green]")
# Create default memory files (skip if they already exist)