Parent Epic
Part of #5 — Integrate Graphify for zero-cost code entity extraction
Task
Modify do_ingest() in agent_notes/commands/memory.py to auto-detect when the title argument is a filesystem folder path and route to wiki_ingest_folder() instead of wiki_ingest().
File
agent_notes/commands/memory.py — function do_ingest() (lines 515-543)
Current Behavior
agent-notes memory ingest "My Title" "My body" "concept1,concept2" "entity1,entity2"
Always calls wiki_ingest() with text-based ingestion.
New Behavior
# Folder path → routes to wiki_ingest_folder (with Graphify auto-extraction)
agent-notes memory ingest /path/to/project "Optional summary"
agent-notes memory ingest ./src "Analyzing source directory"
agent-notes memory ingest ~/code/my-app
# Text title → existing behavior unchanged
agent-notes memory ingest "My Title" "My body text" "concepts" "entities"
Implementation
Modify do_ingest() (line 515-543)
def do_ingest(title: str, body: str, concepts: Optional[list] = None,
entities: Optional[list] = None, tags: Optional[list] = None) -> None:
"""Ingest a source into the wiki backend."""
backend, path = _load_memory_config()
if backend != "wiki":
print("The `ingest` subcommand is only available for wiki storage.")
return
if path is None:
print("Memory path not configured.")
return
# Auto-detect folder path
candidate = Path(title).expanduser().resolve()
if candidate.is_dir():
from ..services.wiki_backend import wiki_ingest_folder
result = wiki_ingest_folder(
path,
folder_path=candidate,
body=body or "",
concepts=concepts,
entities=entities,
tags=tags,
)
source_paths = result.get("source", [])
concept_paths = result.get("concepts", [])
entity_paths = result.get("entities", [])
print(f"{Color.GREEN}Ingested folder: {candidate}{Color.NC}")
for p in source_paths:
print(f" source: {p}")
for p in concept_paths:
print(f" concept: {p}")
for p in entity_paths:
print(f" entity: {p}")
return
# Existing text-based ingest (unchanged)
from ..services.wiki_backend import wiki_ingest
result = wiki_ingest(
path,
title=title,
body=body,
concepts=concepts or [],
entities=entities or [],
tags=tags or [],
)
source_paths = result.get("source", [])
concept_paths = result.get("concepts", [])
entity_paths = result.get("entities", [])
print(f"{Color.GREEN}Ingested: {title}{Color.NC}")
for p in source_paths:
print(f" source: {p}")
for p in concept_paths:
print(f" concept: {p}")
for p in entity_paths:
print(f" entity: {p}")
Edge Cases
- Title looks like a path but isn't a directory (e.g.,
"/tmp/nonexistent"): candidate.is_dir() returns False, falls through to text-based ingest. Title becomes "/tmp/nonexistent".
- Title is "." or "./": Resolves to CWD, which is a directory → triggers folder ingest.
- Title with spaces that's also a valid dir (e.g.,
"My Project"): If ./My Project/ exists as a directory, it triggers folder ingest. This is the desired behavior — directory detection takes priority.
- Title is a file path (not directory):
is_dir() returns False. For file ingest, users should use the existing wiki_ingest_file() path (or we could add is_file() detection too as a follow-up).
- Symlinks:
resolve() follows symlinks. A symlink to a directory is detected as a directory.
CLI Argument Routing (context)
The CLI routing in memory() (line 821-832) passes name as title and extra[0] as body:
elif action == "ingest":
if not name:
do_scan_raw()
exit(0)
body = extra[0] if extra else ""
concepts_csv = extra[1] if extra and len(extra) > 1 else ""
# ...
do_ingest(name, body, concepts=concepts, entities=entities, tags=tags)
So agent-notes memory ingest /path/to/dir "summary" maps to do_ingest("/path/to/dir", "summary"). No changes needed to the CLI routing.
Dependencies
Parent Epic
Part of #5 — Integrate Graphify for zero-cost code entity extraction
Task
Modify
do_ingest()inagent_notes/commands/memory.pyto auto-detect when thetitleargument is a filesystem folder path and route towiki_ingest_folder()instead ofwiki_ingest().File
agent_notes/commands/memory.py— functiondo_ingest()(lines 515-543)Current Behavior
Always calls
wiki_ingest()with text-based ingestion.New Behavior
Implementation
Modify
do_ingest()(line 515-543)Edge Cases
"/tmp/nonexistent"):candidate.is_dir()returns False, falls through to text-based ingest. Title becomes "/tmp/nonexistent"."My Project"): If./My Project/exists as a directory, it triggers folder ingest. This is the desired behavior — directory detection takes priority.is_dir()returns False. For file ingest, users should use the existingwiki_ingest_file()path (or we could addis_file()detection too as a follow-up).resolve()follows symlinks. A symlink to a directory is detected as a directory.CLI Argument Routing (context)
The CLI routing in
memory()(line 821-832) passesnameas title andextra[0]as body:So
agent-notes memory ingest /path/to/dir "summary"maps todo_ingest("/path/to/dir", "summary"). No changes needed to the CLI routing.Dependencies