diff --git a/.claude/CLAUDE.md b/.claude/CLAUDE.md index 0a590b3..febfc21 100644 --- a/.claude/CLAUDE.md +++ b/.claude/CLAUDE.md @@ -76,7 +76,7 @@ Main Process (Node.js) **Local-first storage, cloud AI.** All user data (clients, projects, tasks, notes, timelines) in local SQLite. AI lives entirely on the FastAPI backend — Electron orchestrator is a thin delegation shell that forwards to `/api/v1/device` WS and dispatches v3 typed stream frames + tool-call ↔ DrizzleExecutor round-trips back to renderer. **IPC channels**: -- `'trpc'` — bidirectional tRPC request/response (all CRUD + auth + agent + memory proxy) +- `'trpc'` — bidirectional tRPC request/response (all CRUD + auth + scout + memory proxy) - `'ai:stream'` — one-way v3 stream frames main → renderer - `'ai:action'` — AI side-effects (e.g. agent auto-creates task) @@ -85,19 +85,19 @@ Main Process (Node.js) - `ipc.ts` — Custom tRPC↔IPC bridge - `store.ts` — electron-store for `FormatPrefs` + `uiLanguage`; exports `getUiLanguage()` - `router/index.ts` — All tRPC sub-routers (~1627 LOC) -- `db/schema.ts` — 10 tables: clients, projects, tasks, timelineEvents, timelineEventDependencies, notes, noteEdits, taskComments, agentRuns, agentRunActions +- `db/schema.ts` — 10 tables: clients, projects, tasks, timelineEvents, timelineEventDependencies, notes, noteEdits, taskComments, scoutRuns, scoutRunActions - `db/index.ts` — Drizzle + better-sqlite3 (WAL), singleton `getDb()`, `initDb()` migrations - `db/notes-backfill.ts` — Startup backfill: generates `aiSummary` for notes with null summary - `ai/orchestrator.ts` — Thin backend-delegation layer (~304 LOC). Connectivity/auth guard → `BackendClient.sendHomeRequest()` / `sendFloatingRequest()` → forwards v3 stream frames to renderer. Also schedules daily-brief regeneration. - `ai/token.ts` — Two-tier token storage (safeStorage + electron-store fallback) -- `agents/agent-scheduler.ts` — Local agent scheduling (filesystem agents) -- `api/backend-client.ts` — WS client to FastAPI: handles tool-call round-trips, v3 stream frame dispatch, journey + agent proxies +- `scouts/scout-scheduler.ts` — Local scout scheduling (filesystem scouts) +- `api/backend-client.ts` — WS client to FastAPI: handles tool-call round-trips, v3 stream frame dispatch, journey + scout proxies - `api/drizzle-executor.ts` — Executes backend-issued tool calls against local SQLite. Wraps results through `formatRow()`/`formatRows()` using user FormatPrefs - `auth/auth-manager.ts` — Login, register, logout, OAuth flow (singleton) - `auth/backup-key.ts` — Device-specific AES-256 backup key (safeStorage, not password-derived) - `auth/locale-defaults.ts` — Detects timezone, date/time format, language from OS locale -**tRPC routers** (in `appRouter`): `health`, `settings`, `clients`, `projects`, `tasks`, `timelineEvents`, `timelineEventDependencies`, `notes`, `noteEdits`, `taskComments`, `ai`, `auth`, `agent` (with `local` / `cloud` / `journey` sub-routers), `memory`. +**tRPC routers** (in `appRouter`): `health`, `settings`, `clients`, `projects`, `tasks`, `timelineEvents`, `timelineEventDependencies`, `notes`, `noteEdits`, `taskComments`, `ai`, `auth`, `scout` (with `local` / `cloud` / `journey` sub-routers), `memory`. **Renderer** (`src/renderer/`): file-based routing via TanStack Router (`routeTree.gen.ts` auto-generated). shadcn/ui new-york theme, neutral colors. Path alias `@/*` → `src/renderer/*`. Notes editor: Milkdown (`@milkdown/crepe`). @@ -107,16 +107,16 @@ Main Process (Node.js) - `forge.config.ts` has cross-compilation hooks (downloads platform-specific native binaries for better-sqlite3) - DB has no foreign key constraints — cascade deletes in tRPC procedures - Timestamps are milliseconds (`Date.getTime()`), not ISO strings -- Notes use `aiSummary` (≤250 char, backend `gpt-4o-mini` via `POST /api/v1/agents/notes/summarize`) for AI navigation — LanceDB fully removed +- Notes use `aiSummary` (≤250 char, backend `gpt-4o-mini` via `POST /api/v1/scouts/notes/summarize`) for AI navigation — LanceDB fully removed - AI note edits go through `noteEdits` HITL table (`type: append|insert|replace`, `status: pending|approved|rejected`); backend tool `propose_note_edit` → drizzle-executor inserts row; user approves/rejects in UI; auto-reject on missing anchor - `checkpoints` table replaced by `timelineEvents` + `timelineEventDependencies` (events are typed `milestone|checkpoint|activity`, with optional dep edges) -- `agentRuns` + `agentRunActions` populated by backend-client on tool_call/run_complete frames; UI reads via `agent.runs` / `agent.runActions` +- `scoutRuns` + `scoutRunActions` populated by backend-client on tool_call/run_complete frames; UI reads via `scout.runs` / `scout.runActions` **Settings Page (shared Electron + Web)**: - Settings page runs in **both** Electron and standalone web SPA. Same React components — no duplication. - **Platform Adapter**: `PlatformProvider` context (`src/renderer/lib/platform.tsx`) exposes `isElectron`/`isWeb`/`hasLocalAgents`/`hasFileDialog`. Components use `usePlatform()` to gate Electron-only features. - **Web build**: `vite.web.config.mts` → `dist-web/`. Entry: `web.html` → `src/renderer/web-main.tsx` (uses `httpBatchLink` via `lib/httpLink.ts` instead of `ipcLink`). -- **Electron-only gating**: Device ID card and local agent filesystem gated behind `platform.isElectron`. On web: visible but disabled, not hidden. +- **Electron-only gating**: Device ID card and local scout filesystem gated behind `platform.isElectron`. On web: visible but disabled, not hidden. - **Gotcha**: Do NOT add Electron-specific settings (server URL, native file pickers) without wrapping in `platform.isElectron`. Same component tree renders on web. **Onboarding Wizard**: @@ -134,7 +134,7 @@ Main Process (Node.js) **i18n (Internationalization)**: - `i18next` + `react-i18next` with bundled JSON translations (no lazy loading). - Config in `src/renderer/i18n.ts`. 5 languages: EN, IT, ES, FR, DE. `SUPPORTED_LANGUAGES` exported for UI selectors. -- Translation files: `src/renderer/locales/{en,it,es,fr,de}/translation.json`. Namespaces: `nav`, `auth`, `tasks`, `settings`, `common`, `errors`, `home`, `timeline`, `projects`, `agents`. +- Translation files: `src/renderer/locales/{en,it,es,fr,de}/translation.json`. Namespaces: `nav`, `auth`, `tasks`, `settings`, `common`, `errors`, `home`, `timeline`, `projects`, `scouts`. - **`common.*` namespace** holds shared labels (`save`, `cancel`, `delete`, `edit`, `add`, `rename`, `saving`, `deleting`, `creating`, `renameDescription`, `deleteTitle`). Check `common.*` before adding new key. - Pluralization uses i18next `_one`/`_other` suffixes. - `LanguageSync` component in `src/renderer/index.tsx` reads persisted `uiLanguage` from electron-store via tRPC on startup, syncs to i18next. @@ -191,8 +191,8 @@ FastAPI app (app/main.py) ├── HTTP Routes (app/api/routes/) — all under /api/v1 │ ├── auth.py — register, login, refresh, profile, OAuth, onboarding, password │ ├── chat.py — POST /chat, /chat/brief, /chat/embed -│ ├── agents.py — catalog, can-create, trigger, notes/summarize -│ ├── agent_setup.py — guided agent setup (journey) +│ ├── scouts.py — catalog, can-create, trigger, notes/summarize +│ ├── scout_setup.py — guided scout setup (journey) │ ├── billing.py — Stripe checkout, webhook, subscription, invoices │ ├── device_ws.py — WS /device (unified streaming endpoint: home, floating, brief, journey) │ └── memory.py — core / relational / forget-all @@ -225,9 +225,9 @@ FastAPI app (app/main.py) └── Models (app/models.py) — SQLAlchemy 2.0 ORM ``` -**HTTP route prefix**: every router included with `prefix="/api/v1"`. So `/api/v1/auth/...`, `/api/v1/chat`, `/api/v1/agents/...`, `/api/v1/memory/...`, `/api/v1/device` (WS). +**HTTP route prefix**: every router included with `prefix="/api/v1"`. So `/api/v1/auth/...`, `/api/v1/chat`, `/api/v1/scouts/...`, `/api/v1/memory/...`, `/api/v1/device` (WS). -**ORM models** (`app/models.py`): `User`, `RefreshToken`, `OAuthAccount`, `Subscription`, `LocalAgentConfig`, `CloudAgentConfig`, `AgentRunLog`, `MemoryCore`, `MemoryAssociative`, `MemoryEpisodic`, `MemoryProactive`, `ExtractionQueue`, `MemoryRelation`, `Plugin`. PostgreSQL (asyncpg + SQLAlchemy 2.0 async). Alembic migrations in `alembic/versions/`. +**ORM models** (`app/models.py`): `User`, `RefreshToken`, `OAuthAccount`, `Subscription`, `LocalScoutConfig`, `CloudScoutConfig`, `ScoutRunLog`, `MemoryCore`, `MemoryAssociative`, `MemoryEpisodic`, `MemoryProactive`, `ExtractionQueue`, `MemoryRelation`, `Plugin`. PostgreSQL (asyncpg + SQLAlchemy 2.0 async). Alembic migrations in `alembic/versions/`. **Lifespan crons** (only if `settings.SCHEDULER_ENABLED`): - `_memory_cron_tick` — hourly: drains Free-tier extraction queue + mines proactive patterns for Power+ users @@ -235,7 +235,7 @@ FastAPI app (app/main.py) **LLM routing**: backend agents own all intelligence. Tool calls describe client-side ops (JSON) → Electron `drizzle-executor` runs them against local SQLite → result returned to backend over WS. Tool loop cap inside agent runner prevents runaway iteration. -**Zero-trust data model**: backend never stores raw user content. PostgreSQL holds auth, billing, plugin metadata, encrypted memory (Core/Associative/Episodic/Proactive/Relational), agent configs, run logs. +**Zero-trust data model**: backend never stores raw user content. PostgreSQL holds auth, billing, plugin metadata, encrypted memory (Core/Associative/Episodic/Proactive/Relational), scout configs, run logs. **Config**: `app/config/settings.py` — all env vars via Pydantic Settings. Copy `.env.example` to `.env` for local dev. diff --git a/adiuvAI b/adiuvAI index c1b1b28..5cd895f 160000 --- a/adiuvAI +++ b/adiuvAI @@ -1 +1 @@ -Subproject commit c1b1b289c1750fb282aed3cc63735ac4b755b719 +Subproject commit 5cd895f04e7b165fba7492b64da0887e4536f5c1 diff --git a/api b/api index 70c19d3..fbd308d 160000 --- a/api +++ b/api @@ -1 +1 @@ -Subproject commit 70c19d30642b709a6586da29ffc256450d3c0674 +Subproject commit fbd308d288fd5b90dbce76a3922b98fbea58d5fc