fix: resolve code review issues in tool-result-refactor

1. Remove duplicate ToolResult definition in heartbeat package
   - Import tools.ToolResult instead of local definition
   - Add nil check for handler before execution

2. Fix SpawnTool to return AsyncResult and implement AsyncTool
   - Add callback field and SetCallback method
   - Return AsyncResult instead of NewToolResult

3. Add context cancellation support to SubagentManager
   - Check ctx.Done() before and during task execution
   - Set task status to "cancelled" on cancellation
   - Call callback with result on completion

4. Fix data race window in CronTool.addJob
   - Use Lock instead of RLock for channel/chatID access
   - Ensure consistent snapshot during job creation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
yinwm
2026-02-13 01:59:50 +08:00
parent e7e086155e
commit 474f3dbf90
5 changed files with 73 additions and 28 deletions

View File

@@ -9,6 +9,7 @@ type SpawnTool struct {
manager *SubagentManager
originChannel string
originChatID string
callback AsyncCallback // For async completion notification
}
func NewSpawnTool(manager *SubagentManager) *SpawnTool {
@@ -19,6 +20,11 @@ func NewSpawnTool(manager *SubagentManager) *SpawnTool {
}
}
// SetCallback implements AsyncTool interface for async completion notification
func (t *SpawnTool) SetCallback(cb AsyncCallback) {
t.callback = cb
}
func (t *SpawnTool) Name() string {
return "spawn"
}
@@ -61,10 +67,12 @@ func (t *SpawnTool) Execute(ctx context.Context, args map[string]interface{}) *T
return ErrorResult("Subagent manager not configured")
}
result, err := t.manager.Spawn(ctx, task, label, t.originChannel, t.originChatID)
// Pass callback to manager for async completion notification
result, err := t.manager.Spawn(ctx, task, label, t.originChannel, t.originChatID, t.callback)
if err != nil {
return ErrorResult(fmt.Sprintf("failed to spawn subagent: %v", err))
}
return NewToolResult(result)
// Return AsyncResult since the task runs in background
return AsyncResult(result)
}