You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat: edit_note append/prepend auto-create note if not found (#614)
When append or prepend targets a non-existent note, the tool now
creates the file automatically instead of returning an error. This
eliminates silent failures for plugins (like openclaw) that use
edit_note(append) to build daily conversation notes — on the first
message of each day, the note didn't exist yet.
- find_replace and replace_section still require an existing note
- JSON output now includes `fileCreated: bool` in all responses
- Path traversal security check applied to auto-created directories
- Updated error messages to suggest append/prepend for missing notes
🧪 25 unit tests, 14 MCP integration tests, 10 CLI integration tests — all passing
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: phernandez <paul@basicmachines.co>
"""Format helpful error responses for edit_note failures that guide the AI to retry successfully."""
21
50
22
-
# Entity not found errors
51
+
# Entity not found errors — only reachable for find_replace/replace_section
52
+
# because append/prepend auto-create the note when it doesn't exist
23
53
if"Entity not found"inerror_messageor"entity not found"inerror_message.lower():
24
54
returnf"""# Edit Failed - Note Not Found
25
55
26
-
The note with identifier '{identifier}' could not be found. Edit operations require an exact match (no fuzzy matching).
56
+
The note with identifier '{identifier}' could not be found. The `find_replace` and `replace_section` operations require an existing note with content to modify.
57
+
58
+
**Tip:** `append` and `prepend` operations automatically create the note if it doesn't exist.
27
59
28
60
## Suggestions to try:
29
-
1. **Search for the note first**: Use `search_notes("{projector"project-name"}", "{identifier.split("/")[-1]}")` to find similar notes with exact identifiers
30
-
2. **Try different exact identifier formats**:
61
+
1. **Use append/prepend instead**: These operations will create the note automatically if it doesn't exist
62
+
2. **Search for the note first**: Use `search_notes("{projector"project-name"}", "{identifier.split("/")[-1]}")` to find similar notes with exact identifiers
63
+
3. **Try different exact identifier formats**:
31
64
- If you used a permalink like "folder/note-title", try the exact title: "{identifier.split("/")[-1].replace("-", " ").title()}"
32
65
- If you used a title, try the exact permalink format: "{identifier.lower().replace(" ", "-")}"
33
66
- Use `read_note("{projector"project-name"}", "{identifier}")` first to verify the note exists and get the exact identifier
@@ -152,10 +185,10 @@ async def edit_note(
152
185
Must be an exact match - fuzzy matching is not supported for edit operations.
153
186
Use search_notes() or read_note() first to find the correct identifier if uncertain.
154
187
operation: The editing operation to perform:
155
-
- "append": Add content to the end of the note
156
-
- "prepend": Add content to the beginning of the note
157
-
- "find_replace": Replace occurrences of find_text with content
158
-
- "replace_section": Replace content under a specific markdown header
188
+
- "append": Add content to the end of the note (creates the note if it doesn't exist)
189
+
- "prepend": Add content to the beginning of the note (creates the note if it doesn't exist)
190
+
- "find_replace": Replace occurrences of find_text with content (note must exist)
191
+
- "replace_section": Replace content under a specific markdown header (note must exist)
159
192
content: The content to add or use for replacement
160
193
project: Project name to edit in. Optional - server will resolve using hierarchy.
161
194
If unknown, use list_memory_projects() to discover available projects.
0 commit comments