# namkhasnh/easy_phone_ai architecture

> Architecture diagram of the GitHub repository namkhasnh/easy_phone_ai, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-11-15). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/namkhasnh/easy_phone_ai
- Repository: https://github.com/namkhasnh/easy_phone_ai

## Overview

EasyPhoneAI is an iOS assistant that turns typed, spoken, or photographed requests into editable task drafts, then executes approved actions through device services. Its backend provides parsing, OCR extraction, account, health, and media APIs, with LLM-backed processing and usage controls. The excerpts show the OCR and review flows and TaskEngine responsibilities; the SOURCE INDEX supports additional module links. The README is empty, and unsampled feature details and some app-to-backend wiring remain uncertain, so those relationships are omitted rather than inferred.

Main entry points: [`EasyPhoneAI/Core/Engine/TaskEngine.swift`](https://github.com/namkhasnh/easy_phone_ai/blob/main/EasyPhoneAI/Core/Engine/TaskEngine.swift) (Task engine), [`backend/app/main.py`](https://github.com/namkhasnh/easy_phone_ai/blob/main/backend/app/main.py) (API application), [`backend/app/services/parse_service.py`](https://github.com/namkhasnh/easy_phone_ai/blob/main/backend/app/services/parse_service.py) (Request parsing), [`backend/app/services/extract_service.py`](https://github.com/namkhasnh/easy_phone_ai/blob/main/backend/app/services/extract_service.py) (OCR extraction)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_client["iOS app"]
  node_app["App shell<br/>[EasyPhoneApp.swift]"]
  node_conversation["Conversation"]
  node_ocr["Photo capture"]
  node_review["Draft review"]
  node_api["API client<br/>[APIClient.swift]"]
end

subgraph group_task["Task workflow"]
  node_taskengine["Task engine<br/>[TaskEngine.swift]"]
  node_draft["Task draft<br/>[TaskDraft.swift]"]
  node_step["Task steps<br/>[TaskStep.swift]"]
  node_fields["Fields and rules<br/>[FieldCatalog.swift]"]
  node_validator["Draft validation<br/>[Validator.swift]"]
  node_approval["Approval hash<br/>[ApprovalHash.swift]"]
  node_executor["Step execution<br/>[StepExecutor.swift]"]
  node_repository[("Draft storage")]
end

subgraph group_device["Device services"]
  node_permissions["Permissions"]
  node_deviceactions["Device actions"]
end

subgraph group_server["Backend APIs"]
  node_backend["API application<br/>[main.py]"]
  node_parse["Request parsing<br/>[parse_service.py]"]
  node_extract["OCR extraction<br/>[extract_service.py]"]
  node_ocrservice["Image OCR<br/>[ocr_service.py]"]
  node_llm["LLM gateway<br/>[llm.py]"]
  node_prompts["Prompt library<br/>[prompts.py]"]
  node_schema["Schema checks<br/>[schema_check.py]"]
  node_metering["Usage metering<br/>[metering.py]"]
  node_health["Health endpoint<br/>[health.py]"]
  node_account["Account endpoint<br/>[me.py]"]
  node_media["Media endpoint<br/>[media.py]"]
end

node_user(("User"))

node_user -->|"opens"| node_app
node_user -->|"submits request"| node_conversation
node_user -->|"chooses photo"| node_ocr
node_ocr -->|"extracts text"| node_api
node_ocr -->|"saves draft"| node_repository
node_ocr -->|"applies extraction"| node_taskengine
node_review -->|"forwards intents"| node_taskengine
node_review -->|"checks access"| node_permissions
node_taskengine -->|"executes step"| node_executor
node_taskengine -->|"saves mutations"| node_repository
node_taskengine -->|"validates draft"| node_validator
node_taskengine -->|"checks approval"| node_approval
node_taskengine -->|"uses catalog"| node_fields
node_taskengine -->|"mutates state"| node_step
node_repository -->|"stores"| node_draft
node_draft -->|"contains"| node_step
node_step -->|"contains"| node_fields
node_executor -->|"requires access"| node_permissions
node_executor -.->|"dispatches actions"| node_deviceactions
node_api -.->|"calls API"| node_backend
node_backend -->|"routes parse"| node_parse
node_backend -->|"routes extract"| node_extract
node_backend -->|"routes health"| node_health
node_backend -->|"routes account"| node_account
node_backend -->|"routes media"| node_media
node_parse -->|"calls model"| node_llm
node_parse -->|"uses prompts"| node_prompts
node_parse -->|"checks output"| node_schema
node_parse -->|"records usage"| node_metering
node_extract -->|"calls model"| node_llm
node_extract -->|"uses prompts"| node_prompts
node_extract -->|"checks output"| node_schema
node_extract -->|"records usage"| node_metering
node_ocrservice -->|"calls model"| node_llm
node_ocrservice -->|"uses prompts"| node_prompts
node_ocrservice -->|"checks output"| node_schema
node_ocrservice -->|"records usage"| node_metering

click node_app "https://github.com/namkhasnh/easy_phone_ai/blob/main/EasyPhoneAI/App/EasyPhoneApp.swift"
click node_conversation "https://github.com/namkhasnh/easy_phone_ai/blob/main/EasyPhoneAI/Features/Conversation/ConversationViewModel.swift"
click node_ocr "https://github.com/namkhasnh/easy_phone_ai/blob/main/EasyPhoneAI/Features/OCR/OCRCaptureViewModel.swift"
click node_review "https://github.com/namkhasnh/easy_phone_ai/blob/main/EasyPhoneAI/Features/Review/ReviewViewModel.swift"
click node_taskengine "https://github.com/namkhasnh/easy_phone_ai/blob/main/EasyPhoneAI/Core/Engine/TaskEngine.swift"
click node_draft "https://github.com/namkhasnh/easy_phone_ai/blob/main/EasyPhoneAI/Core/Models/TaskDraft.swift"
click node_step "https://github.com/namkhasnh/easy_phone_ai/blob/main/EasyPhoneAI/Core/Models/TaskStep.swift"
click node_fields "https://github.com/namkhasnh/easy_phone_ai/blob/main/EasyPhoneAI/Core/Models/FieldCatalog.swift"
click node_validator "https://github.com/namkhasnh/easy_phone_ai/blob/main/EasyPhoneAI/Core/Engine/Validator.swift"
click node_approval "https://github.com/namkhasnh/easy_phone_ai/blob/main/EasyPhoneAI/Core/Engine/ApprovalHash.swift"
click node_executor "https://github.com/namkhasnh/easy_phone_ai/blob/main/EasyPhoneAI/Core/Engine/StepExecutor.swift"
click node_repository "https://github.com/namkhasnh/easy_phone_ai/blob/main/EasyPhoneAI/Core/Services/TaskRepository.swift"
click node_permissions "https://github.com/namkhasnh/easy_phone_ai/blob/main/EasyPhoneAI/Core/Permissions/PermissionManager.swift"
click node_deviceactions "https://github.com/namkhasnh/easy_phone_ai/tree/main/EasyPhoneAI/Core/Services/Live"
click node_api "https://github.com/namkhasnh/easy_phone_ai/blob/main/EasyPhoneAI/Core/Networking/APIClient.swift"
click node_backend "https://github.com/namkhasnh/easy_phone_ai/blob/main/backend/app/main.py"
click node_parse "https://github.com/namkhasnh/easy_phone_ai/blob/main/backend/app/services/parse_service.py"
click node_extract "https://github.com/namkhasnh/easy_phone_ai/blob/main/backend/app/services/extract_service.py"
click node_ocrservice "https://github.com/namkhasnh/easy_phone_ai/blob/main/backend/app/services/ocr_service.py"
click node_llm "https://github.com/namkhasnh/easy_phone_ai/blob/main/backend/app/services/llm.py"
click node_prompts "https://github.com/namkhasnh/easy_phone_ai/blob/main/backend/app/services/prompts.py"
click node_schema "https://github.com/namkhasnh/easy_phone_ai/blob/main/backend/app/services/schema_check.py"
click node_metering "https://github.com/namkhasnh/easy_phone_ai/blob/main/backend/app/services/metering.py"
click node_health "https://github.com/namkhasnh/easy_phone_ai/blob/main/backend/app/routers/health.py"
click node_account "https://github.com/namkhasnh/easy_phone_ai/blob/main/backend/app/routers/me.py"
click node_media "https://github.com/namkhasnh/easy_phone_ai/blob/main/backend/app/routers/media.py"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_app,node_conversation,node_ocr,node_review,node_api,node_user toneBlue
class node_taskengine,node_draft,node_step,node_fields,node_validator,node_approval,node_executor,node_repository toneAmber
class node_permissions,node_deviceactions toneMint
class node_backend,node_parse,node_extract,node_ocrservice,node_llm,node_prompts,node_schema,node_metering,node_health,node_account,node_media toneRose
```

## Components

### iOS app

- [App shell](https://github.com/namkhasnh/easy_phone_ai/blob/main/EasyPhoneAI/App/EasyPhoneApp.swift): `EasyPhoneAI/App/EasyPhoneApp.swift`
- [Conversation](https://github.com/namkhasnh/easy_phone_ai/blob/main/EasyPhoneAI/Features/Conversation/ConversationViewModel.swift): `EasyPhoneAI/Features/Conversation/ConversationViewModel.swift`
- [Photo capture](https://github.com/namkhasnh/easy_phone_ai/blob/main/EasyPhoneAI/Features/OCR/OCRCaptureViewModel.swift): `EasyPhoneAI/Features/OCR/OCRCaptureViewModel.swift`
- [Draft review](https://github.com/namkhasnh/easy_phone_ai/blob/main/EasyPhoneAI/Features/Review/ReviewViewModel.swift): `EasyPhoneAI/Features/Review/ReviewViewModel.swift`
- [API client](https://github.com/namkhasnh/easy_phone_ai/blob/main/EasyPhoneAI/Core/Networking/APIClient.swift): `EasyPhoneAI/Core/Networking/APIClient.swift`

### Task workflow

- [Task engine](https://github.com/namkhasnh/easy_phone_ai/blob/main/EasyPhoneAI/Core/Engine/TaskEngine.swift): `EasyPhoneAI/Core/Engine/TaskEngine.swift`
- [Task draft](https://github.com/namkhasnh/easy_phone_ai/blob/main/EasyPhoneAI/Core/Models/TaskDraft.swift): `EasyPhoneAI/Core/Models/TaskDraft.swift`
- [Task steps](https://github.com/namkhasnh/easy_phone_ai/blob/main/EasyPhoneAI/Core/Models/TaskStep.swift): `EasyPhoneAI/Core/Models/TaskStep.swift`
- [Fields and rules](https://github.com/namkhasnh/easy_phone_ai/blob/main/EasyPhoneAI/Core/Models/FieldCatalog.swift): `EasyPhoneAI/Core/Models/FieldCatalog.swift`
- [Draft validation](https://github.com/namkhasnh/easy_phone_ai/blob/main/EasyPhoneAI/Core/Engine/Validator.swift): `EasyPhoneAI/Core/Engine/Validator.swift`
- [Approval hash](https://github.com/namkhasnh/easy_phone_ai/blob/main/EasyPhoneAI/Core/Engine/ApprovalHash.swift): `EasyPhoneAI/Core/Engine/ApprovalHash.swift`
- [Step execution](https://github.com/namkhasnh/easy_phone_ai/blob/main/EasyPhoneAI/Core/Engine/StepExecutor.swift): `EasyPhoneAI/Core/Engine/StepExecutor.swift`
- [Draft storage](https://github.com/namkhasnh/easy_phone_ai/blob/main/EasyPhoneAI/Core/Services/TaskRepository.swift): `EasyPhoneAI/Core/Services/TaskRepository.swift`

### Device services

- [Permissions](https://github.com/namkhasnh/easy_phone_ai/blob/main/EasyPhoneAI/Core/Permissions/PermissionManager.swift): `EasyPhoneAI/Core/Permissions/PermissionManager.swift`
- [Device actions](https://github.com/namkhasnh/easy_phone_ai/tree/main/EasyPhoneAI/Core/Services/Live): `EasyPhoneAI/Core/Services/Live`

### Backend APIs

- [API application](https://github.com/namkhasnh/easy_phone_ai/blob/main/backend/app/main.py): `backend/app/main.py`
- [Request parsing](https://github.com/namkhasnh/easy_phone_ai/blob/main/backend/app/services/parse_service.py): `backend/app/services/parse_service.py`
- [OCR extraction](https://github.com/namkhasnh/easy_phone_ai/blob/main/backend/app/services/extract_service.py): `backend/app/services/extract_service.py`
- [Image OCR](https://github.com/namkhasnh/easy_phone_ai/blob/main/backend/app/services/ocr_service.py): `backend/app/services/ocr_service.py`
- [LLM gateway](https://github.com/namkhasnh/easy_phone_ai/blob/main/backend/app/services/llm.py): `backend/app/services/llm.py`
- [Prompt library](https://github.com/namkhasnh/easy_phone_ai/blob/main/backend/app/services/prompts.py): `backend/app/services/prompts.py`
- [Schema checks](https://github.com/namkhasnh/easy_phone_ai/blob/main/backend/app/services/schema_check.py): `backend/app/services/schema_check.py`
- [Usage metering](https://github.com/namkhasnh/easy_phone_ai/blob/main/backend/app/services/metering.py): `backend/app/services/metering.py`
- [Health endpoint](https://github.com/namkhasnh/easy_phone_ai/blob/main/backend/app/routers/health.py): `backend/app/routers/health.py`
- [Account endpoint](https://github.com/namkhasnh/easy_phone_ai/blob/main/backend/app/routers/me.py): `backend/app/routers/me.py`
- [Media endpoint](https://github.com/namkhasnh/easy_phone_ai/blob/main/backend/app/routers/media.py): `backend/app/routers/media.py`

### Other components

- **User**

## Connections

- User → App shell: opens
- User → Conversation: submits request
- User → Photo capture: chooses photo (evidence: `EasyPhoneAI/Features/OCR/OCRCaptureViewModel.swift`)
- Photo capture → API client: extracts text (evidence: `EasyPhoneAI/Features/OCR/OCRCaptureViewModel.swift`)
- Photo capture → Draft storage: saves draft (evidence: `EasyPhoneAI/Features/OCR/OCRCaptureViewModel.swift`)
- Photo capture → Task engine: applies extraction (evidence: `EasyPhoneAI/Features/OCR/OCRCaptureViewModel.swift`)
- Draft review → Task engine: forwards intents (evidence: `EasyPhoneAI/Features/Review/ReviewViewModel.swift`)
- Draft review → Permissions: checks access (evidence: `EasyPhoneAI/Features/Review/ReviewViewModel.swift`)
- Task engine → Step execution: executes step (evidence: `EasyPhoneAI/Core/Engine/TaskEngine.swift`)
- Task engine → Draft storage: saves mutations (evidence: `EasyPhoneAI/Core/Engine/TaskEngine.swift`)
- Task engine → Draft validation: validates draft (evidence: `EasyPhoneAI/Core/Engine/TaskEngine.swift`)
- Task engine → Approval hash: checks approval (evidence: `EasyPhoneAI/Core/Engine/TaskEngine.swift`)
- Task engine → Fields and rules: uses catalog (evidence: `EasyPhoneAI/Core/Engine/TaskEngine.swift`)
- Task engine → Task steps: mutates state (evidence: `EasyPhoneAI/Core/Engine/TaskEngine.swift`)
- Draft storage → Task draft: stores (evidence: `EasyPhoneAI/Core/Models/TaskDraft.swift`)
- Task draft → Task steps: contains (evidence: `EasyPhoneAI/Core/Models/TaskDraft.swift`)
- Task steps → Fields and rules: contains (evidence: `EasyPhoneAI/Core/Models/TaskStep.swift`)
- Step execution → Permissions: requires access (evidence: `EasyPhoneAI/Core/Permissions/PermissionManager.swift`)
- Step execution → Device actions: dispatches actions
- API client → API application: calls API
- API application → Request parsing: routes parse (evidence: `backend/app/main.py`)
- API application → OCR extraction: routes extract (evidence: `backend/app/main.py`)
- API application → Health endpoint: routes health (evidence: `backend/app/main.py`)
- API application → Account endpoint: routes account (evidence: `backend/app/main.py`)
- API application → Media endpoint: routes media (evidence: `backend/app/main.py`)
- Request parsing → LLM gateway: calls model (evidence: `backend/app/services/parse_service.py`)
- Request parsing → Prompt library: uses prompts (evidence: `backend/app/services/parse_service.py`)
- Request parsing → Schema checks: checks output (evidence: `backend/app/services/parse_service.py`)
- Request parsing → Usage metering: records usage (evidence: `backend/app/services/parse_service.py`)
- OCR extraction → LLM gateway: calls model (evidence: `backend/app/services/extract_service.py`)
- OCR extraction → Prompt library: uses prompts (evidence: `backend/app/services/extract_service.py`)
- OCR extraction → Schema checks: checks output (evidence: `backend/app/services/extract_service.py`)
- OCR extraction → Usage metering: records usage (evidence: `backend/app/services/extract_service.py`)
- Image OCR → LLM gateway: calls model (evidence: `backend/app/services/ocr_service.py`)
- Image OCR → Prompt library: uses prompts (evidence: `backend/app/services/ocr_service.py`)
- Image OCR → Schema checks: checks output (evidence: `backend/app/services/ocr_service.py`)
- Image OCR → Usage metering: records usage (evidence: `backend/app/services/ocr_service.py`)
