Files
alfred/brain/docs/sequence_diagram.md

8.6 KiB

Sequence Diagrams - Agent Media

1. Torrent Search and Download Flow

sequenceDiagram
    autonumber
    participant User
    participant FastAPI as FastAPI Server
    participant Agent
    participant PromptBuilder
    participant LLM as LLM (DeepSeek/Ollama)
    participant Tools as Tool Registry
    participant Memory
    participant Knaben as Knaben API
    participant qBit as qBittorrent

    User->>FastAPI: POST /v1/chat/completions<br/>"Find torrents for Inception 1080p"
    FastAPI->>Agent: step(user_input)
    
    Agent->>Memory: stm.get_recent_history()
    Memory-->>Agent: conversation history
    
    Agent->>PromptBuilder: build_system_prompt(memory)
    PromptBuilder->>Memory: ltm.config, episodic state
    Memory-->>PromptBuilder: context data
    PromptBuilder-->>Agent: system prompt with context
    
    Agent->>LLM: complete(messages)
    LLM-->>Agent: {"action": {"name": "find_torrents", "args": {...}}}
    
    Agent->>Agent: _parse_intent(response)
    Agent->>Tools: execute find_torrents
    Tools->>Knaben: search("Inception 1080p")
    Knaben-->>Tools: torrent results
    
    Tools->>Memory: episodic.store_search_results()
    Memory-->>Tools: stored with indexes (1, 2, 3...)
    
    Tools-->>Agent: {"status": "ok", "torrents": [...]}
    
    Agent->>LLM: complete(messages + tool_result)
    LLM-->>Agent: "I found 5 torrents for Inception..."
    
    Agent->>Memory: stm.add_message("user", input)
    Agent->>Memory: stm.add_message("assistant", response)
    Agent->>Memory: save()
    
    Agent-->>FastAPI: final response
    FastAPI-->>User: JSON response

    Note over User,qBit: User selects a torrent

    User->>FastAPI: POST /v1/chat/completions<br/>"Download the 2nd one"
    FastAPI->>Agent: step(user_input)
    
    Agent->>PromptBuilder: build_system_prompt(memory)
    PromptBuilder->>Memory: episodic.last_search_results
    Note right of Memory: Results still in memory:<br/>1. Inception.2010.1080p...<br/>2. Inception.1080p.BluRay...
    Memory-->>PromptBuilder: context with search results
    PromptBuilder-->>Agent: prompt showing available results
    
    Agent->>LLM: complete(messages)
    LLM-->>Agent: {"action": {"name": "add_torrent_by_index", "args": {"index": 2}}}
    
    Agent->>Tools: execute add_torrent_by_index(index=2)
    Tools->>Memory: episodic.get_result_by_index(2)
    Memory-->>Tools: torrent data with magnet link
    
    Tools->>qBit: add_torrent(magnet_link)
    qBit-->>Tools: success
    
    Tools->>Memory: episodic.add_active_download()
    Tools-->>Agent: {"status": "ok", "torrent_name": "Inception.1080p.BluRay"}
    
    Agent->>LLM: complete(messages + tool_result)
    LLM-->>Agent: "I've added Inception to qBittorrent!"
    
    Agent-->>FastAPI: final response
    FastAPI-->>User: JSON response

2. Folder Configuration Flow

sequenceDiagram
    autonumber
    participant User
    participant FastAPI as FastAPI Server
    participant Agent
    participant LLM as LLM
    participant Tools as Tool Registry
    participant FileManager
    participant Memory
    participant FS as Filesystem

    User->>FastAPI: POST /v1/chat/completions<br/>"Set download folder to /mnt/media/downloads"
    FastAPI->>Agent: step(user_input)
    
    Agent->>LLM: complete(messages)
    LLM-->>Agent: {"action": {"name": "set_path_for_folder", "args": {...}}}
    
    Agent->>Tools: execute set_path_for_folder
    Tools->>FileManager: set_folder_path("download", "/mnt/media/downloads")
    
    FileManager->>FS: Path.exists()?
    FS-->>FileManager: true
    FileManager->>FS: Path.is_dir()?
    FS-->>FileManager: true
    FileManager->>FS: os.access(R_OK)?
    FS-->>FileManager: true
    
    FileManager->>Memory: ltm.set_config("download_folder", path)
    FileManager->>Memory: save()
    Memory->>FS: write ltm.json
    
    FileManager-->>Tools: {"status": "ok", "path": "/mnt/media/downloads"}
    Tools-->>Agent: result
    
    Agent->>LLM: complete(messages + tool_result)
    LLM-->>Agent: "Download folder set to /mnt/media/downloads"
    
    Agent-->>FastAPI: final response
    FastAPI-->>User: JSON response

3. Multi-Tool Workflow (Search Movie → Find Torrents → Download)

sequenceDiagram
    autonumber
    participant User
    participant Agent
    participant LLM as LLM
    participant TMDB as TMDB API
    participant Knaben as Knaben API
    participant qBit as qBittorrent
    participant Memory

    User->>Agent: "Download Dune 2 in 4K"
    
    rect rgb(240, 248, 255)
        Note over Agent,TMDB: Step 1: Identify the movie
        Agent->>LLM: complete(messages)
        LLM-->>Agent: {"action": "find_media_imdb_id", "args": {"media_title": "Dune 2"}}
        Agent->>TMDB: search_movie("Dune 2")
        TMDB-->>Agent: {title: "Dune: Part Two", imdb_id: "tt15239678", year: 2024}
        Agent->>Memory: stm.set_entity("last_media_search", {...})
    end
    
    rect rgb(255, 248, 240)
        Note over Agent,Knaben: Step 2: Search for torrents
        Agent->>LLM: complete(messages + movie_info)
        LLM-->>Agent: {"action": "find_torrents", "args": {"media_title": "Dune Part Two 2024 4K"}}
        Agent->>Knaben: search("Dune Part Two 2024 4K")
        Knaben-->>Agent: [torrent1, torrent2, torrent3...]
        Agent->>Memory: episodic.store_search_results()
    end
    
    rect rgb(240, 255, 240)
        Note over Agent,qBit: Step 3: Add best torrent
        Agent->>LLM: complete(messages + torrents)
        LLM-->>Agent: {"action": "add_torrent_by_index", "args": {"index": 1}}
        Agent->>Memory: episodic.get_result_by_index(1)
        Memory-->>Agent: torrent with magnet
        Agent->>qBit: add_torrent(magnet)
        qBit-->>Agent: success
        Agent->>Memory: episodic.add_active_download()
    end
    
    Agent->>LLM: complete(messages + all_results)
    LLM-->>Agent: "I found Dune: Part Two (2024) and added the 4K torrent to qBittorrent!"
    Agent-->>User: Final response

4. Error Handling Flow

sequenceDiagram
    autonumber
    participant User
    participant Agent
    participant LLM as LLM
    participant Tools as Tool Registry
    participant Memory
    participant API as External API

    User->>Agent: "Download the 5th torrent"
    
    Agent->>LLM: complete(messages)
    LLM-->>Agent: {"action": "add_torrent_by_index", "args": {"index": 5}}
    
    Agent->>Tools: execute add_torrent_by_index(5)
    Tools->>Memory: episodic.get_result_by_index(5)
    
    alt No search results
        Memory-->>Tools: None (no previous search)
        Tools-->>Agent: {"status": "error", "error": "not_found"}
        Agent->>Memory: episodic.add_error("add_torrent_by_index", "not_found")
    else Index out of range
        Memory-->>Tools: None (only 3 results)
        Tools-->>Agent: {"status": "error", "error": "not_found"}
        Agent->>Memory: episodic.add_error("add_torrent_by_index", "not_found")
    end
    
    Agent->>LLM: complete(messages + error)
    LLM-->>Agent: "I couldn't find torrent #5. Please search for torrents first."
    
    Agent-->>User: Error explanation

    Note over User,API: User searches first

    User->>Agent: "Search for Matrix 1999"
    Agent->>API: search("Matrix 1999")
    API-->>Agent: [3 results]
    Agent->>Memory: episodic.store_search_results()
    Agent-->>User: "Found 3 torrents..."

    User->>Agent: "Download the 2nd one"
    Agent->>Memory: episodic.get_result_by_index(2)
    Memory-->>Agent: torrent data ✓
    Agent-->>User: "Added to qBittorrent!"

5. Background Events Flow

sequenceDiagram
    autonumber
    participant User
    participant Agent
    participant Memory
    participant qBit as qBittorrent
    participant LLM as LLM

    Note over qBit,Memory: Background: Download completes
    qBit--)Memory: episodic.complete_download(task_id, file_path)
    Memory->>Memory: add_background_event("download_complete", {...})

    Note over User,LLM: Later: User sends a message
    User->>Agent: "What's new?"
    
    Agent->>Memory: episodic.get_unread_events()
    Memory-->>Agent: [{type: "download_complete", data: {name: "Inception.1080p"}}]
    
    Agent->>Agent: _check_unread_events()
    Note right of Agent: Formats notification:<br/>"Download completed: Inception.1080p"
    
    Agent->>LLM: complete(messages + notification)
    LLM-->>Agent: "Good news! Inception.1080p has finished downloading."
    
    Agent-->>User: Response with notification

Legend

Element Description
rect rgb(...) Grouped steps in a workflow
alt/else Conditional branches
Note Explanatory notes
-->> Response/return
->> Request/call
--)) Async event