Detailed changes
@@ -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
@@ -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]
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
)
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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{
@@ -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() {}
@@ -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
+}
@@ -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"`
+}