Skip to Content

SAM AI - UI Module Architecture Diagrams

SAM AI - UI Module Architecture Diagrams

System Architecture Overview

---
title: SAM AI - UI Module System Architecture
---

graph TB
    subgraph "User Layer"
        Browser[Web Browser]
        ClaudeDesktop[Claude Desktop<br/>MCP Client]
    end

    subgraph "ai_sam Module (UI Layer - THIS MODULE)"
        Views[18 View XML Files<br/>Form, Tree, Kanban, Client Actions]
        ChatJS[sam_chat_vanilla_v2.js<br/>9,056 lines Vanilla JS]
        CanvasJS[Canvas Framework<br/>4 JavaScript files]
        WidgetsJS[Widgets & Components<br/>6 JavaScript files]
        UtilsJS[Utilities & State<br/>8 JavaScript files]
        CSS[8 CSS Files<br/>Purple Branding]
        VendorLib[Vendor Library<br/>203 API Provider Icons]
        Templates[QWeb Templates<br/>Chat, Memory, Canvas]
        Menus[Consolidated Menus<br/>Single Source of Truth]
    end

    subgraph "ai_sam_base Module (Data Layer - SEPARATE)"
        Controllers[10 HTTP Controllers<br/>67 REST Endpoints]
        Models[43 Python Models<br/>Business Logic]
        Security[Access Control<br/>20 Rules]
    end

    subgraph "ai_sam_workflows_base Module (Workflow Data)"
        WorkflowModels[15 Workflow Models<br/>Canvas, Executions, Templates]
        N8NIntegration[N8N Integration<br/>195 Node Types]
    end

    subgraph "External Systems"
        ChromaDB[(ChromaDB<br/>Vector Storage)]
        ApacheAGE[(PostgreSQL + AGE<br/>Graph Database)]
        ClaudeAPI[Claude API]
        OpenAIAPI[OpenAI API]
        GoogleAPI[Google AI APIs]
        MCPServers[Generated MCP Servers<br/>Standalone Python]
    end

    %% User interactions
    Browser --> Views
    Browser --> ChatJS
    Browser --> CanvasJS
    ClaudeDesktop -.->|MCP Protocol| MCPServers

    %% UI Layer connections
    Views --> Menus
    Views --> Templates
    ChatJS --> WidgetsJS
    ChatJS --> UtilsJS
    CanvasJS --> UtilsJS
    ChatJS --> CSS
    Views --> VendorLib

    %% Backend connections
    ChatJS -->|AJAX/RPC| Controllers
    CanvasJS -->|AJAX/RPC| Controllers
    WidgetsJS -->|AJAX/RPC| Controllers
    Controllers --> Models
    Controllers --> Security
    Models --> WorkflowModels

    %% External connections
    Models -.->|Vector Search| ChromaDB
    Models -.->|Graph Queries| ApacheAGE
    Models -.->|AI Requests| ClaudeAPI
    Models -.->|AI Requests| OpenAIAPI
    Models -.->|AI Requests| GoogleAPI
    MCPServers -.->|Odoo RPC| Models

    %% Styling
    classDef uiLayer fill:#e1f5ff,stroke:#01579b,stroke-width:2px
    classDef dataLayer fill:#e8f5e9,stroke:#1b5e20,stroke-width:2px
    classDef workflowLayer fill:#fff9c4,stroke:#f57f17,stroke-width:2px
    classDef external fill:#ffebee,stroke:#b71c1c,stroke-width:1px,stroke-dasharray: 5 5
    classDef user fill:#f3e5f5,stroke:#4a148c,stroke-width:2px

    class Views,ChatJS,CanvasJS,WidgetsJS,UtilsJS,CSS,VendorLib,Templates,Menus uiLayer
    class Controllers,Models,Security dataLayer
    class WorkflowModels,N8NIntegration workflowLayer
    class ChromaDB,ApacheAGE,ClaudeAPI,OpenAIAPI,GoogleAPI,MCPServers external
    class Browser,ClaudeDesktop user

Platform Skin Architecture (Migration 2025-11-30)

---
title: Platform Skin Architecture - UI/Data Layer Separation
---

flowchart LR
    subgraph "Before Migration (Legacy)"
        OldModule[ai_sam<br/>Monolithic Module]
        OldModule --> OldPython[43 Python Models]
        OldModule --> OldControllers[10 Controllers]
        OldModule --> OldViews[18 View Files]
        OldModule --> OldJS[JavaScript Assets]
    end

    subgraph "After Migration (Current - 2025-11-30)"
        direction TB

        subgraph "ai_sam (UI-Only Layer)"
            UIViews[18 View XML Files<br/>ONLY UI DEFINITIONS]
            UIStatic[Static Assets<br/>JavaScript, CSS, Icons]
            UITemplates[QWeb Templates]
            UIMenus[Menu Definitions]

            UIViews --> UIStatic
            UIViews --> UITemplates
            UIViews --> UIMenus
        end

        subgraph "ai_sam_base (Data Layer)"
            DataModels[43 Python Models<br/>ALL BUSINESS LOGIC]
            DataControllers[10 HTTP Controllers<br/>ALL ENDPOINTS]
            DataSecurity[Access Control]

            DataModels --> DataControllers
            DataModels --> DataSecurity
        end

        UIViews -->|Depends on| DataModels
        UIStatic -->|AJAX/RPC Calls| DataControllers
    end

    OldModule ==>|Migration| UIViews
    OldModule ==>|Migration| DataModels

    style OldModule fill:#ffcdd2,stroke:#c62828,stroke-width:2px
    style UIViews fill:#c8e6c9,stroke:#2e7d32,stroke-width:2px
    style DataModels fill:#81c784,stroke:#1b5e20,stroke-width:2px

Benefits:
- Separation of Concerns: UI changes don't require Python restarts
- Independent Updates: Update views without affecting business logic
- Clearer Dependencies: ai_sam depends on ai_sam_base (unidirectional)
- Easier Testing: Test business logic without UI complexity


View Layer Architecture (18 XML Files)

---
title: SAM AI - View Layer Structure
---

graph TB
    Root[sam_ai_menus_consolidated.xml<br/>Root Menu Structure]

    subgraph "Main Views (13 Files)"
        ChatView[sam_ai_chat_v2_action.xml<br/>Client Action - Chat Interface]
        APIProviderView[api_service_provider_views.xml<br/>8-Tab Progressive Disclosure]
        MemoryDashView[ai_memory_dashboard_simple.xml<br/>Client Action - Memory Stats]
        MCPView[mcp_server_config_views.xml<br/>MCP Server Generation]
        PowerPromptsView[sam_mode_context_view.xml<br/>Hierarchical AI Agents]
        CostView[ai_service_cost_comparison_views.xml<br/>Pivot/Graph Cost Analysis]
        WorkspaceView[ai_workspace_views.xml<br/>Team Collaboration]
        ConvReaderView[ai_conversation_reader_views.xml<br/>Conversation Browser]
        ProviderModelView[ai_provider_model_views.xml<br/>AI Model Config]
        ConvView[ai_conversation_views.xml<br/>Conversation Management]
        MessageView[ai_conversation_message_views.xml<br/>Message Display]
        ServiceView[ai_service_views.xml<br/>AI Service Config]
        CredsView[api_credentials_views.xml<br/>Encrypted API Keys]
    end

    subgraph "Memory Views (5 Files)"
        MemoryGraphView[memory_graph_simple.xml<br/>Vis.js Graph Template]
        VectorView[ai_memory_vector_views.xml<br/>ChromaDB Vectors]
        ConnectionView[ai_memory_connection_views.xml<br/>Graph Connections]
        EntityView[ai_memory_entity_views.xml<br/>Graph Entities]
        AccessLogView[ai_memory_access_log_views.xml<br/>Access Auditing]
    end

    Root --> ChatView
    Root --> APIProviderView
    Root --> MemoryDashView
    Root --> MCPView
    Root --> PowerPromptsView
    Root --> CostView
    Root --> WorkspaceView
    Root --> ConvReaderView

    APIProviderView --> CredsView
    ChatView --> ConvView
    ConvView --> MessageView
    ChatView --> ServiceView
    ServiceView --> ProviderModelView

    MemoryDashView --> MemoryGraphView
    MemoryDashView --> VectorView
    MemoryDashView --> ConnectionView
    MemoryDashView --> EntityView
    MemoryDashView --> AccessLogView

    classDef mainView fill:#e1f5ff,stroke:#01579b,stroke-width:2px
    classDef memoryView fill:#f3e5f5,stroke:#4a148c,stroke-width:2px
    classDef rootView fill:#fff9c4,stroke:#f57f17,stroke-width:2px

    class ChatView,APIProviderView,MCPView,PowerPromptsView,CostView,WorkspaceView,ConvReaderView,ProviderModelView,ConvView,MessageView,ServiceView,CredsView mainView
    class MemoryDashView,MemoryGraphView,VectorView,ConnectionView,EntityView,AccessLogView memoryView
    class Root rootView

JavaScript Architecture (18 Files)

---
title: SAM AI - JavaScript Module Structure
---

graph TB
    subgraph "Entry Point"
        ChatMain[sam_chat_vanilla_v2.js<br/>9,056 lines<br/>Main Chat Interface]
    end

    subgraph "Core Frameworks (4 Files)"
        CanvasEngine[canvas_engine.js<br/>HTML5 Canvas Rendering]
        CanvasSizer[canvas_sizer.js<br/>Coordinate Transforms]
        CanvasNodeMgr[canvas_node_manager.js<br/>Node CRUD Operations]
        PlatformLoader[platform_loader.js<br/>Platform Adapters]
    end

    subgraph "Widgets & Components (6 Files)"
        ChatBubble[chat_bubble_widget.js<br/>Chat Launcher<br/>Re-enabled 2025-12-04]
        TokenCounter[token_counter_widget.js<br/>Token Display<br/>Re-enabled 2025-12-04]
        CostAnalysis[cost_analysis.js<br/>Cost Intelligence]
        WorkspaceMgr[workspace_manager.js<br/>Team Collaboration]
        ConvReader[conversation_reader.js<br/>Conversation Browser]
        HierarchicalAgents[hierarchical_agents.js<br/>Power Prompts UI]
    end

    subgraph "Utilities & State (8 Files)"
        MCPGen[mcp_server_generator.js<br/>MCP Server Generation]
        MemoryGraphVis[memory_graph_vis.js<br/>Vis.js Integration]
        APIProviderTabs[api_provider_tabs.js<br/>8-Tab Progressive Disclosure]
        MemoryDash[memory_dashboard.js<br/>Memory Statistics]
        DebugLogger[debug_logger.js<br/>Frontend Logging]
        StateMgr[state_manager.js<br/>Proxy-Based Reactivity]
        Utils[utils.js<br/>Utility Functions]
    end

    %% Entry point connections
    ChatMain --> ChatBubble
    ChatMain --> TokenCounter
    ChatMain --> StateMgr
    ChatMain --> Utils

    %% Canvas framework connections
    CanvasEngine --> CanvasSizer
    CanvasEngine --> CanvasNodeMgr
    CanvasEngine --> PlatformLoader
    PlatformLoader --> Utils

    %% Widget connections
    ChatBubble --> StateMgr
    TokenCounter --> StateMgr
    CostAnalysis --> Utils
    WorkspaceMgr --> StateMgr
    ConvReader --> Utils
    HierarchicalAgents --> Utils

    %% Utility connections
    MCPGen --> Utils
    MemoryGraphVis --> MemoryDash
    APIProviderTabs --> StateMgr
    MemoryDash --> StateMgr
    DebugLogger --> Utils

    %% Styling
    classDef entryPoint fill:#714B67,color:#fff,stroke:#4a148c,stroke-width:3px
    classDef framework fill:#e1f5ff,stroke:#01579b,stroke-width:2px
    classDef widget fill:#fff9c4,stroke:#f57f17,stroke-width:2px
    classDef utility fill:#e8f5e9,stroke:#1b5e20,stroke-width:2px

    class ChatMain entryPoint
    class CanvasEngine,CanvasSizer,CanvasNodeMgr,PlatformLoader framework
    class ChatBubble,TokenCounter,CostAnalysis,WorkspaceMgr,ConvReader,HierarchicalAgents widget
    class MCPGen,MemoryGraphVis,APIProviderTabs,MemoryDash,DebugLogger,StateMgr,Utils utility

Vanilla JavaScript State Management (Proxy-Based Reactivity)

---
title: Reactive State Management - Proxy Pattern
---

sequenceDiagram
    actor User
    participant DOM as DOM Elements
    participant Proxy as State Proxy
    participant StateMap as STATE_TO_DOM_MAP
    participant Updaters as DOM Updaters

    User->>DOM: Interacts (e.g., sends message)
    DOM->>Proxy: Update state property<br/>chatState.messages = [...]

    activate Proxy
    Note over Proxy: Proxy set trap intercepts
    Proxy->>Proxy: target[property] = value
    Proxy->>StateMap: Lookup updaters for 'messages'

    StateMap-->>Proxy: [renderMessages, updateTokenCount, ...]

    loop For each updater
        Proxy->>Updaters: Execute updater(value)
        Updaters->>DOM: Update DOM elements
    end

    deactivate Proxy

    DOM-->>User: Visual feedback (updated UI)

    Note over Proxy,StateMap: Automatic reactivity<br/>No manual DOM manipulation needed

Implementation Example:

// state_manager.js
const STATE_TO_DOM_MAP = {
    messages: [
        (messages) => renderMessageList(messages),
        (messages) => updateTokenCount(messages),
        (messages) => updateScrollPosition()
    ],
    isStreaming: [
        (streaming) => toggleSpinner(streaming),
        (streaming) => disableSendButton(streaming)
    ],
    activeConversationId: [
        (id) => switchConversationTab(id),
        (id) => loadConversationHistory(id)
    ]
};

const chatState = new Proxy({
    messages: [],
    isStreaming: false,
    activeConversationId: null,
    tokenCount: 0
}, {
    set(target, property, value) {
        target[property] = value;

        // Automatically trigger all registered updaters
        STATE_TO_DOM_MAP[property]?.forEach(updater => {
            try {
                updater(value);
            } catch (error) {
                console.error(`Error updating ${property}:`, error);
            }
        });

        return true;
    }
});

Chat Interface User Flow

---
title: Chat Interface V2 - User Interaction Flow
---

stateDiagram-v2
    [*] --> ChatBubble: User opens page

    state ChatBubble {
        [*] --> Minimized: Bubble visible
        Minimized --> Expanded: Click bubble
        Expanded --> Minimized: Click minimize
    }

    ChatBubble --> ChatInterface: Click bubble

    state ChatInterface {
        [*] --> SelectConversation: Load conversations

        state SelectConversation {
            [*] --> ConversationList: Display tabs
            ConversationList --> NewConversation: Click "New"
            ConversationList --> ExistingConversation: Click tab
        }

        SelectConversation --> ComposeMessage

        state ComposeMessage {
            [*] --> TypeMessage: User types
            TypeMessage --> AttachFiles: Optional
            AttachFiles --> TokenCounter: Auto-calculate
            TokenCounter --> ReadyToSend: Show cost estimate
        }

        ComposeMessage --> SendMessage: Click send

        state SendMessage {
            [*] --> StreamResponse: SSE connection
            StreamResponse --> RenderMarkdown: Chunk received
            RenderMarkdown --> UpdateMemory: Save to memory
            UpdateMemory --> Complete: Stream ends
        }

        SendMessage --> ComposeMessage: Continue conversation
        SendMessage --> SelectConversation: Switch conversation
    }

    ChatInterface --> [*]: Close chat

    note right of ChatBubble
        Re-enabled 2025-12-04
        Floating launcher
        Minimize/Maximize
    end note

    note right of TokenCounter
        Re-enabled 2025-12-04
        Shows input/output tokens
        Estimates cost before send
    end note

    note right of StreamResponse
        Real-time SSE streaming
        Markdown rendered as received
        Syntax highlighting applied
    end note

Memory System Architecture

---
title: Dual Database Memory System
---

graph TB
    subgraph "Frontend (ai_sam)"
        ChatUI[Chat Interface]
        MemoryDashUI[Memory Dashboard]
        GraphVisUI[Vis.js Graph Visualization]
    end

    subgraph "Backend (ai_sam_base)"
        MemoryService[Memory Service<br/>Python Business Logic]
        VectorEmbedder[Vector Embedder<br/>Sentence Transformers]
        GraphBuilder[Graph Builder<br/>Entity Extraction]
    end

    subgraph "ChromaDB (Vector Database)"
        Collections[Collections<br/>Per-User/Workspace]
        Vectors[Vector Embeddings<br/>768-dimensional]
        VectorSearch[Similarity Search<br/>Cosine Distance]
    end

    subgraph "PostgreSQL + Apache AGE (Graph Database)"
        Entities[Entities<br/>Users, Concepts, Topics]
        Connections[Connections<br/>Relationships with Weights]
        GraphQueries[Graph Traversal<br/>Cypher Queries]
    end

    %% Frontend connections
    ChatUI -->|Create memory| MemoryService
    ChatUI -->|Search memory| MemoryService
    MemoryDashUI -->|Load statistics| MemoryService
    GraphVisUI -->|Load graph data| MemoryService

    %% Backend processing
    MemoryService --> VectorEmbedder
    MemoryService --> GraphBuilder

    VectorEmbedder -->|Store embeddings| Collections
    VectorEmbedder -->|Query| VectorSearch
    VectorSearch -->|Return similar| Vectors

    GraphBuilder -->|Create entities| Entities
    GraphBuilder -->|Create connections| Connections
    GraphBuilder -->|Query relationships| GraphQueries
    GraphQueries -->|Return paths| Connections

    %% Retrieval flow
    Vectors -->|Semantic results| MemoryService
    Connections -->|Relationship results| MemoryService
    MemoryService -->|Merged results| ChatUI

    classDef frontend fill:#e1f5ff,stroke:#01579b,stroke-width:2px
    classDef backend fill:#e8f5e9,stroke:#1b5e20,stroke-width:2px
    classDef vectorDB fill:#fff9c4,stroke:#f57f17,stroke-width:2px
    classDef graphDB fill:#f3e5f5,stroke:#4a148c,stroke-width:2px

    class ChatUI,MemoryDashUI,GraphVisUI frontend
    class MemoryService,VectorEmbedder,GraphBuilder backend
    class Collections,Vectors,VectorSearch vectorDB
    class Entities,Connections,GraphQueries graphDB

Memory Creation Flow:

---
title: Memory Creation and Storage
---

sequenceDiagram
    actor User
    participant Chat as Chat Interface
    participant MemSvc as Memory Service
    participant Embedder as Vector Embedder
    participant GraphBuilder as Graph Builder
    participant ChromaDB
    participant ApacheAGE

    User->>Chat: Sends message
    Chat->>MemSvc: Store conversation

    par Vector Processing
        MemSvc->>Embedder: Generate embedding
        Embedder->>Embedder: Sentence Transformers<br/>768-dim vector
        Embedder->>ChromaDB: Store vector + metadata
        ChromaDB-->>MemSvc: Vector ID
    and Graph Processing
        MemSvc->>GraphBuilder: Extract entities
        GraphBuilder->>GraphBuilder: NER + Relationship Extraction
        GraphBuilder->>ApacheAGE: Create entities + connections
        ApacheAGE-->>MemSvc: Graph node IDs
    end

    MemSvc-->>Chat: Memory stored successfully
    Chat-->>User: Confirmation

Memory Retrieval Flow:

---
title: Memory Retrieval with Dual Search
---

sequenceDiagram
    actor User
    participant Chat as Chat Interface
    participant MemSvc as Memory Service
    participant ChromaDB
    participant ApacheAGE

    User->>Chat: Asks question about past
    Chat->>MemSvc: Search memory(query)

    par Semantic Search
        MemSvc->>ChromaDB: Vector similarity search
        ChromaDB-->>MemSvc: Top 10 similar memories
    and Graph Search
        MemSvc->>ApacheAGE: Graph traversal query
        ApacheAGE-->>MemSvc: Connected entities
    end

    MemSvc->>MemSvc: Merge + Rank results
    MemSvc-->>Chat: Ranked memory list
    Chat->>Chat: Inject into prompt context
    Chat-->>User: AI response with memory context

Canvas Framework Architecture

---
title: Canvas Framework - Platform-Agnostic Design
---

graph TB
    subgraph "Platform Adapters"
        OdooPlatform[Odoo Platform Adapter]
        N8NPlatform[N8N Platform Adapter]
        FuturePlatform[Future Platform Adapter]
    end

    subgraph "Canvas Core (Platform-Agnostic)"
        CanvasEngine[Canvas Engine<br/>HTML5 Canvas Rendering]
        CoordSystem[Coordinate System<br/>World-Screen Transforms]
        NodeManager[Node Manager<br/>CRUD + Undo/Redo]
        ConnectionMgr[Connection Manager<br/>Edge Routing]
        EventHandler[Event Handler<br/>Mouse/Touch/Keyboard]
    end

    subgraph "Rendering Pipeline"
        DrawNodes[Draw Nodes]
        DrawConnections[Draw Connections]
        DrawLabels[Draw Labels]
        DrawPorts[Draw Ports]
    end

    subgraph "Storage Formats"
        OdooJSON[Odoo Workflow JSON]
        N8NJSON[N8N Workflow JSON]
        GenericJSON[Generic Canvas JSON]
    end

    %% Platform loading
    PlatformLoader[platform_loader.js] --> OdooPlatform
    PlatformLoader --> N8NPlatform
    PlatformLoader --> FuturePlatform

    %% Adapter connections
    OdooPlatform --> CanvasEngine
    N8NPlatform --> CanvasEngine
    FuturePlatform --> CanvasEngine

    %% Core connections
    CanvasEngine --> CoordSystem
    CanvasEngine --> NodeManager
    CanvasEngine --> ConnectionMgr
    CanvasEngine --> EventHandler

    %% Rendering pipeline
    CanvasEngine --> DrawNodes
    CanvasEngine --> DrawConnections
    DrawNodes --> DrawLabels
    DrawNodes --> DrawPorts

    %% Storage connections
    NodeManager --> OdooJSON
    NodeManager --> N8NJSON
    NodeManager --> GenericJSON

    classDef platform fill:#e1f5ff,stroke:#01579b,stroke-width:2px
    classDef core fill:#e8f5e9,stroke:#1b5e20,stroke-width:2px
    classDef render fill:#fff9c4,stroke:#f57f17,stroke-width:2px
    classDef storage fill:#f3e5f5,stroke:#4a148c,stroke-width:2px

    class OdooPlatform,N8NPlatform,FuturePlatform,PlatformLoader platform
    class CanvasEngine,CoordSystem,NodeManager,ConnectionMgr,EventHandler core
    class DrawNodes,DrawConnections,DrawLabels,DrawPorts render
    class OdooJSON,N8NJSON,GenericJSON storage

Coordinate Transformation System:

---
title: Canvas Coordinate Transformations
---

flowchart LR
    MouseEvent[Mouse Event<br/>Screen Coordinates<br/>x: 500, y: 300]

    ScreenToWorld[canvas_sizer.js<br/>screenToWorld]

    WorldCoords[World Coordinates<br/>x: 1000, y: 600<br/>Scaled by zoom]

    NodeCheck{Node at<br/>coordinates?}

    MouseEvent --> ScreenToWorld
    ScreenToWorld --> WorldCoords
    WorldCoords --> NodeCheck

    NodeCheck -->|Yes| SelectNode[Select Node]
    NodeCheck -->|No| Pan[Pan Canvas]

    SelectNode --> Render
    Pan --> Render

    Render[Render Loop] --> WorldToScreen[worldToScreen<br/>Convert back for drawing]
    WorldToScreen --> DrawCanvas[Draw on HTML5 Canvas]

    style MouseEvent fill:#e1f5ff
    style WorldCoords fill:#fff9c4
    style DrawCanvas fill:#c8e6c9

API Provider Configuration (8-Tab Progressive Disclosure)

---
title: API Provider 8-Tab Wizard Flow
---

stateDiagram-v2
    [*] --> Tab1General: Open wizard

    state Tab1General {
        [*] --> EnterName: Name field
        EnterName --> SelectProvider: Choose from 203 vendors
        SelectProvider --> SetStatus: Active/Inactive
    }

    Tab1General --> Tab2Authentication: Next

    state Tab2Authentication {
        [*] --> SelectAuthType: API Key / OAuth / Custom
        SelectAuthType --> EnterCredentials: Encrypted storage
        EnterCredentials --> TestConnection: Validate
    }

    Tab2Authentication --> Tab3Models: Next

    state Tab3Models {
        [*] --> LoadAvailableModels: Fetch from provider
        LoadAvailableModels --> SelectModels: GPT-4, Claude, etc.
        SelectModels --> SetDefaultModel: Choose default
    }

    Tab3Models --> Tab4Endpoints: Next

    state Tab4Endpoints {
        [*] --> ConfigureBaseURL: Base API URL
        ConfigureBaseURL --> ConfigureEndpoints: Chat, Embeddings, etc.
        ConfigureEndpoints --> SetHeaders: Custom headers
    }

    Tab4Endpoints --> Tab5RateLimits: Next

    state Tab5RateLimits {
        [*] --> SetRequestLimit: Requests per period
        SetRequestLimit --> SetPeriod: Minute/Hour/Day
        SetPeriod --> SetRetry: Retry logic
    }

    Tab5RateLimits --> Tab6Cost: Next

    state Tab6Cost {
        [*] --> EnterInputCost: Cost per million input tokens
        EnterInputCost --> EnterOutputCost: Cost per million output tokens
        EnterOutputCost --> SetBudget: Optional budget alerts
    }

    Tab6Cost --> Tab7Advanced: Next

    state Tab7Advanced {
        [*] --> SetTimeout: Request timeout
        SetTimeout --> ConfigureProxy: Optional proxy
        ConfigureProxy --> CustomParams: Custom parameters
    }

    Tab7Advanced --> Tab8Testing: Next

    state Tab8Testing {
        [*] --> WriteSampleRequest: Test prompt
        WriteSampleRequest --> SendTestRequest: Execute
        SendTestRequest --> ViewResponse: Check result
        ViewResponse --> ValidationResult: Success/Failure
    }

    Tab8Testing --> Save: Save provider
    Save --> [*]: Provider configured

    note right of Tab1General
        203 vendor icons loaded from
        static/vendor_library/_registry/
    end note

    note right of Tab2Authentication
        API keys encrypted using
        Odoo's encryption system
    end note

    note right of Tab8Testing
        Live API testing before save
        Validates credentials and configuration
    end note

MCP Server Generation Flow

---
title: MCP Server Generation and Deployment
---

sequenceDiagram
    actor User
    participant UI as MCP Config UI
    participant MCPGen as mcp_server_generator.js
    participant Backend as ai_sam_base Controller
    participant MCPServer as Generated Python Server
    participant ClaudeDesktop as Claude Desktop

    User->>UI: Create MCP Server Config
    UI->>User: Show wizard (model selection, permissions)
    User->>UI: Select Odoo models (res.partner, sale.order)
    User->>UI: Configure permissions (read-only, CRUD)
    User->>MCPGen: Click "Generate Server"

    MCPGen->>Backend: POST /generate_mcp_server
    Backend->>Backend: Generate Python code<br/>Using MCP SDK templates
    Backend->>Backend: Include selected models<br/>Apply permission rules
    Backend-->>MCPGen: Python server code

    MCPGen->>UI: Display generated code
    UI->>User: Download or deploy options

    alt Local Deployment
        User->>MCPGen: Click "Deploy Locally"
        MCPGen->>Backend: Deploy to systemd
        Backend->>Backend: Create systemd service<br/>Start server
        Backend-->>UI: Server running on localhost:8080
    else Download
        User->>UI: Click "Download"
        UI->>User: mcp_server_odoo.py downloaded
        User->>MCPServer: Manual deployment
    end

    User->>ClaudeDesktop: Configure MCP server URL
    ClaudeDesktop->>MCPServer: Connect via MCP protocol
    MCPServer-->>ClaudeDesktop: Available tools listed

    User->>ClaudeDesktop: Query Odoo data
    ClaudeDesktop->>MCPServer: MCP tool call
    MCPServer->>Backend: Odoo RPC call
    Backend-->>MCPServer: Query results
    MCPServer-->>ClaudeDesktop: Formatted response
    ClaudeDesktop-->>User: Answer with Odoo data

Generated MCP Server Structure:

---
title: Generated MCP Server Architecture
---

graph TB
    subgraph "Generated Server (Python)"
        MCPMain[main.py<br/>MCP Server Entry Point]
        ToolRegistry[tool_registry.py<br/>Registered Tools]
        OdooConnector[odoo_connector.py<br/>Odoo RPC Client]
        PermissionLayer[permissions.py<br/>Access Control]
    end

    subgraph "MCP SDK (Anthropic)"
        MCPServer[MCP Server Class]
        MCPTools[Tool Decorators]
        MCPProtocol[MCP Protocol Handler]
    end

    subgraph "Odoo Backend"
        OdooRPC[Odoo JSON-RPC<br/>Port 8069]
        Models[Odoo Models<br/>res.partner, sale.order]
    end

    subgraph "Claude Desktop"
        ClaudeUI[Claude UI]
        MCPClient[MCP Client]
    end

    %% Server structure
    MCPMain --> ToolRegistry
    MCPMain --> OdooConnector
    MCPMain --> PermissionLayer

    %% MCP SDK integration
    MCPMain --> MCPServer
    ToolRegistry --> MCPTools
    MCPServer --> MCPProtocol

    %% Odoo connection
    OdooConnector --> OdooRPC
    OdooRPC --> Models
    PermissionLayer --> OdooConnector

    %% Claude connection
    ClaudeUI --> MCPClient
    MCPClient --> MCPProtocol
    MCPProtocol --> ToolRegistry

    classDef server fill:#e1f5ff,stroke:#01579b,stroke-width:2px
    classDef sdk fill:#fff9c4,stroke:#f57f17,stroke-width:2px
    classDef odoo fill:#e8f5e9,stroke:#1b5e20,stroke-width:2px
    classDef claude fill:#f3e5f5,stroke:#4a148c,stroke-width:2px

    class MCPMain,ToolRegistry,OdooConnector,PermissionLayer server
    class MCPServer,MCPTools,MCPProtocol sdk
    class OdooRPC,Models odoo
    class ClaudeUI,MCPClient claude

Deployment Architecture

---
title: SAM AI - Production Deployment
---

graph TB
    subgraph "CDN Layer"
        CDN[CDN<br/>Static Assets<br/>JS, CSS, Icons]
    end

    subgraph "Load Balancer"
        LB[Nginx / HAProxy<br/>SSL Termination]
    end

    subgraph "Odoo Application Servers"
        Odoo1[Odoo Instance 1<br/>ai_sam + ai_sam_base]
        Odoo2[Odoo Instance 2<br/>ai_sam + ai_sam_base]
        Odoo3[Odoo Instance 3<br/>ai_sam + ai_sam_base]
    end

    subgraph "Database Layer"
        PGPrimary[(PostgreSQL Primary<br/>+ Apache AGE)]
        PGReplica1[(PostgreSQL Replica 1)]
        PGReplica2[(PostgreSQL Replica 2)]
    end

    subgraph "Memory Systems"
        ChromaDB[(ChromaDB Cluster<br/>Vector Storage)]
        RedisCache[(Redis Cache<br/>Session + State)]
    end

    subgraph "Background Workers"
        Worker1[Celery Worker 1<br/>Async Tasks]
        Worker2[Celery Worker 2<br/>Async Tasks]
        Cron[Odoo Cron<br/>Scheduled Tasks]
    end

    subgraph "External APIs"
        ClaudeAPI[Claude API<br/>Anthropic]
        OpenAIAPI[OpenAI API]
        GoogleAPI[Google AI APIs]
    end

    subgraph "MCP Servers"
        MCPServer1[MCP Server 1<br/>Odoo Contacts]
        MCPServer2[MCP Server 2<br/>Odoo Sales]
        MCPServer3[MCP Server 3<br/>Custom Integration]
    end

    subgraph "Monitoring"
        Prometheus[Prometheus<br/>Metrics]
        Grafana[Grafana<br/>Dashboards]
        Sentry[Sentry<br/>Error Tracking]
    end

    %% User connections
    Users[Web Users<br/>Chat Interface] --> CDN
    Users --> LB
    CDN -.->|Static Assets| Users

    %% Load balancing
    LB --> Odoo1
    LB --> Odoo2
    LB --> Odoo3

    %% Database connections
    Odoo1 --> PGPrimary
    Odoo2 --> PGPrimary
    Odoo3 --> PGPrimary
    PGPrimary --> PGReplica1
    PGPrimary --> PGReplica2

    %% Memory systems
    Odoo1 --> ChromaDB
    Odoo2 --> ChromaDB
    Odoo3 --> ChromaDB
    Odoo1 --> RedisCache
    Odoo2 --> RedisCache
    Odoo3 --> RedisCache

    %% Background workers
    Odoo1 --> Worker1
    Odoo2 --> Worker2
    Odoo1 --> Cron

    %% External APIs
    Worker1 -.->|AI Requests| ClaudeAPI
    Worker1 -.->|AI Requests| OpenAIAPI
    Worker2 -.->|AI Requests| GoogleAPI

    %% MCP servers
    MCPServer1 -.->|Odoo RPC| Odoo1
    MCPServer2 -.->|Odoo RPC| Odoo2
    MCPServer3 -.->|Odoo RPC| Odoo3
    Claude[Claude Desktop] -.->|MCP Protocol| MCPServer1
    Claude -.->|MCP Protocol| MCPServer2
    Claude -.->|MCP Protocol| MCPServer3

    %% Monitoring
    Odoo1 -.->|Metrics| Prometheus
    Odoo2 -.->|Metrics| Prometheus
    Odoo3 -.->|Metrics| Prometheus
    Prometheus --> Grafana
    Odoo1 -.->|Errors| Sentry
    Odoo2 -.->|Errors| Sentry
    Odoo3 -.->|Errors| Sentry

    classDef frontend fill:#e1f5ff,stroke:#01579b,stroke-width:2px
    classDef backend fill:#e8f5e9,stroke:#1b5e20,stroke-width:2px
    classDef database fill:#fff9c4,stroke:#f57f17,stroke-width:2px
    classDef external fill:#ffebee,stroke:#b71c1c,stroke-width:1px,stroke-dasharray: 5 5
    classDef monitoring fill:#f3e5f5,stroke:#4a148c,stroke-width:2px

    class Users,CDN,LB frontend
    class Odoo1,Odoo2,Odoo3,Worker1,Worker2,Cron backend
    class PGPrimary,PGReplica1,PGReplica2,ChromaDB,RedisCache database
    class ClaudeAPI,OpenAIAPI,GoogleAPI,MCPServer1,MCPServer2,MCPServer3,Claude external
    class Prometheus,Grafana,Sentry monitoring

File Permission System (ai.access.gate)

---
title: AI Access Gate - File Permission Flow (2025-12-17)
---

sequenceDiagram
    actor User
    participant Chat as Chat Interface
    participant Brain as ai_brain.py
    participant Gate as ai.access.gate
    participant Tools as SAM Tools
    participant FileSystem as Local Files

    User->>Chat: What is in D:/MyFolder?
    Chat->>Brain: send_message_streaming()
    Brain->>Brain: Detect file keyword → Load tools

    Brain->>Gate: check_path_access(path, user_id)

    alt Path Already Approved
        Gate-->>Brain: {allowed: true, approved_path: "D:\MyFolder/**"}
        Brain->>Tools: Execute list_directory
        Tools->>FileSystem: Read directory
        FileSystem-->>Tools: File listing
        Tools-->>Brain: Tool result
        Brain-->>Chat: Stream response with file list
    else Path Not Approved
        Gate->>Gate: Create pending permission
        Gate-->>Brain: {needs_approval: true, permission_request: {...}}
        Brain-->>Chat: permission_required event
        Chat->>User: Show permission popup
        User->>Chat: Click "Allow All in Folder"
        Chat->>Gate: action_approve_recursive()
        Gate->>Gate: Save path/** with state=approved_recursive
        Gate-->>Chat: {success: true}
        Note over Chat,Brain: User resends message or continues
    end

Key Components:

---
title: ai.access.gate Model Structure
---

classDiagram
    class AIAccessGate {
        +Many2one user_id
        +Char path
        +Selection state
        +Datetime approved_at
        +Datetime denied_at
        +check_path_access(path, user_id)
        +action_approve()
        +action_approve_recursive()
        +action_deny()
        +get_approved_paths(user_id)
        -_find_approved_path(path, user_id)
        -_normalize_path(path)
    }

    class State {
        <<enumeration>>
        pending
        approved
        approved_recursive
        denied
        expired
    }

    AIAccessGate --> State : state

    note for AIAccessGate "Uses sudo() throughout to avoid\nOdoo permission check recursion"

Permission Matching Logic:
- Exact match: D:\MyFolder matches D:\MyFolder
- Recursive match: D:\MyFolder\sub\file.txt matches D:\MyFolder/**
- Wildcard match: Uses fnmatch for pattern matching


Agent System Architecture (2025-12-17)

---
title: Agent Selection and Behavior Flow
---

flowchart TB
    subgraph "Frontend (sam_chat_vanilla_v2.js)"
        AgentSelector[Agent Selector Dropdown]
        ChatInput[Chat Input]
    end

    subgraph "Controller (sam_ai_chat_controller.py)"
        GetAgent[Load agent_id from conversation]
        PassAgent[Pass agent_id to brain]
    end

    subgraph "Brain (ai_brain.py)"
        LoadAgent[Load ai.agent.registry record]
        BuildPrompt[_build_system_prompt]
        LoadTools[Load tools]
    end

    subgraph "Agent Components"
        AgentPrompt[Agent System Prompt]
        AgentKnowledge[Agent Knowledge Base]
        AgentTools[Agent Tool Config]
    end

    subgraph "Output"
        CustomBehavior[Agent-Specific AI Response]
    end

    AgentSelector -->|Select "Sales"| ChatInput
    ChatInput -->|conversation_id| GetAgent
    GetAgent -->|agent_id| PassAgent
    PassAgent -->|agent_id| LoadAgent

    LoadAgent --> BuildPrompt
    LoadAgent --> LoadTools

    BuildPrompt --> AgentPrompt
    BuildPrompt --> AgentKnowledge
    LoadTools --> AgentTools

    AgentPrompt --> CustomBehavior
    AgentKnowledge --> CustomBehavior
    AgentTools --> CustomBehavior

    classDef frontend fill:#e1f5ff,stroke:#01579b,stroke-width:2px
    classDef controller fill:#fff9c4,stroke:#f57f17,stroke-width:2px
    classDef brain fill:#e8f5e9,stroke:#1b5e20,stroke-width:2px
    classDef agent fill:#f3e5f5,stroke:#4a148c,stroke-width:2px

    class AgentSelector,ChatInput frontend
    class GetAgent,PassAgent controller
    class LoadAgent,BuildPrompt,LoadTools brain
    class AgentPrompt,AgentKnowledge,AgentTools,CustomBehavior agent

Agent Registry Model:

---
title: ai.agent.registry Structure
---

classDiagram
    class AIAgentRegistry {
        +Char name
        +Char display_name
        +Text description
        +Selection archetype
        +Selection category
        +Char slash_command
        +Char color
        +Char model_name
        +Text tools (JSON)
        +Text capabilities (JSON)
        +Text system_prompt
        +One2many knowledge_ids
        +get_relevant_knowledge(query, max_chunks)
    }

    class AIAgentKnowledge {
        +Many2one agent_id
        +Char name
        +Text content
        +Selection content_type
        +Char source_file
        +Integer sequence
    }

    class Archetype {
        <<enumeration>>
        advisor
        implementer
        gatekeeper
        automator
        enforcer
    }

    AIAgentRegistry "1" --> "*" AIAgentKnowledge : knowledge_ids
    AIAgentRegistry --> Archetype : archetype

What Changes Per Agent:

Component User-Wide Agent-Specific
File Access Permissions ✅ Shared via ai.access.gate
System Prompt ✅ agent.system_prompt
Knowledge Base ✅ agent.knowledge_ids
Tool Configuration ✅ Base tools (read/write/list) Future: Additional specialized tools
AI Model ✅ agent.model_name (optional)

Tool Execution Flow (2025-12-17)

---
title: Tool Execution with Permission Checking
---

sequenceDiagram
    participant Brain as ai_brain.py
    participant OpenAI as OpenAI API
    participant Gate as ai.access.gate
    participant Tools as Tool Executor
    participant FS as File System

    Brain->>OpenAI: Chat request with tools
    OpenAI-->>Brain: tool_use: list_directory(path)

    Brain->>Brain: _execute_tool(list_directory, {path})

    Brain->>Gate: check_path_access(path)

    alt Permission Granted
        Gate-->>Brain: {allowed: true}
        Brain->>Tools: Execute list_directory
        Tools->>FS: os.listdir(path)
        FS-->>Tools: [files...]
        Tools-->>Brain: Tool result JSON
        Brain->>OpenAI: Continue with tool result
        OpenAI-->>Brain: Final response
    else Permission Needed
        Gate-->>Brain: {needs_approval: true}
        Brain-->>Brain: Yield permission_required event
        Note over Brain: Wait for user approval
    end

OpenAI vs Anthropic Tool Format:

---
title: Provider-Specific Tool Message Formats
---

flowchart LR
    subgraph "Anthropic Format"
        A1[role: assistant<br/>content: tool_use blocks]
        A2[role: user<br/>content: tool_result blocks]
        A1 --> A2
    end

    subgraph "OpenAI Format"
        O1[role: assistant<br/>content: null<br/>tool_calls: array]
        O2[role: tool<br/>tool_call_id: xxx<br/>content: result]
        O1 --> O2
    end

    Detect{api_format?}
    Detect -->|anthropic| A1
    Detect -->|openai| O1

Streaming Architecture (SSE)

---
title: SSE Streaming with Transaction Management
---

sequenceDiagram
    participant Browser
    participant Controller as Controller
    participant Cursor as DB Cursor
    participant Brain as Brain
    participant API as AI API

    Browser->>Controller: POST /sam_ai/chat/send_streaming
    Controller->>Controller: Create SSE response

    Controller->>Cursor: with registry.cursor() as cr
    activate Cursor

    Cursor->>Brain: send_message_streaming()
    Brain->>Brain: Load profile, conversation, agent
    Brain->>Brain: Build system prompt

    Note over Brain,Cursor: CRITICAL: Commit before HTTP call
    Brain->>Cursor: env.cr.commit()

    Brain->>API: HTTP request (streaming)

    loop For each chunk
        API-->>Brain: SSE chunk
        Brain-->>Controller: yield {type: chunk}
        Controller-->>Browser: event: chunk
    end

    Brain-->>Controller: yield {type: done}
    Controller->>Cursor: cr.commit()
    deactivate Cursor
    Controller-->>Browser: event: done

Key Fix (2025-12-17): Added self.env.cr.commit() before making HTTP calls to prevent "idle in transaction" deadlocks where the database transaction stayed open while waiting for API responses.


Last Updated: December 17, 2025
Module: ai_sam (UI Layer)
Version: 1.0.0

Recent Updates (2025-12-17):
- Added ai.access.gate file permission system
- Integrated agent system (custom prompts, knowledge, tools)
- Fixed OpenAI tool format handling
- Fixed transaction deadlock in streaming

These diagrams can be rendered in:
- GitHub/GitLab (automatic Mermaid rendering)
- VS Code (Mermaid Preview extension)
- Online: https://mermaid.live

Was this helpful?