mirror of
https://github.com/tiennm99/goclaw.git
synced 2026-07-31 18:20:25 +00:00
Add 16 new event constants and typed payload structs for full WS visibility into team agent operations. Enrich AgentEvent with delegation and routing context (delegationId, teamId, parentAgentId, userId, channel, chatId). Emit thinking/chunk events for non-streaming runs so delegate member agents also produce WS events. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
71 lines
2.6 KiB
Go
71 lines
2.6 KiB
Go
package tools
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"log/slog"
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
|
|
"github.com/nextlevelbuilder/goclaw/internal/store"
|
|
"github.com/nextlevelbuilder/goclaw/internal/tracing"
|
|
"github.com/nextlevelbuilder/goclaw/pkg/protocol"
|
|
)
|
|
|
|
// Delegate executes a synchronous delegation to another agent.
|
|
func (dm *DelegateManager) Delegate(ctx context.Context, opts DelegateOpts) (*DelegateResult, error) {
|
|
task, _, err := dm.prepareDelegation(ctx, opts, "sync")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
dm.active.Store(task.ID, task)
|
|
defer func() {
|
|
now := time.Now()
|
|
task.CompletedAt = &now
|
|
dm.active.Delete(task.ID)
|
|
}()
|
|
|
|
dm.injectDependencyResults(ctx, &opts)
|
|
message := buildDelegateMessage(opts)
|
|
dm.emitDelegationEvent(protocol.EventDelegationStarted, task)
|
|
slog.Info("delegation started", "id", task.ID, "target", opts.TargetAgentKey, "mode", "sync")
|
|
|
|
// Propagate parent trace ID so the delegate trace links back.
|
|
// Clear senderID — delegations are system-initiated, the delegate agent
|
|
// should not inherit the caller's group writer permissions (the delegate
|
|
// agent has its own writer list, and would incorrectly deny writes).
|
|
delegateCtx := store.WithSenderID(ctx, "")
|
|
if parentTraceID := tracing.TraceIDFromContext(ctx); parentTraceID != uuid.Nil {
|
|
delegateCtx = tracing.WithDelegateParentTraceID(delegateCtx, parentTraceID)
|
|
}
|
|
|
|
startTime := time.Now()
|
|
result, err := dm.runAgent(delegateCtx, opts.TargetAgentKey, dm.buildRunRequest(task, message))
|
|
duration := time.Since(startTime)
|
|
if err != nil {
|
|
task.Status = "failed"
|
|
dm.emitDelegationEventWithError(task, err)
|
|
dm.saveDelegationHistory(task, "", err, duration)
|
|
return nil, fmt.Errorf("delegation to %q failed: %w", opts.TargetAgentKey, err)
|
|
}
|
|
|
|
// Apply quality gates before marking completed.
|
|
if result, err = dm.applyQualityGates(delegateCtx, task, opts, result); err != nil {
|
|
task.Status = "failed"
|
|
dm.emitDelegationEventWithError(task, err)
|
|
dm.saveDelegationHistory(task, "", err, duration)
|
|
return nil, fmt.Errorf("delegation to %q failed quality gate: %w", opts.TargetAgentKey, err)
|
|
}
|
|
|
|
task.Status = "completed"
|
|
dm.emitDelegationEvent(protocol.EventDelegationCompleted, task)
|
|
dm.trackCompleted(task)
|
|
dm.autoCompleteTeamTask(task, result.Content, result.Deliverables)
|
|
dm.saveDelegationHistory(task, result.Content, nil, duration)
|
|
slog.Info("delegation completed", "id", task.ID, "target", opts.TargetAgentKey, "iterations", result.Iterations)
|
|
|
|
return &DelegateResult{Content: result.Content, Iterations: result.Iterations, DelegationID: task.ID, TeamTaskID: task.TeamTaskID.String(), MediaPaths: result.MediaPaths}, nil
|
|
}
|