Anthropic/LangChain streams tool arguments as JSON string deltas in
chunk.tool_call_chunks (not chunk.tool_calls which has empty args dict).
Collect and accumulate both sources, then merge by tool_call_id.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Anthropic Claude streaming sends tool call chunks where the first chunk
has the name but empty args dict, and subsequent chunks have args but
no name. The previous deduplication only kept the first entry with a
name, discarding all the args. Now we accumulate: merge dict args and
concatenate string args (for OpenAI) across all chunks per tool_call_id.
Fixes "No code provided" error when code_interpreter is called.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add /api/v1/code-interpreter/files/{session_id}/{file_id} proxy endpoint
so the browser can download files from the internal LibreCodeInterpreter
- Normalize file objects in CodeInterpreterTool to consistent {id, name, session_id}
shape regardless of which field names LibreCodeInterpreter returns
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Previously sync_agent was called without db in all 3 agent endpoints,
so usage_stats was None and tokens/conversations/unique_users were never
sent to the collector (showing N/A in AgentHub). Now sync_agent opens
its own AsyncSession when no db is passed, avoiding the closed
request-scoped session issue.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
/exec/programmatic is for agentic tool-calling and returns files:[].
/exec uses the runner with savefig/open keyword detection and uploads
files to MinIO. Response is streaming with whitespace keepalive then
JSON body — parse with resp.text.strip().
Also include download URLs in tool display output.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
wrapper_cmd mounts tmpfs over /app/ssl to hide SSL certs from sandboxes,
but the directory didn't exist so mount failed silently, killing the entire
sh -c chain before REPL could start. tmpfs: in compose creates it.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
SYS_ADMIN + seccomp:unconfined was insufficient; nsjail needs to mount
/proc in new mount namespaces which requires full privileged mode.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Seccomp filter was blocking mount/unshare/pivot_root syscalls required by
nsjail to build sandbox mount tree, causing all REPL processes to fail.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Terminal button in chat input bar toggles code interpreter per-message
- Backend accepts &code_interpreter=true query param to force-enable the tool
- Works for any agent, regardless of enable_code_interpreter setting
- File attach button now uses supportsFileUpload prop (works for any agent)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
LLM wasn't calling the tool because it didn't know it had code execution
capability. Now appends an explicit instruction whenever enable_code_interpreter
is True on the agent.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
CSS doesn't load correctly through Apache reverse proxy due to absolute
static asset paths. Direct external link is more reliable.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
**Phase 1 — Agent Usage Sync to AgentHub Collector**
- Add agent_usage service: per-agent stats (messages, tokens, conversations, unique users, first/last used)
- Collector sync now includes usage data in payload; sync_agent accepts optional db session
- Celery beat task runs every 6h to sync all active agents with fresh usage stats
**Phase 2 — LibreCodeInterpreter Integration**
- Add code-interpreter, redis, minio services to docker-compose.prod.yml
- CodeInterpreterTool (BaseTool): sandboxed execution via /exec, 13 languages, Python session persistence via conversation_id
- ToolContext extended with conversation_id and agent_slug
- enable_code_interpreter boolean on Agent model (migration 027), tool seeded in tool_definitions (migration 026)
- Code interpreter auto-injected into agent tools when enabled
- Frontend: CodeExecutionResult component with terminal-style stdout/stderr/files rendering
**Phase 3 — Agent API Endpoints**
- GET /api/v1/agents/{slug}/analytics — per-agent usage stats + daily time series
- POST /api/v1/agents/{slug}/execute — synchronous programmatic agent execution (non-SSE)
- Sub-routes registered before /{slug} to avoid FastAPI route conflict
**Phase 4 — Fix Department & Region RAG Scoping**
- Department filter now OR-includes global (null department) docs, matching region filter behaviour
- retriever.search_documents/retrieve_and_prepare/query accept department_ids/region_codes lists
- MatchAny used for multi-value Qdrant filters; chat.py passes full arrays from knowledge_scope
- Admin PATCH /users/{id} now validates region_code against the regions table
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- New service: app/services/agent_collector.py
- Maps Nexus Agent fields to collector API payload
- Marks agents with tool="Oliver Nexus", tags=["nexus","oliver",...]
- Skips private non-system agents
- Fire-and-forget via asyncio.create_task, errors only logged
- Hooked into agents.py: create_agent, update_agent, update_agent_status
each trigger sync_agent() after successful DB commit
- scripts/sync_agents_to_collector.py — one-shot bulk sync of all
active agents for initial population of the collector
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Pass announcements state from sidebar down to WhatsNewModal as props
to eliminate duplicate useAnnouncements() instance and API call
- Snapshot unread items before calling markAllRead so they remain
visible after the readIds state updates
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- graph_consent.py: filter offline_access/openid/profile before passing to MSAL
(MSAL reserves these and throws ValueError if supplied as user scopes)
- graph_consent.py: return 501 with clear message when ENTRA_CLIENT_SECRET not set
- graph_token_manager.py: include client_secret in refresh_token request (required
for confidential client); strip openid/profile from refresh scope; ensure
offline_access is present to receive a new refresh_token
- Add /auth/graph-callback page: handles Microsoft redirect after consent,
POSTs code to backend, notifies opener window on success, then closes popup
- app-shell.tsx: exclude /auth/graph-callback from sidebar layout
Requires ENTRA_CLIENT_SECRET and a web platform on the Azure app registration.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace root redirect with a full home page for authenticated users
- Greeting by time of day with user's display name
- Quick Start cards linking to RAG, Assistant, Agents, and User Guide
- What's New section pulling from announcements API with unread indicators
- Platform Features panel highlighting key capabilities
- Logo in sidebar now navigates to home page on click
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Root cause: CreateAgentTool/ListAgentsTool were registered in-memory at
startup but had no rows in tool_definitions table. chat.py resolves tools
via get_enabled_tools(mode, db) which queries tool_definitions — so the
tools were invisible to the assistant agent.
- Migration 025: INSERT create_agent + list_agents into tool_definitions
with is_enabled=true, allowed_modes=["assistant"]
- types/index.ts: add tool_ids to AgentListItem (fixes TS build error
in agents/page.tsx line 97)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- New /agents page: beautiful card grid with icon, category badge,
capability chips (RAG, M365 Tools, File Upload), description, Open Chat CTA
- Layout: System Assistants (pinned top) → Your Agents → Templates
- Search bar + category filter (All / General / HR / Finance / IT / Operations)
- Empty state with Create Agent CTA; Admin Panel shortcut for managers
- Sidebar: replace full agent list with system bots only + single
"Agent Mode" button showing count of custom agents → /agents
- Remove AgentPickerModal from sidebar (now lives on /agents page)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Remove unused lucide imports: Users, Settings, Zap, Eye, Edit3, Lock, Unlock, Star, Copy
- Escape all quotes and apostrophes in JSX text nodes (" / ')
- Add key props to <span> elements used as table cell content
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- New /user-guide Next.js page with sticky TOC, Cmd+K search, section
highlighting via IntersectionObserver
- 11 sections covering all features: Overview, Login, Navigation, Process
Helper, Personal Assistant, AI Agents (all 4 creation paths), Knowledge
Base, Language, Admin Panel, Tips, Troubleshooting
- Role-based content (User / Agent Manager / Content Manager / Super Admin)
clearly marked with colour badges throughout
- Section 6.9 "Available templates" fetches live from /agents/templates API
so the list stays current as admins add or remove templates
- Sidebar "Help" button now navigates to /user-guide instead of opening PDF
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Streaming produces incomplete chunks (empty name/id). Previously assistant_msg
was built from raw tool_calls_in_response, causing Anthropic to reject with
'tool_use.name: String should have at least 1 character'.
Now dedup + parse happens first; assistant_msg is built from the validated
parsed_calls list so only complete tool_use blocks reach the API.
Also return early if all chunks were incomplete (no valid calls).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- agent_builder.py: fix execute(self, arguments, context) signature on
CreateAgentTool and ListAgentsTool to match BaseTool contract; was
(self, context, **kwargs) causing "takes 2 positional args but 3 given"
- llm.py: ensure tool call IDs are non-empty before building AIMessage
so Anthropic API doesn't reject with "tool_use.id: valid string required"
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1. _should_use_tools classifier didn't know about agent management →
extended prompt to include 'creating or managing AI agents'
2. Assistant system prompt didn't tell Claude about create_agent tool →
migration 023 updates DB prompt with explicit instructions
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Right panel (360px) toggles via SlidersHorizontal button in chat header.
Shows full agent config: name, description, category, instructions,
welcome message, suggested prompts, model, capabilities, visibility.
Editable for own/managed agents; read-only + Fork for system agents.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
OpenAI: gpt-5.2 only
Anthropic: claude-sonnet-4-6, claude-opus-4-6, claude-haiku-4-5-20251001
Google: gemini-3.1-pro-preview only
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Added: AI provider/model selection, welcome message, suggested prompts chip list,
RAG toggle, file upload toggle. Agents are still created as private.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Agents are now dynamic — any slug can be passed as mode.
Updated: chat-input, chat-list, chat-message, message-feedback, useChatStore.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace react-hook-form with useState, shadcn Select with native <select>,
and Switch with inline toggle buttons. No new packages required.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Modal now marks all as read on open and only shows new items;
once seen they never reappear (no more grayed-out clutter)
- Empty state shows "You're all caught up!" message
- Migration 021: seeds two announcements — one for users (rate answers)
and one for admins/content managers (feedback dashboard)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>