New pkg/chat/tool_handler.go: ToolCallHandler interface + ToolCall
type + BuildToolManifest helper + Core-action dispatch adapter +
inline {"tool_call": ...} JSON parser. Service.Send now detects
inline tool calls during stream, invokes OnToolCall, persists a
'tool' result message, and continues the completion loop. Manifest
is prepended to system prompt when a handler is registered
(no-op when unregistered — back-compat).
Good/Bad/Ugly coverage in tool_handler_test.go: valid tool_call
dispatches through mock executor and lands in history; unknown
tool name surfaces error into conversation (not a silent drop);
malformed inline JSON does NOT dispatch — stream continues, no
executor call, assistant message preserves the raw tool_call
fragment for audit.
go vet + go test ./pkg/chat/... clean (codex 0.124.0, gpt-5.5,
LEK AGENTS.md loaded).
Closes tasks.lthn.sh/view.php?id=22
Co-authored-by: Codex <noreply@openai.com>
Co-Authored-By: Virgil <virgil@lethean.io>
47 lines
1.1 KiB
Go
47 lines
1.1 KiB
Go
package chat
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"strings"
|
|
|
|
guimcp "forge.lthn.ai/core/gui/pkg/mcp"
|
|
)
|
|
|
|
type exampleToolExecutor struct{}
|
|
|
|
func (exampleToolExecutor) Manifest() []guimcp.ToolDescriptor {
|
|
return []guimcp.ToolDescriptor{{
|
|
Name: "layout_suggest",
|
|
Description: "Suggest a layout",
|
|
InputSchema: map[string]any{"type": "object"},
|
|
}}
|
|
}
|
|
|
|
func (exampleToolExecutor) ManifestText() string {
|
|
return "Available MCP tools:\n- layout_suggest: Suggest a layout"
|
|
}
|
|
|
|
func (exampleToolExecutor) CallTool(_ context.Context, name string, _ map[string]any) (string, error) {
|
|
if name == "layout_suggest" {
|
|
return `{"mode":"left-right"}`, nil
|
|
}
|
|
return "", nil
|
|
}
|
|
|
|
func ExampleNewToolCallHandler() {
|
|
handler := NewToolCallHandler(exampleToolExecutor{})
|
|
result, err := handler.OnToolCall(context.Background(), ToolCall{
|
|
ID: "call-1",
|
|
Name: "layout_suggest",
|
|
Arguments: map[string]any{"window_count": 2},
|
|
})
|
|
|
|
fmt.Println(err == nil)
|
|
fmt.Println(result)
|
|
fmt.Println(strings.Contains(handler.BuildToolManifest(), "layout_suggest"))
|
|
// Output:
|
|
// true
|
|
// {"mode":"left-right"}
|
|
// true
|
|
}
|