Add scratchpad_delete MCP tool
Mirrors the existing scratchpad_* tools end-to-end: catalog schema, dispatch, ToolHost.ScratchpadDelete, and a host method that delegates to scratchpad.Store.Delete and fires scratchpadsChanged() on success so the sidebar refreshes. Missing-pad errors surface rather than being masked. Resolves the [MCP SCRATCHPAD DELETE] TODO item.
This commit is contained in:
@@ -832,6 +832,14 @@ func (h *toolHost) ScratchpadAppend(name, content string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (h *toolHost) ScratchpadDelete(name string) error {
|
||||
err := h.pads.Delete(name)
|
||||
if err == nil && h.scratch != nil {
|
||||
h.scratch.scratchpadsChanged()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (h *toolHost) WhoAmI(callerID string) mcp.WhoAmI {
|
||||
w := mcp.WhoAmI{
|
||||
ProcessID: callerID,
|
||||
@@ -1091,7 +1099,7 @@ func availableToolsForRole(role mcp.CallerRole) []string {
|
||||
"send_input", "send_message", "request_human_attention",
|
||||
"timer_wait", "timer_set", "timer_fire_when_idle_any", "timer_fire_when_idle_all",
|
||||
"timer_cancel", "timer_pause", "timer_resume", "timer_list",
|
||||
"scratchpad_list", "scratchpad_read", "scratchpad_write", "scratchpad_append",
|
||||
"scratchpad_list", "scratchpad_read", "scratchpad_write", "scratchpad_append", "scratchpad_delete",
|
||||
"whoami", "help",
|
||||
}
|
||||
if role == mcp.RoleOrchestrator {
|
||||
@@ -1146,8 +1154,8 @@ func helpFor(topic string) mcp.HelpResponse {
|
||||
case "scratchpads":
|
||||
return mcp.HelpResponse{
|
||||
Topic: "scratchpads",
|
||||
Content: "Project-scoped markdown files. Read returns content + revision; pass that back as expected_revision on write to get last-write-wins-with-detection. Append is unconditional.",
|
||||
RelatedTools: []string{"scratchpad_list", "scratchpad_read", "scratchpad_write", "scratchpad_append"},
|
||||
Content: "Project-scoped markdown files. Read returns content + revision; pass that back as expected_revision on write to get last-write-wins-with-detection. Append is unconditional; delete removes a pad by name.",
|
||||
RelatedTools: []string{"scratchpad_list", "scratchpad_read", "scratchpad_write", "scratchpad_append", "scratchpad_delete"},
|
||||
}
|
||||
case "timers":
|
||||
return mcp.HelpResponse{
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/hjbdev/patterm/internal/preset"
|
||||
"github.com/hjbdev/patterm/internal/scratchpad"
|
||||
)
|
||||
|
||||
@@ -95,3 +97,41 @@ func TestDeletingLastFocusedScratchpadFocusesRunningChild(t *testing.T) {
|
||||
t.Fatalf("focusedID = %q, want pid", st.focusedID)
|
||||
}
|
||||
}
|
||||
|
||||
type scratchpadChangeRecorder struct {
|
||||
count int
|
||||
}
|
||||
|
||||
func (r *scratchpadChangeRecorder) scratchpadsChanged() {
|
||||
r.count++
|
||||
}
|
||||
|
||||
func TestToolHostScratchpadDeleteRemovesPadAndRefreshes(t *testing.T) {
|
||||
t.Setenv("XDG_DATA_HOME", t.TempDir())
|
||||
pads, err := scratchpad.Open("scratchpad-delete-host-test")
|
||||
if err != nil {
|
||||
t.Fatalf("scratchpad.Open: %v", err)
|
||||
}
|
||||
if _, err := pads.Write("doomed.md", "content", ""); err != nil {
|
||||
t.Fatalf("write doomed.md: %v", err)
|
||||
}
|
||||
recorder := &scratchpadChangeRecorder{}
|
||||
host := newToolHost(nil, pads, nil, preset.Set{}, nil, 120, 40)
|
||||
host.scratch = recorder
|
||||
|
||||
if err := host.ScratchpadDelete("doomed.md"); err != nil {
|
||||
t.Fatalf("ScratchpadDelete: %v", err)
|
||||
}
|
||||
if recorder.count != 1 {
|
||||
t.Fatalf("scratchpadsChanged calls = %d, want 1", recorder.count)
|
||||
}
|
||||
if _, _, err := pads.Read("doomed.md"); !errors.Is(err, os.ErrNotExist) {
|
||||
t.Fatalf("read deleted pad error = %v, want os.ErrNotExist", err)
|
||||
}
|
||||
if err := host.ScratchpadDelete("doomed.md"); !errors.Is(err, os.ErrNotExist) {
|
||||
t.Fatalf("delete missing error = %v, want os.ErrNotExist", err)
|
||||
}
|
||||
if recorder.count != 1 {
|
||||
t.Fatalf("scratchpadsChanged calls after failed delete = %d, want 1", recorder.count)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user