From 82669d3704136f6ae4f7953d0d0dfad9866a1f3f Mon Sep 17 00:00:00 2001 From: roberto Date: Sun, 1 Mar 2026 23:56:32 +0100 Subject: [PATCH] step 2 complete: all request/response models defined and validated Co-Authored-By: Claude Opus 4.6 --- BACKEND_PLAN.md | 4 +-- app/schemas.py | 84 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+), 2 deletions(-) create mode 100644 app/schemas.py diff --git a/BACKEND_PLAN.md b/BACKEND_PLAN.md index 9d88a2f..c2d01ce 100644 --- a/BACKEND_PLAN.md +++ b/BACKEND_PLAN.md @@ -98,8 +98,8 @@ adiuva-api/ - [x] Write `.env.example` - **Outcome:** Runnable FastAPI skeleton (returns 404 on all routes). -### Step 2 — Pydantic schemas (API contracts) -- [ ] Create `app/schemas.py` (mirrors `src/shared/api-types.ts` from Electron repo): +### Step 2 — Pydantic schemas (API contracts) ✅ +- [x] Create `app/schemas.py` (mirrors `src/shared/api-types.ts` from Electron repo): - `ChatRequest`: `message: str`, `context: ChatContext`, `execution_mode: Literal['direct', 'plan']` - `ChatContext`: `user_profile: dict`, `relevant_documents: list[str]`, `recent_tasks: list[dict]`, `conversation_history: list[dict]` - `ChatResponse`: `response: str`, `actions: list[PlanAction]` diff --git a/app/schemas.py b/app/schemas.py new file mode 100644 index 0000000..0737824 --- /dev/null +++ b/app/schemas.py @@ -0,0 +1,84 @@ +"""Pydantic schemas — API request/response contracts. + +Mirrors the TypeScript types from the Electron app (src/shared/api-types.ts). +""" + +from __future__ import annotations + +from typing import Any, Literal + +from pydantic import BaseModel, Field + + +# ── Billing ────────────────────────────────────────────────────────── + +BillingTier = Literal["free", "pro", "power", "team"] + + +# ── Auth ───────────────────────────────────────────────────────────── + +class AuthTokens(BaseModel): + access_token: str + refresh_token: str + expires_at: int + + +class UserProfile(BaseModel): + id: str + email: str + tier: BillingTier + + +# ── Chat ───────────────────────────────────────────────────────────── + +class ChatContext(BaseModel): + user_profile: dict[str, Any] = Field(default_factory=dict) + relevant_documents: list[str] = Field(default_factory=list) + recent_tasks: list[dict[str, Any]] = Field(default_factory=list) + conversation_history: list[dict[str, Any]] = Field(default_factory=list) + + +class PlanAction(BaseModel): + type: Literal[ + "create_record", + "update_record", + "delete_record", + "index_document", + "send_notification", + ] + table: str | None = None + data: dict[str, Any] | None = None + + +class ChatRequest(BaseModel): + message: str + context: ChatContext = Field(default_factory=ChatContext) + execution_mode: Literal["direct", "plan"] = "direct" + + +class ChatResponse(BaseModel): + response: str + actions: list[PlanAction] = Field(default_factory=list) + + +# ── Execution Plans ────────────────────────────────────────────────── + +class PlanStep(BaseModel): + action: str + prompt_template: str | None = None + variables: dict[str, Any] | None = None + data_from_step: int | None = None + + +class ExecutionPlan(BaseModel): + agent: str + steps: list[PlanStep] = Field(default_factory=list) + + +# ── Backup ─────────────────────────────────────────────────────────── + +class BackupMetadata(BaseModel): + version: int + timestamp: int + checksum: str + chunk_count: int