feat: implement R42 chat infrastructure with Anthropic API integration and custom design system
This commit is contained in:
23
AI_AGENT.md
23
AI_AGENT.md
@@ -30,6 +30,9 @@ All persistent data lives in **PocketBase**. The data access layer is in `src/li
|
||||
* `respellion:admin:anthropic_key` — Anthropic API key.
|
||||
* `respellion:admin:model` — Model override.
|
||||
* `respellion:admin:use_simulation` — Simulation mode toggle.
|
||||
* `kb:suggestions` — Pending/approved/rejected graph deltas proposed by R42. Always mutated via `kbStore` (see §8).
|
||||
* `quiz:active:{userId}` — Boolean flag set while the user is mid-quiz. R42's FAB is hidden when this is true (quiz-integrity rule).
|
||||
* `chat:thread:{userId}` — Persisted R42 conversation, capped at 50 messages.
|
||||
|
||||
**Session:** User login is PIN-based. The logged-in user's ID is stored in `sessionStorage` under `respellion_session` and resolved against `team_members` on app load (see `src/store/AppContext.jsx`).
|
||||
|
||||
@@ -65,7 +68,25 @@ The app is fully containerized. PocketBase runs as a sidecar service.
|
||||
* **Nginx:** Ensures any frontend route not matching a static file falls back to `index.html` (SPA support). The `/api/anthropic` path is proxied to the Anthropic API. The `/pb` path is proxied to the PocketBase service.
|
||||
* **PocketBase URL:** Resolved from `VITE_PB_URL` env var, or falls back to `window.location.origin + '/pb'` (see `src/lib/pb.js`).
|
||||
|
||||
## 7. How to Add New Features
|
||||
## 8. R42 Chatbot
|
||||
The platform ships a global chatbot avatar called **R42**, rendered as the Respellion `{ r }` brand mark in three states (idle / typing / error).
|
||||
|
||||
* **Mark component:** `src/components/ui/Mark.jsx`. Pure SVG; renders the brand mark with `state`, `size`, `theme`, `showFrame`, `brace`, `letter` props. Requires the `BallPill` font (loaded via `@font-face` in `src/index.css`, served from `public/fonts/BallPill-light.otf`). Falls back to JetBrains Mono (already loaded).
|
||||
* **Chat module:** `src/components/chat/`.
|
||||
* `ChatLauncher.jsx` — global FAB; auto-hides when `quiz:active:{userId}` is set. Listens to the `respellion:quiz-state` window event for fast updates.
|
||||
* `ChatWindow.jsx` — 380×480 chat panel; Esc closes; renders messages from `useChat`.
|
||||
* `useChat.js` — owns the message list, persists to `chat:thread:{userId}`, calls `anthropicApi.chat()`. `buildKbContext` is async (PocketBase), so `send()` is fully async.
|
||||
* `prompts.js` — system prompt, greeting, and the `propose_graph_delta` tool spec.
|
||||
* `rag.js` — fetches `kb:topics` + `kb:relations` from PocketBase; lazy-loads `kb:content:{id}` only when a topic is mentioned. Returns `{ context, topics }` so `validateDelta` can reuse the fetched topics without a second round-trip.
|
||||
* **Multi-turn API:** `anthropicApi.chat(systemPrompt, messages, { tools })` in `src/lib/api.js`. Returns the raw Anthropic response (`{ content: [...], stop_reason }`) so callers can read both text blocks and `tool_use` blocks. No API key header — Caddy proxy injects it server-side, matching the existing `generateContent` pattern.
|
||||
* **Quiz-integrity rule:** `src/pages/Testen.jsx` sets `quiz:active:{userId}=true` on start and clears it on every non-quiz phase + unmount, plus dispatches a `respellion:quiz-state` event. Never bypass this — letting users ask R42 mid-quiz would break scoring.
|
||||
* **Graph refinement:** when R42's `tool_use` block proposes a `propose_graph_delta`, `rag.js` validates (no duplicate ids, no orphan relations, caps 3 topics / 5 relations) and surfaces a confirmation chip inline.
|
||||
* **Admin user clicks Ja** — `kbStore.applyDelta` writes to PocketBase via `db.upsertTopic` / `db.addRelation` immediately.
|
||||
* **Non-admin clicks Ja** — `kbStore.appendSuggestion` queues an entry in `kb:suggestions` localStorage (status `pending`).
|
||||
* **Admin approval UI:** `src/components/admin/SuggestionsQueue.jsx`, mounted at the top of the Knowledge Graph admin panel. Approve calls `kbStore.approveSuggestion(id)` which runs the same `applyDelta` merge (async, PocketBase) and flips status to `approved`. Reject flips to `rejected` for audit.
|
||||
* **kbStore:** `src/lib/kbStore.js` is the single source of truth for KB mutations from the chatbot path. Topics/relations go to PocketBase; suggestions queue goes to localStorage. Dispatches `respellion:kb-updated` after any write so the D3 graph and the queue panel refresh without a reload.
|
||||
|
||||
## 9. How to Add New Features
|
||||
1. **Define Schema:** Add a new PocketBase collection via the Admin UI or the init script (`scripts/setup-pb-collections.mjs`).
|
||||
2. **Add DB Helpers:** Add async CRUD functions in `src/lib/db.js`.
|
||||
3. **Build UI:** Create components using `Card`, `Button`, and `framer-motion` for smooth entry (`animate-in fade-in slide-in-from-bottom-4`).
|
||||
|
||||
Reference in New Issue
Block a user