Files
chauncygu 1d4ffa964d Update README.MD and add nano-claude-code v3.0 + original-source-code/src
- README.MD: add original-source-code and nano-claude-code sections, update
  overview table (4 subprojects), add v3.0 news entry, expand comparison table
  with memory/multi-agent/skills dimensions
- nano-claude-code v3.0: multi-agent package (multi_agent/), memory package
  (memory/), skill package (skill/) with built-in /commit and /review skills,
  context compression (compaction.py), tool registry plugin system, diff view,
  17 slash commands, 18 built-in tools, 101 tests (~5000 lines total)
- original-source-code/src: add raw TypeScript source tree (1884 files)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 10:26:29 -07:00

217 lines
7.7 KiB
Python

"""Memory tool registrations: MemorySave, MemoryDelete, MemorySearch.
Importing this module registers the three tools into the central registry.
"""
from __future__ import annotations
from datetime import datetime
from tool_registry import ToolDef, register_tool
from .store import MemoryEntry, save_memory, delete_memory, load_index
from .context import find_relevant_memories
from .scan import scan_all_memories, format_memory_manifest
# ── Tool implementations ───────────────────────────────────────────────────
def _memory_save(params: dict, config: dict) -> str:
"""Save or update a persistent memory entry."""
entry = MemoryEntry(
name=params["name"],
description=params["description"],
type=params["type"],
content=params["content"],
created=datetime.now().strftime("%Y-%m-%d"),
)
scope = params.get("scope", "user")
save_memory(entry, scope=scope)
scope_label = "project" if scope == "project" else "user"
return f"Memory saved: '{entry.name}' [{entry.type}/{scope_label}]"
def _memory_delete(params: dict, config: dict) -> str:
"""Delete a persistent memory entry by name."""
name = params["name"]
scope = params.get("scope", "user")
delete_memory(name, scope=scope)
return f"Memory deleted: '{name}' (scope: {scope})"
def _memory_search(params: dict, config: dict) -> str:
"""Search memories by keyword query with optional AI relevance filtering."""
query = params["query"]
use_ai = params.get("use_ai", False)
max_results = params.get("max_results", 5)
results = find_relevant_memories(
query, max_results=max_results, use_ai=use_ai, config=config
)
if not results:
return f"No memories found matching '{query}'."
lines = [f"Found {len(results)} relevant memory/memories for '{query}':", ""]
for r in results:
freshness = f"{r['freshness_text']}" if r["freshness_text"] else ""
lines.append(
f"[{r['type']}/{r['scope']}] {r['name']}\n"
f" {r['description']}\n"
f" {r['content'][:200]}{'...' if len(r['content']) > 200 else ''}"
f"{freshness}"
)
return "\n\n".join(lines)
def _memory_list(params: dict, config: dict) -> str:
"""List all memory entries with their manifest (type, scope, age, description)."""
headers = scan_all_memories()
if not headers:
return "No memories stored."
scope_filter = params.get("scope", "all")
if scope_filter != "all":
headers = [h for h in headers if h.scope == scope_filter]
if not headers:
return f"No {scope_filter} memories stored."
manifest = format_memory_manifest(headers)
return f"{len(headers)} memory/memories:\n\n{manifest}"
# ── Tool registrations ─────────────────────────────────────────────────────
register_tool(ToolDef(
name="MemorySave",
schema={
"name": "MemorySave",
"description": (
"Save a persistent memory entry as a markdown file with frontmatter. "
"Use for information that should persist across conversations: "
"user preferences, feedback/corrections, project context, or external references. "
"Do NOT save: code patterns, architecture, git history, or task state.\n\n"
"For feedback/project memories, structure content as: "
"rule/fact, then **Why:** and **How to apply:** lines."
),
"input_schema": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Human-readable name (becomes the filename slug)",
},
"type": {
"type": "string",
"enum": ["user", "feedback", "project", "reference"],
"description": (
"user=preferences/role, feedback=guidance on how to work, "
"project=ongoing work/decisions, reference=external system pointers"
),
},
"description": {
"type": "string",
"description": "Short one-line description (used for relevance decisions — be specific)",
},
"content": {
"type": "string",
"description": "Body text. For feedback/project: rule/fact + **Why:** + **How to apply:**",
},
"scope": {
"type": "string",
"enum": ["user", "project"],
"description": (
"'user' (default) = ~/.nano_claude/memory/ shared across projects; "
"'project' = .nano_claude/memory/ local to this project"
),
},
},
"required": ["name", "type", "description", "content"],
},
},
func=_memory_save,
read_only=False,
concurrent_safe=False,
))
register_tool(ToolDef(
name="MemoryDelete",
schema={
"name": "MemoryDelete",
"description": "Delete a persistent memory entry by name.",
"input_schema": {
"type": "object",
"properties": {
"name": {"type": "string", "description": "Name of the memory to delete"},
"scope": {
"type": "string",
"enum": ["user", "project"],
"description": "Scope to delete from (default: 'user')",
},
},
"required": ["name"],
},
},
func=_memory_delete,
read_only=False,
concurrent_safe=False,
))
register_tool(ToolDef(
name="MemorySearch",
schema={
"name": "MemorySearch",
"description": (
"Search persistent memories by keyword. Returns matching entries with "
"content preview and staleness warning for old memories. "
"Set use_ai=true to use AI-powered relevance ranking (costs a small API call)."
),
"input_schema": {
"type": "object",
"properties": {
"query": {"type": "string", "description": "Search query"},
"max_results": {
"type": "integer",
"description": "Maximum results to return (default: 5)",
},
"use_ai": {
"type": "boolean",
"description": "Use AI relevance ranking (default: false = keyword only)",
},
"scope": {
"type": "string",
"enum": ["user", "project", "all"],
"description": "Which scope to search (default: 'all')",
},
},
"required": ["query"],
},
},
func=_memory_search,
read_only=True,
concurrent_safe=True,
))
register_tool(ToolDef(
name="MemoryList",
schema={
"name": "MemoryList",
"description": (
"List all memory entries with type, scope, age, and description. "
"Useful for reviewing what's been remembered before deciding to save or delete."
),
"input_schema": {
"type": "object",
"properties": {
"scope": {
"type": "string",
"enum": ["user", "project", "all"],
"description": "Which scope to list (default: 'all')",
},
},
},
},
func=_memory_list,
read_only=True,
concurrent_safe=True,
))