feat(frontend): make SSE idle timeout configurable via VIBE_TRADING_SSE_TIMEOUT (#157)
The frontend safety timeout was hardcoded at 90 s, causing false "Execution timed out" toasts for users running slow local models (e.g. Ollama on limited VRAM or CPU). - Backend: expose `sse_timeout_seconds` in `LLMSettingsResponse`, reading from `VIBE_TRADING_SSE_TIMEOUT` env var (default 90 s) - Frontend: fetch the value from `/settings/llm` on mount and use it instead of the hardcoded 90 000 ms constant - `.env.example`: document the new variable in the Agent Tuning section Co-authored-by: Sky <985369746@qq.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
f9bea768f4
commit
a8144e9acf
4 files changed
+15
-2
No files matched your search
@@ -139,3 +139,6 @@ TUSHARE_TOKEN=your-tushare-token
|
||||
# SUBAGENT_TIMEOUT=300
|
||||
# SUBAGENT_MAX_ITER=25
|
||||
# TOKEN_THRESHOLD=40000
|
||||
# Frontend SSE idle timeout in seconds before showing "Execution timed out".
|
||||
# Increase when using slow local models (e.g. Ollama on CPU/limited VRAM).
|
||||
# VIBE_TRADING_SSE_TIMEOUT=90
|
||||
@@ -170,6 +170,7 @@ class LLMSettingsResponse(BaseModel):
|
||||
timeout_seconds: int
|
||||
max_retries: int
|
||||
reasoning_effort: str
|
||||
sse_timeout_seconds: int
|
||||
env_path: str
|
||||
providers: List[LLMProviderOption]
|
||||
|
||||
@@ -926,6 +927,7 @@ def _build_llm_settings_response(values: Optional[Dict[str, str]] = None) -> LLM
|
||||
timeout_seconds=_coerce_int(env_values.get("TIMEOUT_SECONDS", "120"), 120),
|
||||
max_retries=_coerce_int(env_values.get("MAX_RETRIES", "2"), 2),
|
||||
reasoning_effort=env_values.get("LANGCHAIN_REASONING_EFFORT", "").strip().lower(),
|
||||
sse_timeout_seconds=_coerce_int(env_values.get("VIBE_TRADING_SSE_TIMEOUT", "90"), 90),
|
||||
env_path=_project_relative_path(ENV_PATH),
|
||||
providers=LLM_PROVIDERS,
|
||||
)
|
||||
|
||||
@@ -232,6 +232,7 @@ export interface LLMSettings {
|
||||
timeout_seconds: number;
|
||||
max_retries: number;
|
||||
reasoning_effort: string;
|
||||
sse_timeout_seconds: number;
|
||||
env_path: string;
|
||||
providers: LLMProviderOption[];
|
||||
}
|
||||
|
||||
@@ -212,6 +212,7 @@ export function Agent() {
|
||||
const pendingGoalSessionRef = useRef<string | null>(null);
|
||||
const [showScrollBtn, setShowScrollBtn] = useState(false);
|
||||
const lastEventRef = useRef(0);
|
||||
const sseTimeoutMsRef = useRef(90_000);
|
||||
|
||||
/* tool_progress coalescing — keep latest payload per-tool, flush once per rAF. */
|
||||
const pendingProgressRef = useRef<Map<string, NonNullable<ToolCallEntry["progress"]>>>(new Map());
|
||||
@@ -709,11 +710,17 @@ export function Agent() {
|
||||
|
||||
useEffect(() => () => doDisconnect(), [doDisconnect]);
|
||||
|
||||
/* Safety timeout: if streaming but no SSE event for 90s, reset to idle */
|
||||
useEffect(() => {
|
||||
api.getLLMSettings().then((s) => {
|
||||
sseTimeoutMsRef.current = s.sse_timeout_seconds * 1000;
|
||||
}).catch(() => {});
|
||||
}, []);
|
||||
|
||||
/* Safety timeout: if streaming but no SSE event for sseTimeoutMsRef.current ms, reset to idle */
|
||||
useEffect(() => {
|
||||
if (status !== "streaming") return;
|
||||
const timer = setInterval(() => {
|
||||
if (lastEventRef.current && Date.now() - lastEventRef.current > 90_000 && act().status === "streaming") {
|
||||
if (lastEventRef.current && Date.now() - lastEventRef.current > sseTimeoutMsRef.current && act().status === "streaming") {
|
||||
act().setStatus("idle");
|
||||
toast.warning("Execution timed out, automatically stopped");
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user