AI Assistant

AI Assistant — Ask & Refresh

The dashboard floating widget lets operators ask grounded questions about open and closed trades, strategies, config, and live market state, and refresh AI market analysis on demand. It is read-only and advisory: it may suggest existing operator commands (e.g. /close_smart <tag>) but never places or closes orders — confirm suggested actions in Telegram.

Backed by arb_bot/ai/assistant.py (TradingAssistant) and arb_bot/ai/context.py (read-only context pack), using the same headless codex exec transport as the prediction engine. Every answer is grounded in the provided context pack — the model never fabricates numbers. Chat turns are persisted to ai_chat_messages. Endpoints: POST /api/ai/ask, POST /api/ai/ask/stream, POST /api/ai/refresh, GET /api/ai/chat/history.

Streaming chat

POST /api/ai/ask/stream answers a turn as Server-Sent Events (text/event-stream): each chunk is a data: {"token": ...} event, terminated by data: [DONE]; a failed turn emits data: {"error": ...}. The HTTP providers (OpenCodeGoProvider, MiniMaxProvider, OpenRouterProvider) stream token-by-token via complete_stream; when the resolved chain is codex-only the endpoint falls back to a single-chunk batch response. The same per-tier call caps apply as on POST /api/ai/ask.

Per-message model picker

The chat composer exposes a per-message model dropdown populated from the models field on the opencode-go catalog entry in GET /api/portfolio/ai-providers/catalog (see AI Provider Settings). The chosen model rides the optional AskRequest.model field on both /api/ai/ask and /api/ai/ask/stream.

Tiered call caps

The assistant resolves its tier via Config.AI_FEATURE_TIERS["assistant"]. On the fast tier the caps are AI_ASSISTANT_FAST_SESSION_CALL_CAP (default 100) and AI_ASSISTANT_FAST_DAILY_CALL_CAP (default 200); on premium the standard AI_ASSISTANT_SESSION_CALL_CAP (20) and AI_ASSISTANT_DAILY_CALL_CAP (50) apply. Batch and streaming endpoints share this accounting.