Fixes recommend_model() returning empty string on Apple Silicon
when MLX is the recommended engine. Also adds gguf_file and
mlx_repo download metadata, and estimated_download_gb helper.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 tasks with TDD steps, covering model catalog fixes, multi-engine
pull, interactive download in init, privacy scanner, and CLI registration.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Covers two features based on user feedback:
1. Interactive model download in `jarvis init` with MLX catalog fix
2. New `jarvis scan` privacy environment audit command
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Eight tool modules (file_write, apply_patch, git_tool, db_query,
pdf_tool, image_tool, audio_tool, knowledge_tools) were missing from
openjarvis/tools/__init__.py. Their @ToolRegistry.register() decorators
never fired, so the /v1/tools endpoint never returned them and the
web UI agent wizard showed an incomplete tool list.
Add the missing imports and a regression test that checks all expected
tool names are in the registry after package import.
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add query complexity analyzer with CLI and UI integration
Classify incoming queries by difficulty (trivial→very_complex) to
suggest appropriate token budgets for local vs. cloud routing.
- Add score_complexity() with weighted signals (length, code, math,
reasoning, multi-step, creative) and token tier mapping
- Wire into `jarvis ask`: auto-suggest max_tokens when not set by user,
show complexity in --profile output, log at DEBUG level
- Add complexity metadata to /v1/chat/completions API response
- Display complexity tier and score in frontend XRayFooter
- Extend RoutingContext with complexity_score, suggested_max_tokens,
has_reasoning fields
- Update HeuristicRouter to route on complexity_score instead of
raw query_length
- Remove duplicated regex patterns from router.py (use complexity
module as single source of truth)
- Add 30 unit tests for complexity module
- Fix existing router tests for new complexity-based routing
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: pass temperature and max_tokens from UI settings to backend
The settings page stores temperature and max_tokens in the frontend
store, but these values were never included in the chat API request.
The backend Pydantic model defaults max_tokens to 1024 when the field
is absent, which is too low for thinking models like qwen3.5 — they
consume all tokens on reasoning and return empty content.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: pass UI settings to backend and auto-bump max_tokens from complexity
- Pass temperature and max_tokens from frontend Settings store to the
backend API (cherry-picked from fix/ui-max-tokens-passthrough)
- Server-side: bump max_tokens when the complexity analyzer suggests a
higher budget (e.g. for thinking models on complex queries), never
reduce below the client-requested value
- Fixes empty responses with thinking models (e.g. qwen3.5) that
consumed all tokens on internal reasoning
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: raise token budget tiers to prevent empty responses on thinking models
Double all tier budgets (trivial: 512→1024, simple: 1024→2048, etc.)
so that thinking models like qwen3.5 have enough headroom for internal
chain-of-thought plus visible output, even on simple queries.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: CI lint and test failures
- Break long lines in routes.py to satisfy 88-char limit (E501)
- Add intelligence.max_tokens and temperature to mocked config in
test_ask_router.py so complexity analyzer can compare against int
instead of MagicMock
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: line too long in test_complexity.py (E501)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add `stream: bool` parameter to `POST /v1/managed-agents/{id}/messages`.
When `stream=true`, the agent processes the message synchronously and
returns an SSE stream (OpenAI-compatible format) with token-by-token
response, tool result events, and usage metadata.
This enables real-time voice assistants and chat UIs to receive agent
responses as they are generated, rather than polling for completion.
- Extend SendMessageRequest with `stream` field (default: false)
- Add _stream_managed_agent() helper using asyncio.to_thread()
- Build AgentContext from conversation history for multi-turn support
- Emit tool_results as named SSE events
- Persist agent response in DB after streaming completes
- Add 6 new tests covering streaming behavior
- Update agents.md documentation with streaming examples
SystemBuilder.build() constructed AgentExecutor without a trace_store,
so traces were never recorded even when config.traces.enabled = true.
The traces.enabled flag was parsed but never read during executor
construction.
Now reads config.traces.enabled and creates a TraceStore instance
that is passed to AgentExecutor, enabling trace recording for
jarvis agents ask/run and the agent scheduler daemon.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: nvidia gpu config for docker
* refactor: split NVIDIA GPU support into compose override
Address review feedback:
- Revert --engine ollama from base Dockerfile CMD (breaks non-Ollama users)
- Keep bookworm pin and OLLAMA_HOST fix in base config
- Move GPU-specific config (/proc, /sys mounts, deploy.resources.reservations)
into new docker-compose.gpu.nvidia.yml override, matching the existing ROCm
pattern (docker-compose.gpu.rocm.yml)
- Restore Ollama port to standard 11434
- Remove commented-out GPU blocks from base docker-compose.yml
- Add Ollama healthcheck with depends_on condition to base compose
- Remove run.sh from repo root
- Rewrite README Docker section to document CPU, NVIDIA, and ROCm patterns
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Jon Saad-Falcon <41205309+jonsaadfalcon@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add CLI commands: config, registry, tool
* fix: address review feedback on CLI config/registry/tool commands
- Replace non-existent `create_config_template` with `generate_default_toml`
to fix ImportError when config file is missing
- Deduplicate registry maps into shared `_load_registry_map()` helper
- Remove dead `_get_registry_class()` function and its tests
- Route JSON output to stdout for pipeability (`jarvis config show json | jq`)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Jon Saad-Falcon <41205309+jonsaadfalcon@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The energy_wh_saved and flops_saved values were orders of magnitude too
high because a scaling factor that grows linearly with N was applied to
the energy calculation, making it scale as O(N³) instead of O(N²).
Replace the buggy scale-factor approach with a direct FLOP-to-energy
conversion using each provider's per-token constants. Add regression
tests to prevent recurrence.
Closes#95
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add MiniMax as cloud inference provider
Add MiniMax M2.5 and M2.5-highspeed as a 5th cloud provider alongside
OpenAI, Anthropic, Google, and OpenRouter. Uses the OpenAI-compatible
API at api.minimax.io/v1 via the existing openai SDK dependency.
Changes:
- Add MiniMax client init, generate, and streaming in CloudEngine
- Add MiniMax models to model catalog with correct pricing
- Add MINIMAX_API_KEY environment variable support
- Add temperature clamping (0.01-1.0) per MiniMax API constraints
- Add 19 unit tests and 3 integration tests
- Update docs and README with MiniMax provider info
* feat: upgrade MiniMax default model to M2.7
- Add MiniMax-M2.7 and MiniMax-M2.7-highspeed to model list
- Set MiniMax-M2.7 as default model (first in list)
- Keep all previous models (M2.5, M2.5-highspeed) as alternatives
- Update pricing table with M2.7 entries
- Update model catalog with M2.7 specs
- Update docs to list all available MiniMax models
- Update unit tests (23 passing) and integration tests (3 passing)
---------
Co-authored-by: Octopus <octo-patch@users.noreply.github.com>
- Catch any Exception from Tavily (not just specific error types)
- Fall back to DuckDuckGo for any error, making the tool more robust
- Fix test mocks to use builtins.__import__ for proper local import mocking
- Simplify test_execute_tavily_error to test generic exception handling
When Tavily API is unavailable (no API key, import error, or API error),
the web_search tool now falls back to DuckDuckGo search instead of
failing. This ensures the tool always works for users without a
Tavily API key.
- Add DuckDuckGo search as fallback using ddgs package
- Catch specific Tavily exceptions (MissingAPIKeyError, InvalidAPIKeyError,
ForbiddenError, UsageLimitExceededError, TimeoutError, BadRequestError)
- Add logger.debug calls to log when falling back to DuckDuckGo
- Use ddgs instead of deprecated duckduckgo-search package name
- Add test for DuckDuckGo fallback result formatting
- Simplify test mocking to use consistent monkeypatch patterns
Closes#81
- Move "Current Focus Areas" and "How to Get Involved" to top of roadmap
- Remove Version History section entirely
- Fix "take" workflow: clarify that claiming happens on GitHub issues,
with link to create new issues if none exists
- Remove Contributing Guide from MkDocs nav (linked from roadmap instead)
- Link to CONTRIBUTING.md on GitHub from "How to Get Involved" section
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Reorganize roadmap around the 5 workstreams: Continuous Operators,
Mobile & Messaging, Secure Cloud Collaboration, Tutorials, Hardware
- Add concrete "Where you can help" tables with maturity tags and
good-first-issue markers under each workstream
- Change "GRPO training from trace data" to "Post-training data"
- Fix 404 link: CONTRIBUTING.md link now points to GitHub, not docs site
- Remove !!! tip admonition from docs/development/contributing.md
- Preserve version history in collapsible section
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add root CONTRIBUTING.md with incentives (paper acknowledgment, Mac Mini
giveaway), contribution tiers, PR process, and maintainership path
- Add CODE_OF_CONDUCT.md (Contributor Covenant v2.1)
- Add .pre-commit-config.yaml with ruff lint + format hooks
- Add GitHub issue templates (bug report, feature request, new eval dataset)
- Add PR template with test/lint/format checklist
- Rewrite docs roadmap with GitHub Projects structure, current focus areas,
and collapsible version history
- Remove Development section from MkDocs nav; replace with top-level Roadmap tab
- Delete changelog, extending docs (consolidated into CONTRIBUTING.md)
- Delete root ROADMAP.md (content now lives in docs site)
- Add pre-commit to dev extras in pyproject.toml
- Add Roadmap link to README
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Reviewed and tested: zero new test failures vs main, Rust tests all pass (7/7 including 2 new). Added debug logging for memory injection errors and cleaned up .gitignore.
- Remove openjarvis-bugfix-spec-v2.md from .gitignore (not a general pattern)
- Replace bare `except: pass` with debug logging in routes.py memory injection
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add _annotate_anthropic_cache helper that annotates system messages
with cache_control for Anthropic prompt caching.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add optional prompt_builder parameter to BaseAgent. When provided,
_build_messages() uses builder.build() output instead of raw system_prompt.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The web UI chat endpoint and managed agent executor both skipped
memory context injection entirely:
- serve.py never created a memory backend
- app.py received config but never stored it on app.state
- executor.py never queried the FTS5 document store
Now all three entry points (CLI, server, agents) inject retrieved
context from the indexed knowledge base.
- Add porter stemming to FTS5 tokenizer (tokenize='porter unicode61')
so plurals like 'medications' match 'Medication'
- Strip punctuation from FTS5 queries so question marks don't break MATCH
- Expand tilde (~) in db_path before opening SQLite connection
- Remove 'id' from FTS5 columns (UUIDs shouldn't be full-text indexed)
- Add memory context injection to server chat_completions route
(routes.py had no memory integration - UI chat was never grounded)
- Fix agent name-to-ID resolution in agent_cmd.py (foreign key error)
- Align Python SQLiteMemory schema with Rust backend