(ctx context.Context, taskID, prompt string)
| 395 | } |
| 396 | |
| 397 | func (rt *AgentTaskRuntime) runWorker(ctx context.Context, taskID, prompt string) { |
| 398 | rt.setStatus(taskID, "running") |
| 399 | rt.mu.Lock() |
| 400 | spec := rt.workerSpecs[taskID] |
| 401 | rt.mu.Unlock() |
| 402 | start := time.Now() |
| 403 | sub := NewSubAgent(spec.cfg, spec.registry, spec.definition, spec.parentState, spec.modelOverride, spec.agentType, spec.extraContext) |
| 404 | sessionState := spec.sessionState |
| 405 | if sessionState == nil { |
| 406 | sessionState = sub.createSessionState(ctx, prompt) |
| 407 | } else { |
| 408 | sessionState.Messages = append(sessionState.Messages, map[string]any{ |
| 409 | "role": "user", |
| 410 | "content": []map[string]any{{"type": "text", "text": prompt}}, |
| 411 | }) |
| 412 | } |
| 413 | startInputTokens := sessionState.TotalInputTokens |
| 414 | startOutputTokens := sessionState.TotalOutputTokens |
| 415 | startToolUseCount := sessionState.TotalToolUseCount |
| 416 | result := sub.ExecuteOneRequest(ctx, prompt, sessionState) |
| 417 | if result.TimedOut && ctx.Err() == nil { |
| 418 | finalizeCtx, finalizeCancel := context.WithTimeout(ctx, time.Duration(SubagentFinalizeSeconds)*time.Second) |
| 419 | result = sub.finalizeTimedOutRun(finalizeCtx, prompt, sessionState, result.FinalText) |
| 420 | finalizeCancel() |
| 421 | } |
| 422 | if result.TimedOut { |
| 423 | result.FinalText = sub.wrapTimedOutResult(result.FinalText) |
| 424 | } |
| 425 | inputDelta := result.TotalInputTokens - startInputTokens |
| 426 | outputDelta := result.TotalOutputTokens - startOutputTokens |
| 427 | toolUseDelta := sessionState.TotalToolUseCount - startToolUseCount |
| 428 | rt.mu.Lock() |
| 429 | current := rt.records[taskID] |
| 430 | if current == nil { |
| 431 | rt.mu.Unlock() |
| 432 | return |
| 433 | } |
| 434 | if current.Status == "killed" { |
| 435 | extra := spec.extraContext |
| 436 | reusable := current.Reusable |
| 437 | delete(rt.workers, taskID) |
| 438 | delete(rt.workerSpecs, taskID) |
| 439 | rt.mu.Unlock() |
| 440 | if wt, _ := extra["worktree_path"].(string); wt != "" && !reusable { |
| 441 | _ = RemoveWorktree(context.Background(), wt) |
| 442 | } |
| 443 | return |
| 444 | } |
| 445 | current.DurationMS += int(time.Since(start).Milliseconds()) |
| 446 | current.InputTokens += inputDelta |
| 447 | current.OutputTokens += outputDelta |
| 448 | current.ToolUseCount += toolUseDelta |
| 449 | reusable := current.Reusable |
| 450 | extra := spec.extraContext |
| 451 | spec.sessionState = sessionState |
| 452 | spec.firstCompleted = true |
| 453 | rt.workerSpecs[taskID] = spec |
| 454 | delete(rt.workers, taskID) |
no test coverage detected