This repository has been archived on 2026-08-16. You can view files and clone it, but cannot push or open issues or pull requests.
ollie-core/pkg/tools/file/server.go

93 lines
2.5 KiB
Go

package file
import (
"context"
"encoding/json"
"fmt"
"ollie/pkg/tools"
)
// Server implements tools.Server for file_read and file_write.
type Server struct {
// Confirm is called before each operation. Return false to deny.
Confirm func(string) bool
}
// New returns a file Server.
func New() *Server { return &Server{} }
// Decl is the default factory for a file Server. Reassign to override.
var Decl func() tools.Server = func() tools.Server { return New() }
// ListTools implements tools.Server.
func (s *Server) ListTools() ([]tools.ToolInfo, error) {
return tools.FileDefs(), nil
}
// CallTool implements tools.Server.
func (s *Server) CallTool(_ context.Context, tool string, args json.RawMessage) (json.RawMessage, error) {
result, err := s.dispatch(tool, args)
if err != nil {
return json.Marshal(map[string]string{"error": err.Error()})
}
return json.Marshal(map[string]any{
"content": []map[string]string{{"type": "text", "text": result}},
})
}
// Close implements tools.Server (no-op).
func (s *Server) Close() {}
func (s *Server) dispatch(name string, args json.RawMessage) (string, error) {
switch name {
case "file_read":
return s.dispatchRead(args)
case "file_write":
return s.dispatchWrite(args)
default:
return "", fmt.Errorf("unknown file tool: %s", name)
}
}
func (s *Server) dispatchRead(args json.RawMessage) (string, error) {
var a struct {
Path string `json:"path"`
}
if err := json.Unmarshal(args, &a); err != nil {
return "", fmt.Errorf("file_read: bad args: %w", err)
}
if a.Path == "" {
return "", fmt.Errorf("file_read: 'path' is required")
}
if s.Confirm != nil && !s.Confirm("read "+a.Path) {
return "", fmt.Errorf("file_read: denied by user")
}
return Read(a.Path)
}
func (s *Server) dispatchWrite(args json.RawMessage) (string, error) {
var a struct {
Path string `json:"path"`
Content string `json:"content"`
StartLine int `json:"start_line"`
EndLine int `json:"end_line"`
}
if err := json.Unmarshal(args, &a); err != nil {
return "", fmt.Errorf("file_write: bad args: %w", err)
}
if a.Path == "" {
return "", fmt.Errorf("file_write: 'path' is required")
}
prompt := "write " + a.Path
if a.StartLine > 0 {
prompt = fmt.Sprintf("write %s lines %d-%d", a.Path, a.StartLine, a.EndLine)
}
if s.Confirm != nil && !s.Confirm(prompt) {
return "", fmt.Errorf("file_write: denied by user")
}
return Write(a.Path, a.Content, a.StartLine, a.EndLine)
}
var _ tools.Server = (*Server)(nil) // compile-time interface check