waveterm/pkg/aiusechat/tools_web.go
Mike Sawka 0e8eb83f62
Updates to prepare for v0.12 launch (#2434)
Documentation Updates (removing AI Widget Information / deprecation)
Hover effect on tool calls shows which widget is effected
Remove AI Widget from sidebar unless there is customized presets
Backend now provides blockid (if available) to frontend for tool calls
2025-10-15 16:10:37 -07:00

108 lines
No EOL
2.7 KiB
Go

// Copyright 2025, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0
package aiusechat
import (
"context"
"encoding/json"
"fmt"
"time"
"github.com/wavetermdev/waveterm/pkg/aiusechat/uctypes"
"github.com/wavetermdev/waveterm/pkg/waveobj"
"github.com/wavetermdev/waveterm/pkg/wcore"
"github.com/wavetermdev/waveterm/pkg/wstore"
)
type WebNavigateToolInput struct {
WidgetId string `json:"widget_id"`
Url string `json:"url"`
}
func parseWebNavigateInput(input any) (*WebNavigateToolInput, error) {
result := &WebNavigateToolInput{}
if input == nil {
return nil, fmt.Errorf("input is required")
}
inputBytes, err := json.Marshal(input)
if err != nil {
return nil, fmt.Errorf("failed to marshal input: %w", err)
}
if err := json.Unmarshal(inputBytes, result); err != nil {
return nil, fmt.Errorf("failed to unmarshal input: %w", err)
}
if result.WidgetId == "" {
return nil, fmt.Errorf("widget_id is required")
}
if result.Url == "" {
return nil, fmt.Errorf("url is required")
}
return result, nil
}
func GetWebNavigateToolDefinition(tabId string) uctypes.ToolDefinition {
return uctypes.ToolDefinition{
Name: "web_navigate",
DisplayName: "Navigate Web Widget",
Description: "Navigate a web browser widget to a new URL",
ToolLogName: "web:navigate",
Strict: true,
InputSchema: map[string]any{
"type": "object",
"properties": map[string]any{
"widget_id": map[string]any{
"type": "string",
"description": "8-character widget ID of the web browser widget",
},
"url": map[string]any{
"type": "string",
"description": "URL to navigate to",
},
},
"required": []string{"widget_id", "url"},
"additionalProperties": false,
},
ToolInputDesc: func(input any) string {
parsed, err := parseWebNavigateInput(input)
if err != nil {
return fmt.Sprintf("error parsing input: %v", err)
}
return fmt.Sprintf("navigating web widget %s to %q", parsed.WidgetId, parsed.Url)
},
ToolAnyCallback: func(input any) (any, error) {
parsed, err := parseWebNavigateInput(input)
if err != nil {
return nil, err
}
ctx, cancelFn := context.WithTimeout(context.Background(), 5*time.Second)
defer cancelFn()
fullBlockId, err := wcore.ResolveBlockIdFromPrefix(ctx, tabId, parsed.WidgetId)
if err != nil {
return nil, err
}
blockORef := waveobj.MakeORef(waveobj.OType_Block, fullBlockId)
meta := map[string]any{
"url": parsed.Url,
}
err = wstore.UpdateObjectMeta(ctx, blockORef, meta, false)
if err != nil {
return nil, fmt.Errorf("failed to update web block URL: %w", err)
}
wcore.SendWaveObjUpdate(blockORef)
return true, nil
},
}
}