From d9eabf748609a9a036c720c0ee369ecbd5ce6cd6 Mon Sep 17 00:00:00 2001 From: Ayman Bagabas Date: Wed, 24 Sep 2025 12:58:26 -0400 Subject: [PATCH] refactor: centralize tool types in proto pkg and unmarshal permission params --- internal/llm/tools/bash.go | 23 +--- internal/llm/tools/diagnostics.go | 5 +- internal/llm/tools/download.go | 18 +-- internal/llm/tools/edit.go | 27 +--- internal/llm/tools/fetch.go | 18 +-- internal/llm/tools/glob.go | 16 +-- internal/llm/tools/grep.go | 18 +-- internal/llm/tools/ls.go | 30 ++--- internal/llm/tools/multiedit.go | 32 ++--- internal/llm/tools/sourcegraph.go | 19 +-- internal/llm/tools/tools.go | 21 +-- internal/llm/tools/view.go | 24 +--- internal/llm/tools/write.go | 24 +--- internal/proto/message.go | 4 +- internal/proto/permission.go | 144 ++++++++++++++++++++ internal/proto/tools.go | 216 ++++++++++++++++++++++++++++++ 16 files changed, 445 insertions(+), 194 deletions(-) create mode 100644 internal/proto/tools.go diff --git a/internal/llm/tools/bash.go b/internal/llm/tools/bash.go index 7f91ecb78b3d79380d029a1d58bb62083cdf27fe..9b65cc4ceee8e434c5234545e607024173316244 100644 --- a/internal/llm/tools/bash.go +++ b/internal/llm/tools/bash.go @@ -12,25 +12,16 @@ import ( "github.com/charmbracelet/crush/internal/config" "github.com/charmbracelet/crush/internal/permission" + "github.com/charmbracelet/crush/internal/proto" "github.com/charmbracelet/crush/internal/shell" ) -type BashParams struct { - Command string `json:"command"` - Timeout int `json:"timeout"` -} - -type BashPermissionsParams struct { - Command string `json:"command"` - Timeout int `json:"timeout"` -} +type ( + BashParams = proto.BashParams + BashPermissionsParams = proto.BashPermissionsParams + BashResponseMetadata = proto.BashResponseMetadata +) -type BashResponseMetadata struct { - StartTime int64 `json:"start_time"` - EndTime int64 `json:"end_time"` - Output string `json:"output"` - WorkingDirectory string `json:"working_directory"` -} type bashTool struct { permissions permission.Service workingDir string @@ -38,7 +29,7 @@ type bashTool struct { } const ( - BashToolName = "bash" + BashToolName = proto.BashToolName DefaultTimeout = 1 * 60 * 1000 // 1 minutes in milliseconds MaxTimeout = 10 * 60 * 1000 // 10 minutes in milliseconds diff --git a/internal/llm/tools/diagnostics.go b/internal/llm/tools/diagnostics.go index 8e0c332cef76e40d5e24e74ed3260b95aab8b04b..aee04a188ac78042c319947e913b18dfd5244c2f 100644 --- a/internal/llm/tools/diagnostics.go +++ b/internal/llm/tools/diagnostics.go @@ -12,12 +12,11 @@ import ( "github.com/charmbracelet/crush/internal/csync" "github.com/charmbracelet/crush/internal/lsp" + "github.com/charmbracelet/crush/internal/proto" "github.com/charmbracelet/x/powernap/pkg/lsp/protocol" ) -type DiagnosticsParams struct { - FilePath string `json:"file_path"` -} +type DiagnosticsParams = proto.DiagnosticsParams type diagnosticsTool struct { lspClients *csync.Map[string, *lsp.Client] diff --git a/internal/llm/tools/download.go b/internal/llm/tools/download.go index 63092cf24a0dbb98e7aef58e9d4ee867525ae945..de8b9bff7394748fda6a7627a40b14eed965430f 100644 --- a/internal/llm/tools/download.go +++ b/internal/llm/tools/download.go @@ -13,19 +13,13 @@ import ( "time" "github.com/charmbracelet/crush/internal/permission" + "github.com/charmbracelet/crush/internal/proto" ) -type DownloadParams struct { - URL string `json:"url"` - FilePath string `json:"file_path"` - Timeout int `json:"timeout,omitempty"` -} - -type DownloadPermissionsParams struct { - URL string `json:"url"` - FilePath string `json:"file_path"` - Timeout int `json:"timeout,omitempty"` -} +type ( + DownloadParams = proto.DownloadParams + DownloadPermissionsParams = proto.DownloadPermissionsParams +) type downloadTool struct { client *http.Client @@ -33,7 +27,7 @@ type downloadTool struct { workingDir string } -const DownloadToolName = "download" +const DownloadToolName = proto.DownloadToolName //go:embed download.md var downloadDescription []byte diff --git a/internal/llm/tools/edit.go b/internal/llm/tools/edit.go index ae4322e08da087127a3238a1e3edf6c1a9a2e37a..4f572eda2cb68d714e87cb0b5f12fff30ca0c524 100644 --- a/internal/llm/tools/edit.go +++ b/internal/llm/tools/edit.go @@ -15,30 +15,17 @@ import ( "github.com/charmbracelet/crush/internal/diff" "github.com/charmbracelet/crush/internal/fsext" "github.com/charmbracelet/crush/internal/history" + "github.com/charmbracelet/crush/internal/proto" "github.com/charmbracelet/crush/internal/lsp" "github.com/charmbracelet/crush/internal/permission" ) -type EditParams struct { - FilePath string `json:"file_path"` - OldString string `json:"old_string"` - NewString string `json:"new_string"` - ReplaceAll bool `json:"replace_all,omitempty"` -} - -type EditPermissionsParams struct { - FilePath string `json:"file_path"` - OldContent string `json:"old_content,omitempty"` - NewContent string `json:"new_content,omitempty"` -} - -type EditResponseMetadata struct { - Additions int `json:"additions"` - Removals int `json:"removals"` - OldContent string `json:"old_content,omitempty"` - NewContent string `json:"new_content,omitempty"` -} +type ( + EditParams = proto.EditParams + EditPermissionsParams = proto.EditPermissionsParams + EditResponseMetadata = proto.EditResponseMetadata +) type editTool struct { lspClients *csync.Map[string, *lsp.Client] @@ -47,7 +34,7 @@ type editTool struct { workingDir string } -const EditToolName = "edit" +const EditToolName = proto.EditToolName //go:embed edit.md var editDescription []byte diff --git a/internal/llm/tools/fetch.go b/internal/llm/tools/fetch.go index e9c5732462651cd9e31337f91f4f4d91a36e70c1..c56ce32988b3a71159b19c672eeda80611c00782 100644 --- a/internal/llm/tools/fetch.go +++ b/internal/llm/tools/fetch.go @@ -14,19 +14,13 @@ import ( md "github.com/JohannesKaufmann/html-to-markdown" "github.com/PuerkitoBio/goquery" "github.com/charmbracelet/crush/internal/permission" + "github.com/charmbracelet/crush/internal/proto" ) -type FetchParams struct { - URL string `json:"url"` - Format string `json:"format"` - Timeout int `json:"timeout,omitempty"` -} - -type FetchPermissionsParams struct { - URL string `json:"url"` - Format string `json:"format"` - Timeout int `json:"timeout,omitempty"` -} +type ( + FetchParams = proto.FetchParams + FetchPermissionsParams = proto.FetchPermissionsParams +) type fetchTool struct { client *http.Client @@ -34,7 +28,7 @@ type fetchTool struct { workingDir string } -const FetchToolName = "fetch" +const FetchToolName = proto.FetchToolName //go:embed fetch.md var fetchDescription []byte diff --git a/internal/llm/tools/glob.go b/internal/llm/tools/glob.go index 85207c28ea3408ab4a3867e983766d35c9474b47..ce4dc609c2e90d8f173b6508c70672042535e028 100644 --- a/internal/llm/tools/glob.go +++ b/internal/llm/tools/glob.go @@ -13,22 +13,18 @@ import ( "strings" "github.com/charmbracelet/crush/internal/fsext" + "github.com/charmbracelet/crush/internal/proto" ) -const GlobToolName = "glob" +const GlobToolName = proto.GlobToolName //go:embed glob.md var globDescription []byte -type GlobParams struct { - Pattern string `json:"pattern"` - Path string `json:"path"` -} - -type GlobResponseMetadata struct { - NumberOfFiles int `json:"number_of_files"` - Truncated bool `json:"truncated"` -} +type ( + GlobParams = proto.GlobParams + GlobResponseMetadata = proto.GlobResponseMetadata +) type globTool struct { workingDir string diff --git a/internal/llm/tools/grep.go b/internal/llm/tools/grep.go index cbf50360b9355c05797690678a99d1310b19556f..90c905103d49df76cecd27545144714f2a7647a2 100644 --- a/internal/llm/tools/grep.go +++ b/internal/llm/tools/grep.go @@ -18,6 +18,7 @@ import ( "time" "github.com/charmbracelet/crush/internal/fsext" + "github.com/charmbracelet/crush/internal/proto" ) // regexCache provides thread-safe caching of compiled regex patterns @@ -70,13 +71,6 @@ var ( globBraceRegex = regexp.MustCompile(`\{([^}]+)\}`) ) -type GrepParams struct { - Pattern string `json:"pattern"` - Path string `json:"path"` - Include string `json:"include"` - LiteralText bool `json:"literal_text"` -} - type grepMatch struct { path string modTime time.Time @@ -84,16 +78,16 @@ type grepMatch struct { lineText string } -type GrepResponseMetadata struct { - NumberOfMatches int `json:"number_of_matches"` - Truncated bool `json:"truncated"` -} +type ( + GrepParams = proto.GrepParams + GrepResponseMetadata = proto.GrepResponseMetadata +) type grepTool struct { workingDir string } -const GrepToolName = "grep" +const GrepToolName = proto.GrepToolName //go:embed grep.md var grepDescription []byte diff --git a/internal/llm/tools/ls.go b/internal/llm/tools/ls.go index f421e69e7af938801aa9c3affacfe30ed669fabc..d5d52d3cde64963ac93a3a46e7252aa054fb5237 100644 --- a/internal/llm/tools/ls.go +++ b/internal/llm/tools/ls.go @@ -11,29 +11,15 @@ import ( "github.com/charmbracelet/crush/internal/fsext" "github.com/charmbracelet/crush/internal/permission" + "github.com/charmbracelet/crush/internal/proto" ) -type LSParams struct { - Path string `json:"path"` - Ignore []string `json:"ignore"` -} - -type LSPermissionsParams struct { - Path string `json:"path"` - Ignore []string `json:"ignore"` -} - -type TreeNode struct { - Name string `json:"name"` - Path string `json:"path"` - Type string `json:"type"` // "file" or "directory" - Children []*TreeNode `json:"children,omitempty"` -} - -type LSResponseMetadata struct { - NumberOfFiles int `json:"number_of_files"` - Truncated bool `json:"truncated"` -} +type ( + LSParams = proto.LSParams + LSPermissionsParams = proto.LSPermissionsParams + LSResponseMetadata = proto.LSResponseMetadata + TreeNode = proto.TreeNode +) type lsTool struct { workingDir string @@ -41,7 +27,7 @@ type lsTool struct { } const ( - LSToolName = "ls" + LSToolName = proto.LSToolName MaxLSFiles = 1000 ) diff --git a/internal/llm/tools/multiedit.go b/internal/llm/tools/multiedit.go index 1d6e415ceb8cc10bcc32788cddbbdc40fc781907..13b9e149859f000ebf8537cfdbbd9709dc26f3ce 100644 --- a/internal/llm/tools/multiedit.go +++ b/internal/llm/tools/multiedit.go @@ -17,32 +17,16 @@ import ( "github.com/charmbracelet/crush/internal/history" "github.com/charmbracelet/crush/internal/lsp" "github.com/charmbracelet/crush/internal/permission" + "github.com/charmbracelet/crush/internal/proto" ) -type MultiEditOperation struct { - OldString string `json:"old_string"` - NewString string `json:"new_string"` - ReplaceAll bool `json:"replace_all,omitempty"` -} - -type MultiEditParams struct { - FilePath string `json:"file_path"` - Edits []MultiEditOperation `json:"edits"` -} +type ( + MultiEditOperation = proto.MultiEditOperation + MultiEditParams = proto.MultiEditParams -type MultiEditPermissionsParams struct { - FilePath string `json:"file_path"` - OldContent string `json:"old_content,omitempty"` - NewContent string `json:"new_content,omitempty"` -} - -type MultiEditResponseMetadata struct { - Additions int `json:"additions"` - Removals int `json:"removals"` - OldContent string `json:"old_content,omitempty"` - NewContent string `json:"new_content,omitempty"` - EditsApplied int `json:"edits_applied"` -} + MultiEditPermissionsParams = proto.MultiEditPermissionsParams + MultiEditResponseMetadata = proto.MultiEditResponseMetadata +) type multiEditTool struct { lspClients *csync.Map[string, *lsp.Client] @@ -51,7 +35,7 @@ type multiEditTool struct { workingDir string } -const MultiEditToolName = "multiedit" +const MultiEditToolName = proto.MultiEditToolName //go:embed multiedit.md var multieditDescription []byte diff --git a/internal/llm/tools/sourcegraph.go b/internal/llm/tools/sourcegraph.go index aea6b1ae8f0d52d10c083debf5bd3780957f261a..d31b50acb5768d0c2f77ba9822f0f956776c320d 100644 --- a/internal/llm/tools/sourcegraph.go +++ b/internal/llm/tools/sourcegraph.go @@ -10,25 +10,20 @@ import ( "net/http" "strings" "time" -) -type SourcegraphParams struct { - Query string `json:"query"` - Count int `json:"count,omitempty"` - ContextWindow int `json:"context_window,omitempty"` - Timeout int `json:"timeout,omitempty"` -} + "github.com/charmbracelet/crush/internal/proto" +) -type SourcegraphResponseMetadata struct { - NumberOfMatches int `json:"number_of_matches"` - Truncated bool `json:"truncated"` -} +type ( + SourcegraphParams = proto.SourcegraphParams + SourcegraphResponseMetadata = proto.SourcegraphResponseMetadata +) type sourcegraphTool struct { client *http.Client } -const SourcegraphToolName = "sourcegraph" +const SourcegraphToolName = proto.SourcegraphToolName //go:embed sourcegraph.md var sourcegraphDescription []byte diff --git a/internal/llm/tools/tools.go b/internal/llm/tools/tools.go index 41c0515616032b117f3c09a0056cac9e86b62c66..d6181e599fe5ddcc397c77990f473bb067980492 100644 --- a/internal/llm/tools/tools.go +++ b/internal/llm/tools/tools.go @@ -3,6 +3,8 @@ package tools import ( "context" "encoding/json" + + "github.com/charmbracelet/crush/internal/proto" ) type ToolInfo struct { @@ -12,27 +14,20 @@ type ToolInfo struct { Required []string } -type toolResponseType string - type ( sessionIDContextKey string messageIDContextKey string ) const ( - ToolResponseTypeText toolResponseType = "text" - ToolResponseTypeImage toolResponseType = "image" + ToolResponseTypeText = proto.ToolResponseTypeText + ToolResponseTypeImage = proto.ToolResponseTypeImage SessionIDContextKey sessionIDContextKey = "session_id" MessageIDContextKey messageIDContextKey = "message_id" ) -type ToolResponse struct { - Type toolResponseType `json:"type"` - Content string `json:"content"` - Metadata string `json:"metadata,omitempty"` - IsError bool `json:"is_error"` -} +type ToolResponse = proto.ToolResponse func NewTextResponse(content string) ToolResponse { return ToolResponse{ @@ -60,11 +55,7 @@ func NewTextErrorResponse(content string) ToolResponse { } } -type ToolCall struct { - ID string `json:"id"` - Name string `json:"name"` - Input string `json:"input"` -} +type ToolCall = proto.ToolCall type BaseTool interface { Info() ToolInfo diff --git a/internal/llm/tools/view.go b/internal/llm/tools/view.go index c3824bf1b1cc11dc22c57d60eb72654999a5e970..00d692a0ad8d757e996f36dcae3d4dd12cd22ca8 100644 --- a/internal/llm/tools/view.go +++ b/internal/llm/tools/view.go @@ -15,22 +15,17 @@ import ( "github.com/charmbracelet/crush/internal/csync" "github.com/charmbracelet/crush/internal/lsp" "github.com/charmbracelet/crush/internal/permission" + "github.com/charmbracelet/crush/internal/proto" ) //go:embed view.md var viewDescription []byte -type ViewParams struct { - FilePath string `json:"file_path"` - Offset int `json:"offset"` - Limit int `json:"limit"` -} - -type ViewPermissionsParams struct { - FilePath string `json:"file_path"` - Offset int `json:"offset"` - Limit int `json:"limit"` -} +type ( + ViewParams = proto.ViewParams + ViewPermissionsParams = proto.ViewPermissionsParams + ViewResponseMetadata = proto.ViewResponseMetadata +) type viewTool struct { lspClients *csync.Map[string, *lsp.Client] @@ -38,13 +33,8 @@ type viewTool struct { permissions permission.Service } -type ViewResponseMetadata struct { - FilePath string `json:"file_path"` - Content string `json:"content"` -} - const ( - ViewToolName = "view" + ViewToolName = proto.ViewToolName MaxReadSize = 250 * 1024 DefaultReadLimit = 2000 MaxLineLength = 2000 diff --git a/internal/llm/tools/write.go b/internal/llm/tools/write.go index 36ea13d2dd6e1930eb645ab036c950b9a4d6fdc8..a4ecf0d6d63cae76910d9f6543899493fa0da630 100644 --- a/internal/llm/tools/write.go +++ b/internal/llm/tools/write.go @@ -15,6 +15,7 @@ import ( "github.com/charmbracelet/crush/internal/diff" "github.com/charmbracelet/crush/internal/fsext" "github.com/charmbracelet/crush/internal/history" + "github.com/charmbracelet/crush/internal/proto" "github.com/charmbracelet/crush/internal/lsp" "github.com/charmbracelet/crush/internal/permission" @@ -23,16 +24,11 @@ import ( //go:embed write.md var writeDescription []byte -type WriteParams struct { - FilePath string `json:"file_path"` - Content string `json:"content"` -} - -type WritePermissionsParams struct { - FilePath string `json:"file_path"` - OldContent string `json:"old_content,omitempty"` - NewContent string `json:"new_content,omitempty"` -} +type ( + WriteParams = proto.WriteParams + WritePermissionsParams = proto.WritePermissionsParams + WriteResponseMetadata = proto.WriteResponseMetadata +) type writeTool struct { lspClients *csync.Map[string, *lsp.Client] @@ -41,13 +37,7 @@ type writeTool struct { workingDir string } -type WriteResponseMetadata struct { - Diff string `json:"diff"` - Additions int `json:"additions"` - Removals int `json:"removals"` -} - -const WriteToolName = "write" +const WriteToolName = proto.WriteToolName func NewWriteTool(lspClients *csync.Map[string, *lsp.Client], permissions permission.Service, files history.Service, workingDir string) BaseTool { return &writeTool{ diff --git a/internal/proto/message.go b/internal/proto/message.go index 6b4decf291c71cc2fdbeefa44d6c8a03ce505c32..b86e6a8d96a44e081723dfa1c829704e7e6d6b4f 100644 --- a/internal/proto/message.go +++ b/internal/proto/message.go @@ -125,8 +125,8 @@ type ToolCall struct { ID string `json:"id"` Name string `json:"name"` Input string `json:"input"` - Type string `json:"type"` - Finished bool `json:"finished"` + Type string `json:"type,omitempty"` + Finished bool `json:"finished,omitempty"` } func (ToolCall) isPart() {} diff --git a/internal/proto/permission.go b/internal/proto/permission.go index 5f03fabe2617103119982eb6a70cc3ef75a75f76..c99bf9eab67551f9d679d10219ec9b0ec4fc2ab1 100644 --- a/internal/proto/permission.go +++ b/internal/proto/permission.go @@ -1,5 +1,9 @@ package proto +import ( + "encoding/json" +) + type CreatePermissionRequest struct { SessionID string `json:"session_id"` ToolCallID string `json:"tool_call_id"` @@ -26,3 +30,143 @@ type PermissionRequest struct { Params any `json:"params"` Path string `json:"path"` } + +// UnmarshalJSON implements the json.Unmarshaler interface. This is needed +// because the Params field is of type any, so we need to unmarshal it into +// it's appropriate type based on the [PermissionRequest.ToolName]. +func (p *PermissionRequest) UnmarshalJSON(data []byte) error { + type Alias PermissionRequest + aux := &struct { + Params json.RawMessage `json:"params"` + *Alias + }{ + Alias: (*Alias)(p), + } + if err := json.Unmarshal(data, &aux); err != nil { + return err + } + + switch p.ToolName { + case BashToolName: + var params BashPermissionsParams + if err := json.Unmarshal(aux.Params, ¶ms); err != nil { + return err + } + p.Params = params + case DownloadToolName: + var params DownloadPermissionsParams + if err := json.Unmarshal(aux.Params, ¶ms); err != nil { + return err + } + p.Params = params + case EditToolName: + var params EditPermissionsParams + if err := json.Unmarshal(aux.Params, ¶ms); err != nil { + return err + } + p.Params = params + case WriteToolName: + var params WritePermissionsParams + if err := json.Unmarshal(aux.Params, ¶ms); err != nil { + return err + } + p.Params = params + case MultiEditToolName: + var params MultiEditPermissionsParams + if err := json.Unmarshal(aux.Params, ¶ms); err != nil { + return err + } + p.Params = params + case FetchToolName: + var params FetchPermissionsParams + if err := json.Unmarshal(aux.Params, ¶ms); err != nil { + return err + } + p.Params = params + case ViewToolName: + var params ViewPermissionsParams + if err := json.Unmarshal(aux.Params, ¶ms); err != nil { + return err + } + p.Params = params + case LSToolName: + var params LSPermissionsParams + if err := json.Unmarshal(aux.Params, ¶ms); err != nil { + return err + } + p.Params = params + default: + panic("unknown tool name: " + p.ToolName) + } + return nil +} + +// UnmarshalJSON implements the json.Unmarshaler interface. This is needed +// because the Params field is of type any, so we need to unmarshal it into +// it's appropriate type based on the [CreatePermissionRequest.ToolName]. +func (p *CreatePermissionRequest) UnmarshalJSON(data []byte) error { + type Alias CreatePermissionRequest + aux := &struct { + Params json.RawMessage `json:"params"` + *Alias + }{ + Alias: (*Alias)(p), + } + if err := json.Unmarshal(data, &aux); err != nil { + return err + } + + switch p.ToolName { + case BashToolName: + var params BashPermissionsParams + if err := json.Unmarshal(aux.Params, ¶ms); err != nil { + return err + } + p.Params = params + case DownloadToolName: + var params DownloadPermissionsParams + if err := json.Unmarshal(aux.Params, ¶ms); err != nil { + return err + } + p.Params = params + case EditToolName: + var params EditPermissionsParams + if err := json.Unmarshal(aux.Params, ¶ms); err != nil { + return err + } + p.Params = params + case WriteToolName: + var params WritePermissionsParams + if err := json.Unmarshal(aux.Params, ¶ms); err != nil { + return err + } + p.Params = params + case MultiEditToolName: + var params MultiEditPermissionsParams + if err := json.Unmarshal(aux.Params, ¶ms); err != nil { + return err + } + p.Params = params + case FetchToolName: + var params FetchPermissionsParams + if err := json.Unmarshal(aux.Params, ¶ms); err != nil { + return err + } + p.Params = params + case ViewToolName: + var params ViewPermissionsParams + if err := json.Unmarshal(aux.Params, ¶ms); err != nil { + return err + } + p.Params = params + case LSToolName: + var params LSPermissionsParams + if err := json.Unmarshal(aux.Params, ¶ms); err != nil { + return err + } + p.Params = params + default: + panic("unknown tool name: " + p.ToolName) + } + return nil +} diff --git a/internal/proto/tools.go b/internal/proto/tools.go new file mode 100644 index 0000000000000000000000000000000000000000..7de4bad4e0e3fae59aca40f941ac337e67e34c3f --- /dev/null +++ b/internal/proto/tools.go @@ -0,0 +1,216 @@ +package proto + +type ToolResponseType string + +const ( + ToolResponseTypeText ToolResponseType = "text" + ToolResponseTypeImage ToolResponseType = "image" +) + +type ToolResponse struct { + Type ToolResponseType `json:"type"` + Content string `json:"content"` + Metadata string `json:"metadata,omitempty"` + IsError bool `json:"is_error"` +} + +const ( + BashToolName = "bash" +) + +type BashParams struct { + Command string `json:"command"` + Timeout int `json:"timeout"` +} + +type BashPermissionsParams struct { + Command string `json:"command"` + Timeout int `json:"timeout"` +} + +type BashResponseMetadata struct { + StartTime int64 `json:"start_time"` + EndTime int64 `json:"end_time"` + Output string `json:"output"` + WorkingDirectory string `json:"working_directory"` +} + +type DiagnosticsParams struct { + FilePath string `json:"file_path"` +} + +const DownloadToolName = "download" + +type DownloadParams struct { + URL string `json:"url"` + FilePath string `json:"file_path"` + Timeout int `json:"timeout,omitempty"` +} + +type DownloadPermissionsParams struct { + URL string `json:"url"` + FilePath string `json:"file_path"` + Timeout int `json:"timeout,omitempty"` +} + +const EditToolName = "edit" + +type EditParams struct { + FilePath string `json:"file_path"` + OldString string `json:"old_string"` + NewString string `json:"new_string"` + ReplaceAll bool `json:"replace_all,omitempty"` +} + +type EditPermissionsParams struct { + FilePath string `json:"file_path"` + OldContent string `json:"old_content,omitempty"` + NewContent string `json:"new_content,omitempty"` +} + +type EditResponseMetadata struct { + Additions int `json:"additions"` + Removals int `json:"removals"` + OldContent string `json:"old_content,omitempty"` + NewContent string `json:"new_content,omitempty"` +} + +const FetchToolName = "fetch" + +type FetchParams struct { + URL string `json:"url"` + Format string `json:"format"` + Timeout int `json:"timeout,omitempty"` +} + +type FetchPermissionsParams struct { + URL string `json:"url"` + Format string `json:"format"` + Timeout int `json:"timeout,omitempty"` +} + +const GlobToolName = "glob" + +type GlobParams struct { + Pattern string `json:"pattern"` + Path string `json:"path"` +} + +type GlobResponseMetadata struct { + NumberOfFiles int `json:"number_of_files"` + Truncated bool `json:"truncated"` +} + +const GrepToolName = "grep" + +type GrepParams struct { + Pattern string `json:"pattern"` + Path string `json:"path"` + Include string `json:"include"` + LiteralText bool `json:"literal_text"` +} +type GrepResponseMetadata struct { + NumberOfMatches int `json:"number_of_matches"` + Truncated bool `json:"truncated"` +} + +const LSToolName = "ls" + +type LSParams struct { + Path string `json:"path"` + Ignore []string `json:"ignore"` +} + +type LSPermissionsParams struct { + Path string `json:"path"` + Ignore []string `json:"ignore"` +} + +type TreeNode struct { + Name string `json:"name"` + Path string `json:"path"` + Type string `json:"type"` // "file" or "directory" + Children []*TreeNode `json:"children,omitempty"` +} + +type LSResponseMetadata struct { + NumberOfFiles int `json:"number_of_files"` + Truncated bool `json:"truncated"` +} + +const MultiEditToolName = "multiedit" + +type MultiEditOperation struct { + OldString string `json:"old_string"` + NewString string `json:"new_string"` + ReplaceAll bool `json:"replace_all,omitempty"` +} + +type MultiEditParams struct { + FilePath string `json:"file_path"` + Edits []MultiEditOperation `json:"edits"` +} + +type MultiEditPermissionsParams struct { + FilePath string `json:"file_path"` + OldContent string `json:"old_content,omitempty"` + NewContent string `json:"new_content,omitempty"` +} + +type MultiEditResponseMetadata struct { + Additions int `json:"additions"` + Removals int `json:"removals"` + OldContent string `json:"old_content,omitempty"` + NewContent string `json:"new_content,omitempty"` + EditsApplied int `json:"edits_applied"` +} + +const SourcegraphToolName = "sourcegraph" + +type SourcegraphParams struct { + Query string `json:"query"` + Count int `json:"count,omitempty"` + ContextWindow int `json:"context_window,omitempty"` + Timeout int `json:"timeout,omitempty"` +} + +type SourcegraphResponseMetadata struct { + NumberOfMatches int `json:"number_of_matches"` + Truncated bool `json:"truncated"` +} + +const ViewToolName = "view" + +type ViewParams struct { + FilePath string `json:"file_path"` + Offset int `json:"offset"` + Limit int `json:"limit"` +} + +type ViewPermissionsParams struct { + FilePath string `json:"file_path"` + Offset int `json:"offset"` + Limit int `json:"limit"` +} +type ViewResponseMetadata struct { + FilePath string `json:"file_path"` + Content string `json:"content"` +} + +const WriteToolName = "write" + +type WriteParams struct { + FilePath string `json:"file_path"` + Content string `json:"content"` +} + +type WritePermissionsParams struct { + FilePath string `json:"file_path"` + OldContent string `json:"old_content,omitempty"` + NewContent string `json:"new_content,omitempty"` +} +type WriteResponseMetadata struct { + Diff string `json:"diff"` + Additions int `json:"additions"` + Removals int `json:"removals"` +}