mirror of
https://github.com/NoFxAiOS/nofx.git
synced 2026-07-15 00:36:56 +08:00
fix: context propagation in LLM calls, SSE error handling, security hardening
- Propagate request context through MCP client (Request.Ctx field) — Client disconnects now cancel in-flight LLM API calls (both streaming and non-streaming) — Prevents wasted LLM tokens when user navigates away mid-response - proxyBinance: use http.NewRequestWithContext for context-aware upstream calls — Client disconnects cancel Binance proxy requests — Distinguishes client cancellation from upstream failures - Fix SSE parse bug in AgentChatPage: catch block was swallowing error events — throw new Error(data) for 'error' events was caught by the same try/catch — Now parse JSON separately, then handle events outside try/catch - Add io.LimitReader to Hyperliquid coins.go JSON decoder (4MB limit) - Use safe.ReadAllLimited in batch ticker handler for consistency - Sanitize URL validation error in handler_ai_model.go (was leaking raw error) - Cache agent tool definitions (built once, reused per message) - Sort trade history by exit time for consistent ordering
This commit is contained in:
@@ -503,6 +503,10 @@ func (client *Client) callWithRequestFull(req *Request) (*LLMResponse, error) {
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create request: %w", err)
|
||||
}
|
||||
// Propagate request context so client disconnects cancel in-flight LLM calls
|
||||
if req.Ctx != nil {
|
||||
httpReq = httpReq.WithContext(req.Ctx)
|
||||
}
|
||||
|
||||
resp, err := client.HTTPClient.Do(httpReq)
|
||||
if err != nil {
|
||||
@@ -541,6 +545,10 @@ func (client *Client) callWithRequest(req *Request) (string, error) {
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to create request: %w", err)
|
||||
}
|
||||
// Propagate request context so client disconnects cancel in-flight LLM calls
|
||||
if req.Ctx != nil {
|
||||
httpReq = httpReq.WithContext(req.Ctx)
|
||||
}
|
||||
|
||||
resp, err := client.HTTPClient.Do(httpReq)
|
||||
if err != nil {
|
||||
@@ -686,8 +694,13 @@ func (client *Client) CallWithRequestStream(req *Request, onChunk func(string))
|
||||
|
||||
// Idle-timeout watchdog: cancel the request if no SSE line arrives for 60 seconds.
|
||||
// This breaks the scanner out of an indefinitely blocking Read on a hung connection.
|
||||
// Use request's Ctx as parent so client disconnects propagate cancellation.
|
||||
const idleTimeout = 60 * time.Second
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
parentCtx := req.Ctx
|
||||
if parentCtx == nil {
|
||||
parentCtx = context.Background()
|
||||
}
|
||||
ctx, cancel := context.WithCancel(parentCtx)
|
||||
defer cancel()
|
||||
resetCh := make(chan struct{}, 1)
|
||||
safe.GoNamed("mcp-stream-idle-watchdog", func() {
|
||||
|
||||
Reference in New Issue
Block a user