browser: add window resize tool with chromedp
Co-Authored-By: sketch <hello@sketch.dev>
Change-ID: s68bdc7fb84309a7ck
diff --git a/claudetool/browse/browse.go b/claudetool/browse/browse.go
index a5a1621..8a72390 100644
--- a/claudetool/browse/browse.go
+++ b/claudetool/browse/browse.go
@@ -655,6 +655,71 @@
return llm.TextContent(successResponse()), nil
}
+// ResizeTool definition
+type resizeInput struct {
+ Width int `json:"width"`
+ Height int `json:"height"`
+ Timeout string `json:"timeout,omitempty"`
+}
+
+// NewResizeTool creates a tool for resizing the browser window
+func (b *BrowseTools) NewResizeTool() *llm.Tool {
+ return &llm.Tool{
+ Name: "browser_resize",
+ Description: "Resize the browser window to a specific width and height",
+ InputSchema: json.RawMessage(`{
+ "type": "object",
+ "properties": {
+ "width": {
+ "type": "integer",
+ "description": "Window width in pixels"
+ },
+ "height": {
+ "type": "integer",
+ "description": "Window height in pixels"
+ },
+ "timeout": {
+ "type": "string",
+ "description": "Timeout as a Go duration string (default: 5s)"
+ }
+ },
+ "required": ["width", "height"]
+ }`),
+ Run: b.resizeRun,
+ }
+}
+
+func (b *BrowseTools) resizeRun(ctx context.Context, m json.RawMessage) ([]llm.Content, error) {
+ var input resizeInput
+ if err := json.Unmarshal(m, &input); err != nil {
+ return llm.TextContent(errorResponse(fmt.Errorf("invalid input: %w", err))), nil
+ }
+
+ browserCtx, err := b.GetBrowserContext()
+ if err != nil {
+ return llm.TextContent(errorResponse(err)), nil
+ }
+
+ // Create a timeout context for this operation
+ timeoutCtx, cancel := context.WithTimeout(browserCtx, parseTimeout(input.Timeout))
+ defer cancel()
+
+ // Validate dimensions
+ if input.Width <= 0 || input.Height <= 0 {
+ return llm.TextContent(errorResponse(fmt.Errorf("invalid dimensions: width and height must be positive"))), nil
+ }
+
+ // Resize the browser window
+ err = chromedp.Run(timeoutCtx,
+ chromedp.EmulateViewport(int64(input.Width), int64(input.Height)),
+ )
+ if err != nil {
+ return llm.TextContent(errorResponse(err)), nil
+ }
+
+ return llm.TextContent(successResponse()), nil
+}
+
// GetTools returns browser tools, optionally filtering out screenshot-related tools
func (b *BrowseTools) GetTools(includeScreenshotTools bool) []*llm.Tool {
tools := []*llm.Tool{
@@ -665,6 +730,7 @@
b.NewGetTextTool(),
b.NewEvalTool(),
b.NewScrollIntoViewTool(),
+ b.NewResizeTool(),
}
// Add screenshot-related tools if supported