feat: US-006 - Add AsyncCallback type and AsyncTool interface
- Define AsyncCallback function type for async tool completion notification - Define AsyncTool interface with SetCallback method - Add comprehensive godoc comments with usage examples - This enables tools like SpawnTool to notify completion asynchronously Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -91,7 +91,7 @@
|
|||||||
"Typecheck passes"
|
"Typecheck passes"
|
||||||
],
|
],
|
||||||
"priority": 6,
|
"priority": 6,
|
||||||
"passes": false,
|
"passes": true,
|
||||||
"notes": ""
|
"notes": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,12 +6,13 @@ Tool 返回值结构化重构 - 将 Tool 接口返回值从 (string, error) 改
|
|||||||
|
|
||||||
## Progress
|
## Progress
|
||||||
|
|
||||||
### Completed (4/21)
|
### Completed (5/21)
|
||||||
|
|
||||||
- US-001: Add ToolResult struct and helper functions
|
- US-001: Add ToolResult struct and helper functions
|
||||||
- US-002: Modify Tool interface to return *ToolResult
|
- US-002: Modify Tool interface to return *ToolResult
|
||||||
- US-004: Delete isToolConfirmationMessage function (already removed in commit 488e7a9)
|
- US-004: Delete isToolConfirmationMessage function (already removed in commit 488e7a9)
|
||||||
- US-005: Update AgentLoop tool result processing logic
|
- US-005: Update AgentLoop tool result processing logic
|
||||||
|
- US-006: Add AsyncCallback type and AsyncTool interface
|
||||||
|
|
||||||
### In Progress
|
### In Progress
|
||||||
|
|
||||||
@@ -24,7 +25,7 @@ Tool 返回值结构化重构 - 将 Tool 接口返回值从 (string, error) 改
|
|||||||
| US-003 | Modify ToolRegistry to process ToolResult | Pending | registry.go already updated |
|
| US-003 | Modify ToolRegistry to process ToolResult | Pending | registry.go already updated |
|
||||||
| US-004 | Delete isToolConfirmationMessage function | Completed | Already removed in commit 488e7a9 |
|
| US-004 | Delete isToolConfirmationMessage function | Completed | Already removed in commit 488e7a9 |
|
||||||
| US-005 | Update AgentLoop tool result processing logic | Completed | No test files in pkg/agent yet |
|
| US-005 | Update AgentLoop tool result processing logic | Completed | No test files in pkg/agent yet |
|
||||||
| US-006 | Add AsyncCallback type and AsyncTool interface | Pending | |
|
| US-006 | Add AsyncCallback type and AsyncTool interface | Completed | |
|
||||||
| US-007 | Heartbeat async task execution support | Pending | |
|
| US-007 | Heartbeat async task execution support | Pending | |
|
||||||
| US-008 | Inject callback into async tools in AgentLoop | Pending | |
|
| US-008 | Inject callback into async tools in AgentLoop | Pending | |
|
||||||
| US-009 | State save atomicity - SetLastChannel | Pending | |
|
| US-009 | State save atomicity - SetLastChannel | Pending | |
|
||||||
@@ -84,4 +85,20 @@ Tool 返回值结构化重构 - 将 Tool 接口返回值从 (string, error) 改
|
|||||||
- **Gotchas encountered:** 编辑大文件时要小心不要引入重复代码。我之前编辑时没有完整替换代码块,导致有重复的代码段。
|
- **Gotchas encountered:** 编辑大文件时要小心不要引入重复代码。我之前编辑时没有完整替换代码块,导致有重复的代码段。
|
||||||
- **Useful context:** `opts.SendResponse` 参数控制是否发送响应给用户。当工具设置了 `ForUser` 时,即使 Silent=false,也只有在 `SendResponse=true` 时才会发送。
|
- **Useful context:** `opts.SendResponse` 参数控制是否发送响应给用户。当工具设置了 `ForUser` 时,即使 Silent=false,也只有在 `SendResponse=true` 时才会发送。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## [2026-02-12] - US-006
|
||||||
|
- What was implemented:
|
||||||
|
- 在 `pkg/tools/base.go` 中定义 `AsyncCallback` 函数类型
|
||||||
|
- 定义 `AsyncTool` 接口,包含 `SetCallback(cb AsyncCallback)` 方法
|
||||||
|
- 添加完整的 godoc 注释,包含使用示例
|
||||||
|
|
||||||
|
- Files changed:
|
||||||
|
- `pkg/tools/base.go`
|
||||||
|
|
||||||
|
- **Learnings for future iterations:**
|
||||||
|
- **Patterns discovered:** Go 接口的设计应该是可选的组合模式。`AsyncTool` 是一个可选接口,工具可以选择实现以支持异步操作。
|
||||||
|
- **Gotchas encountered:** 无
|
||||||
|
- **Useful context:** 这个模式将在 US-008 中用于 `SpawnTool`,让子代理完成时能够通知主循环。
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -2,6 +2,7 @@ package tools
|
|||||||
|
|
||||||
import "context"
|
import "context"
|
||||||
|
|
||||||
|
// Tool is the interface that all tools must implement.
|
||||||
type Tool interface {
|
type Tool interface {
|
||||||
Name() string
|
Name() string
|
||||||
Description() string
|
Description() string
|
||||||
@@ -16,6 +17,58 @@ type ContextualTool interface {
|
|||||||
SetContext(channel, chatID string)
|
SetContext(channel, chatID string)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AsyncCallback is a function type that async tools use to notify completion.
|
||||||
|
// When an async tool finishes its work, it calls this callback with the result.
|
||||||
|
//
|
||||||
|
// The ctx parameter allows the callback to be canceled if the agent is shutting down.
|
||||||
|
// The result parameter contains the tool's execution result.
|
||||||
|
//
|
||||||
|
// Example usage in an async tool:
|
||||||
|
//
|
||||||
|
// func (t *MyAsyncTool) Execute(ctx context.Context, args map[string]interface{}) *ToolResult {
|
||||||
|
// // Start async work in background
|
||||||
|
// go func() {
|
||||||
|
// result := doAsyncWork()
|
||||||
|
// if t.callback != nil {
|
||||||
|
// t.callback(ctx, result)
|
||||||
|
// }
|
||||||
|
// }()
|
||||||
|
// return AsyncResult("Async task started")
|
||||||
|
// }
|
||||||
|
type AsyncCallback func(ctx context.Context, result *ToolResult)
|
||||||
|
|
||||||
|
// AsyncTool is an optional interface that tools can implement to support
|
||||||
|
// asynchronous execution with completion callbacks.
|
||||||
|
//
|
||||||
|
// Async tools return immediately with an AsyncResult, then notify completion
|
||||||
|
// via the callback set by SetCallback.
|
||||||
|
//
|
||||||
|
// This is useful for:
|
||||||
|
// - Long-running operations that shouldn't block the agent loop
|
||||||
|
// - Subagent spawns that complete independently
|
||||||
|
// - Background tasks that need to report results later
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
//
|
||||||
|
// type SpawnTool struct {
|
||||||
|
// callback AsyncCallback
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// func (t *SpawnTool) SetCallback(cb AsyncCallback) {
|
||||||
|
// t.callback = cb
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// func (t *SpawnTool) Execute(ctx context.Context, args map[string]interface{}) *ToolResult {
|
||||||
|
// go t.runSubagent(ctx, args)
|
||||||
|
// return AsyncResult("Subagent spawned, will report back")
|
||||||
|
// }
|
||||||
|
type AsyncTool interface {
|
||||||
|
Tool
|
||||||
|
// SetCallback registers a callback function to be invoked when the async operation completes.
|
||||||
|
// The callback will be called from a goroutine and should handle thread-safety if needed.
|
||||||
|
SetCallback(cb AsyncCallback)
|
||||||
|
}
|
||||||
|
|
||||||
func ToolToSchema(tool Tool) map[string]interface{} {
|
func ToolToSchema(tool Tool) map[string]interface{} {
|
||||||
return map[string]interface{}{
|
return map[string]interface{}{
|
||||||
"type": "function",
|
"type": "function",
|
||||||
|
|||||||
Reference in New Issue
Block a user