Skip to content

Auto-detect folder path in do_ingest() CLI handler #9

@verkligheten

Description

@verkligheten

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

  1. 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".
  2. Title is "." or "./": Resolves to CWD, which is a directory → triggers folder ingest.
  3. 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.
  4. 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).
  5. 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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions