Adds `anthropic_api` model type so users can authenticate with a direct
Anthropic API key instead of (or alongside) the CLI OAuth session.
- model_registry.py: `anthropic_api` type; `save/get/remove_anthropic_api_key()`
mirroring the Google account pattern; `save_cloud_model()` now picks type
based on credential type (cli → claude_cli, api_key → anthropic_api);
`_resolve_model()` merges api_key from the credential entry
- llm_client.py: `_anthropic_api()` backend (AsyncAnthropic SDK); dispatch
and fallback wiring; usage tracking
- routers/local_llm.py: Anthropic API key management routes
(POST /settings/local/anthropic-key, /anthropic-key/{id}/remove);
`anthropic_api` badge and edit-form credential selector
- static/local_llm.html: Anthropic Cloud Provider block now shows API key
management (add/remove); Add Model → Anthropic tab has credential selector
(CLI vs API key)
- requirements.txt: enable anthropic>=0.40.0
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace free-form reasoning_budget_tokens number input with a 5-level
select in both the edit form (local_llm.py) and add-model form
(local_llm.html). Values: 0 / 1024 / 4096 / 8192 / 32768 tokens.
Edit form pre-selects the stored value.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- reasoning_budget_tokens: optional int field on local_openai models;
when set, injects {"reasoning": {"budget_tokens": N}} via extra_body
into every OpenRouter API call (both tool-loop and confirmation-gate
rounds). Field exposed in the model edit form in Settings.
- session name moved from standalone full-row div between #messages
and #input-area into the persona-switcher block in the header, as a
third dim line under "Cortex · Local". Collapses when empty via
:empty CSS. No JS changes required.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- inject_mode: per-role toggle (parallel to inject_datetime) gates the
"Current mode: Off The Record" line in the system prompt; wired through
model_registry, context_loader, chat router, orchestrator router, and
local_llm settings UI
- OTR orchestrator fix: OrchestrateRequest now carries off_record;
_finalize_job stores it per message and gates log_turn on it; JS
orchestrate payload sends off_record correctly
- Per-message hover metadata: removed always-visible .model-tag; replaced
with .msg-meta strip in the action bar (hover-only); shows model label,
host, fallback indicator, and OTR badge; stored in session JSON
- Send/stop button tooltip: shows role + model and (when tools on)
separate orchestrator model + engine label; live elapsed timer on stop
button via startRunTimer/stopRunTimer
- OrchestratorResult.backend_label: new field; openai_orchestrator fills
it; finalize_job propagates it to job dict and session messages
- GET /backend: exposes orchestrator_model label so the frontend tooltip
can show both models separately
- TODO: session delete confirmation added
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds a synchronous sub-agent spawning tool that lets the orchestrator
delegate tasks to a specific role's model and tool set.
- cortex/tools/agents.py: spawn_agent(task, role, tier, timeout, max_rounds)
- Supports local_openai and gemini_api model types
- Per-host asyncio semaphore (keyed by host_id or model type)
- asyncio.wait_for() enforces timeout; admin-only tool
- cortex/model_registry.py: max_concurrent field in host schema (default 3,
clamped 1-20); backfilled on _normalize() for existing hosts
- cortex/routers/local_llm.py + local_llm.html: "Max parallel" number input
in host add/edit forms
- cortex/tools/__init__.py: spawn_agent registered in TOOL_CATEGORIES["Agents"],
_CALLABLES, TOOL_ROLES (admin), and _ALL_DECLARATIONS
- Docs: TOOLS.md count 44→45, spawn_agent section; HELP.md tool table updated;
ARCH__FUTURE.md Round 2 completed items; TODO__Agents.md spawn_agent checked;
CLAUDE.md tool count and list updated
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Each role can now disable the current date/time header injected into the
system prompt. Default is true (all existing roles unchanged). Useful for
pure processing roles (summarizer, classifier, translator) where temporal
context is irrelevant or could cause unexpected model behavior.
Changes:
- model_registry: set_role_config/get_role_config gain inject_datetime field
- context_loader: load_context gains inject_datetime param (default True)
- orchestrator router: passes inject_datetime from role_cfg to load_context
- local_llm router: reads inject_datetime from POST body, passes to registry;
role_config_data_js includes the field
- local_llm.html: checkbox in role config panel; populate on open, save on submit
Session logs still timestamp every turn (HH:MM header in YYYY-MM-DD.md files)
regardless of this setting — the toggle only affects the system prompt header.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
tools/__init__.py shrinks from 1,137 → 250 lines. Each domain file now
owns both its callables and its FunctionDeclarations (DECLARATIONS list),
so adding a new tool only touches one file.
New TOOL_CATEGORIES dict exported from __init__ — used by the UI for
grouped tool checkboxes.
Role config UI (Settings → Model Registry → Role Assignments):
- ⚙ button per role expands an inline configure panel
- Textarea for system_append (injected into system prompt for this role)
- Grouped checkboxes for tool allow-list (all checked = no restriction)
- POST /api/models/role-config saves both fields; updates ROLE_CONFIG_DATA
in-page so re-open reflects current state without a page reload
Backend:
- model_registry.set_role_config() writes system_append + tools to registry
- TOOL_CATEGORIES exported from tools/__init__ for UI rendering
- TOOLS.md header updated: 30 → 39 tools (ae_journal_* and cortex_* additions)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Inline edit form per model row (label, model name/ID, host/account, context, tags)
- Fetch models button in edit form for local models — same live-picker UX as Add Model
- POST /settings/local/models/{id}/edit route in local_llm.py
- Admin role badge (ADMIN/USER pill) in Account Settings page
- HELP.md updated: new tools table with admin/confirm markers, PWA install section
- TODO updated: tool expansions marked done, distill review and Unsloth resolved,
role-based access and admin badge added to completed
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds cloud provider management to /settings/models:
- Google Accounts section: add/remove Gemini API keys with labels
- Add Model form: provider tabs (Local / Google / Anthropic) with
catalog dropdowns that auto-fill label and context_k
- Provider badges on model rows (Anthropic / Google / Local)
- /settings/local now redirects to /settings/models (canonical URL)
- save_cloud_model() in model_registry for Anthropic/Google entries
- Distill role migration restored in _migrate_from_local_llm
- Test fixes: version assertions updated to V2
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds host_type ("openwebui" | "openai") to the host schema so Cortex can
talk to both Open WebUI/Ollama and OpenRouter/standard-OpenAI endpoints.
Path differences per type:
openwebui (default): /api/chat/completions, /api/models
openai: /chat/completions, /models
model_registry.py:
- host_type added to host schema (default "openwebui", backward compat)
- save_host() accepts host_type parameter
- _resolve_model() passes host_type through with the merged host fields
llm_client._local():
- Reads host_type from resolved model_cfg
- Selects correct chat completions path accordingly
routers/local_llm.py:
- save_host route accepts host_type form field
- fetch-models uses /models for openai type, /api/models for openwebui
- Existing host rows show type selector pre-filled from stored value
local_llm.html:
- "Add host" form includes type selector
To use OpenRouter:
- Add host: URL = https://openrouter.ai/api/v1, Type = OpenAI-compatible
- API key from openrouter.ai (store in .env or model_registry.json only)
- Fetch models or add manually (e.g. anthropic/claude-sonnet-4-5-20251022)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replaces the single-host local model settings page with a full model
registry interface at /settings/local.
Hosts section:
- List existing hosts with inline edit + save + remove
- Collapsible "Add host" form
- Per-host "Fetch models" button
Models section:
- List all models with label, model name, host, context_k badge, tags
- Remove button
Add Model section:
- Host dropdown, label, model name, context_k, tags (comma-separated)
- "Fetch models from host" with auto-fill picker
Role Assignments section:
- One row per defined role (chat, orchestrator, distill, coder, research)
- Primary + backup_1 + backup_2 dropdowns per role
- Dropdowns pre-filled from registry on load
- AJAX save on change (POST /api/models/role) with toast confirmation
- Built-in models (claude_cli, gemini_cli, gemini_api) always available in dropdowns
Backend:
- All user_settings references replaced with model_registry
- host/{id}/remove route added
- fetch-models now accepts host_id query param
- POST /api/models/role for AJAX role assignment
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>