mirror of
https://github.com/tiennm99/goclaw.git
synced 2026-07-12 17:04:21 +00:00
1ac08155b0
Makes the Stop button on the traces page actually stop running traces. Seven-phase implementation across provider HTTP, agent router, trace persistence, WS events, tool exec, i18n, and integration tests. - Provider HTTP+SSE ctx-aware: close socket on cancel via CtxBody wrapper - Router 2-phase abort: CAS state machine, 3s grace, force-mark fallback - Trace retry: 3 inline retries + 10-max retry queue, stale recovery 10min - trace.status WS event: real-time UI updates (invalidates query on receive) - Tool exec: process-group kill (SIGTERM→3s→SIGKILL), Rod page ctx watch - i18n: 6 abort toast variants in en/vi/zh - Integration: 9 scenarios, -race clean Fixes tenant-ctx loss in forceMarkTraceAborted and retry worker broadcast (caught by code-reviewer: C1/C2). Stale threshold intentionally 10min because start_time-based; last_span_at migration is a follow-up.
51 lines
1.7 KiB
Go
51 lines
1.7 KiB
Go
package cmd
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/nextlevelbuilder/goclaw/internal/agent"
|
|
"github.com/nextlevelbuilder/goclaw/internal/config"
|
|
"github.com/nextlevelbuilder/goclaw/internal/scheduler"
|
|
)
|
|
|
|
// makeSchedulerRunFunc creates the RunFunc for the scheduler.
|
|
// It extracts the agentID from the session key and routes to the correct agent loop.
|
|
func makeSchedulerRunFunc(agents *agent.Router, cfg *config.Config) scheduler.RunFunc {
|
|
return func(ctx context.Context, req agent.RunRequest) (*agent.RunResult, error) {
|
|
// Extract agentID from session key.
|
|
// Supported formats:
|
|
// agent:{agentId}:{rest}
|
|
// delegate:{sourceUUID8}:{targetAgentKey}:{delegationId} (legacy, kept for existing sessions)
|
|
agentID := cfg.ResolveDefaultAgentID()
|
|
if parts := strings.SplitN(req.SessionKey, ":", 4); len(parts) >= 2 {
|
|
switch parts[0] {
|
|
case "agent":
|
|
agentID = parts[1]
|
|
case "delegate":
|
|
if len(parts) >= 3 {
|
|
agentID = parts[2]
|
|
}
|
|
}
|
|
}
|
|
|
|
loop, err := agents.Get(ctx, agentID)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("agent %s not found: %w", agentID, err)
|
|
}
|
|
|
|
// Register run with the agent router so IsSessionBusy() and AbortRunsForSession()
|
|
// work correctly for inbound channel runs (Telegram DM intent classifier, /stop, etc.).
|
|
// The ctx from the scheduler is already cancellable; we create a child so the router's
|
|
// cancel func is independent from the scheduler's cancel func. Calling cancel twice is safe.
|
|
runCtx, cancel := context.WithCancel(ctx)
|
|
injectCh := agents.RegisterRun(runCtx, req.RunID, req.SessionKey, agentID, cancel)
|
|
defer agents.UnregisterRun(req.RunID)
|
|
defer cancel()
|
|
|
|
req.InjectCh = injectCh
|
|
return loop.Run(runCtx, req)
|
|
}
|
|
}
|