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.