# Feature: AI-verktøy (Drag-and-drop tekstbehandling) **Filsti:** `docs/features/ai_verktoy.md` ## 1. Konsept Et frittstående verktøy-panel på arbeidsflaten for AI-drevet tekstbehandling. I stedet for en ✨-knapp inne i editoren er AI-et et eget verktøy som lever side ved side med chat, artikkelverktøy, kanban og andre paneler. Brukeren konfigurerer verktøyet med en prompt og drar innhold til/fra det. Inspirert av fysiske verktøy: du har en maskin på arbeidsbenken, konfigurert til å gjøre én ting godt. Du mater inn materiale, og får bearbeidet materiale tilbake. Maskinen står der klar mellom bruk. ## 2. Brukeropplevelse ### 2.1 Åpne og konfigurere 1. Brukeren trekker AI-verktøyet inn på arbeidsflaten (fra verktøy-paletten). 2. Verktøyet åpner seg med: - En **prompt-velger** med gjennomarbeidede standardprompter - Et **fritekst-felt** for egendefinert prompt - En **modell-indikator** (viser hvilken modell som brukes — styrt av server) 3. Brukeren velger prompt og verktøyet er klart. 4. Verktøyet *husker* konfigurasjonen — det står klart til bruk uten å rekonfigurere hver gang. ### 2.2 To retninger — to semantikker | Retning | Metafor | Handling | Resultat | |---|---|---|---| | **Verktøy → Node** | "Penselen" | Dra AI-verktøyet og slipp på en tekstnode | In-place revisjon: teksten modifiseres, originalen versjoneres | | **Node → Verktøy** | "Kverna" | Dra en tekstnode og slipp på AI-verktøyet | Ny node opprettes med `derived_from`-edge til kilden | **Penselen** — du bruker verktøyet *på* teksten. Passer for korrektur, språkvask, rensing av innlimt rot. Teksten oppgraderes, originalen bevares som revisjon. **Kverna** — du sender teksten *gjennom* verktøyet. Passer for oppsummering, oversettelse, uttrekk av fakta. Output er et nytt objekt som kan tas med videre til andre verktøy på flaten. ### 2.3 Typisk bruksscenario ``` Vegard sitter på bussen, leser en artikkel i VG på mobilen. Ctrl+A → kopierer alt (artikkel + ingresser + annonser + navigasjon). Limer inn i en ny node i Synops. Drar AI-verktøyet (konfigurert med "Rens tekst") → noden. AI-et vasker bort alt som ikke er artikkelen, strukturerer teksten, forkorter, og oppgir kilde. Originalen er bevart som revisjon. Ferdig. Ren, lesbar tekst. Ingen rot. ``` ## 3. Standardprompter Gjennomarbeidede, klare til bruk uten konfigurasjon: | Prompt | Hva den gjør | Typisk retning | |---|---|---| | **Rens tekst** | Fjerner støy fra innlimt webinnhold, fikser skrivefeil, strukturerer, oppgir kilde | Verktøy → Node | | **Korrektør** | Fikser grammatikk og skrivefeil, beholder innhold intakt | Verktøy → Node | | **Oppsummering** | Kondenserer til 2–5 setninger med det viktigste | Node → Verktøy | | **Oversett** | Oversetter til/fra norsk/engelsk | Begge | | **Skriv om for publisering** | Omskriver til artikkelformat med tittel, ingress, brødtekst | Node → Verktøy | | **Trekk ut fakta** | Identifiserer påstander, tall, sitater som separate punkter | Node → Verktøy | | **Forenkle** | Omskriver til klarere, enklere språk | Verktøy → Node | | **Endre tone** | Formell ↔ uformell, saklig ↔ engasjert | Verktøy → Node | Brukere kan lage egne prompter og lagre dem. Egendefinerte prompter lagres som noder (`node_kind: 'ai_preset'`) som kan deles via edges. ## 4. Modellstyring **Modell bestemmes av serveren, ikke brukeren.** Hvert AI-verktøy (standardprompt eller egendefinert) har en server-tildelt modellprofil. Brukeren ser hvilken modell som brukes (transparens), men kan ikke endre den. | Prompt-kategori | Modellprofil | Begrunnelse | |---|---|---| | Rens tekst, korrektør, forenkle | Flash (billig, rask) | Enkle transformasjoner | | Oppsummering, oversettelse | Flash (billig, rask) | Rutineoppgaver | | Skriv om for publisering | Standard | Krever mer resonering | | Trekk ut fakta | Standard | Nøyaktighet viktigere | | Egendefinert (default) | Flash | Kan oppgraderes av admin | Modellprofiler konfigureres i maskinrommet og mappes til LiteLLM-aliaser. Admin kan justere modellprofil per prompt via Prompt Lab. **Kostnadskontroll:** Serveren styrer modellvalg for å hindre at brukere velger den dyreste modellen for alt. AI-forbruk logges per bruker/samling i `ai_usage_log`. ## 5. AI-verktøyet som node AI-verktøyet er selv en node i grafen (`node_kind: 'ai_preset'`): ```jsonc { "node_kind": "ai_preset", "title": "Rens tekst", "metadata": { "prompt": "Fiks denne teksten. Output på norsk...", "model_profile": "flash", "category": "standard", // "standard" | "custom" "default_direction": "tool_to_node", // hint for UI "icon": "sparkles", "color": "#8B5CF6" } } ``` Fordeler: - **Delbart:** Edge til samling/team → alle i teamet har tilgang - **Versjonerbart:** Promptjustering over tid med revisjonshistorikk - **Sporbart:** `derived_from`-edge fra output til kilde + `processed_by`-edge til AI-preset → full provenance i kunnskapsgrafen - **Gjenbrukbart:** Flere instanser av samme verktøy med ulik konfigurasjon ## 6. Teknisk arkitektur ### 6.1 Signalflyt ``` Bruker drar node → AI-verktøy (eller omvendt) │ ▼ Frontend sender intention til maskinrommet: POST /intentions/ai_process { source_node_id: "...", ai_preset_id: "...", direction: "node_to_tool" | "tool_to_node" } │ ▼ Maskinrommet: 1. Hent kilde-node content 2. Hent AI-preset prompt + modellprofil 3. Map modellprofil → LiteLLM-alias 4. Send til AI Gateway (LiteLLM) 5a. direction = tool_to_node: → Lagre original som revisjon → Oppdater node content med AI-output 5b. direction = node_to_tool: → Opprett ny node med AI-output → Opprett derived_from-edge til kilde → Opprett processed_by-edge til AI-preset 6. Logg forbruk i ai_usage_log │ ▼ Frontend mottar oppdatering via WebSocket (PG LISTEN/NOTIFY) ``` ### 6.2 Drag-and-drop integrasjon AI-verktøyet følger arbeidsflate-konvensjonene fra `docs/retninger/arbeidsflaten.md`: **Som mål (node → verktøy):** - Aksepterer: alle noder med `content`-felt (tekst, chatmeldinger, notater) - Drop-sone lyser opp med verktøyets farge under drag - Ved drop: opprett ny node, vis den ved siden av verktøyet **Som kilde (verktøy → node):** - Verktøyet kan "dras" til en tekstnode - Drop-sone på tekstnoden lyser opp - Ved drop: modifiser noden in-place **Inkompatibilitet:** - Lydfiler, bilder, mediefiler → "AI-verktøyet behandler kun tekst" - Tomme noder → "Noden har ikke innhold å behandle" ### 6.3 Oppdatering av kompatibilitetsmatrisen Legges til i `docs/retninger/arbeidsflaten.md`: | Kilde → Mål | AI-verktøy | |---|---| | **Chatboble** | Ny node med AI-output + `derived_from` | | **Tekst/notat** | Ny node med AI-output + `derived_from` | | **Lydfil** | Inkompatibel: "AI-verktøyet behandler kun tekst" | | **Transkripsjon** | Ny node med AI-output + `derived_from` | | **Bilde** | Inkompatibel | | Kilde → Mål | Tekstnode (fra AI-verktøy) | |---|---| | **AI-verktøy** | In-place revisjon av tekstnoden | ## 7. Forhold til eksisterende AI-design ### Erstatter ✨-knappen i editoren Editor-proposalen (`docs/proposals/editor.md`) beskriver en ✨-knapp inne i editoren. Med spatial workspace-retningen erstattes denne av AI-verktøyet som eget panel. Fordeler: - **Separat konfigurasjonsflate:** Prompt og parametere lever i sitt eget panel, ikke gjemt bak en meny i editoren - **Persistent:** Verktøyet står konfigurert og klart. ✨-knappen krever prompt-valg hver gang - **Konsistent drag-and-drop:** Samme interaksjonsmønster som mellom alle andre verktøy på flaten - **Flere samtidige:** Du kan ha "Rens tekst" og "Oppsummer" som to separate paneler, begge klare ### Bygger på Prompt Lab Egendefinerte prompter kan opprettes og testes i Prompt Lab (`docs/features/prompt_lab.md`) før de deployes som AI-preset-noder. ### Fremtidig: kjeding Flere AI-verktøy i serie: dra output fra "Oversett" videre til "Forenkle". Grafen sporer hele transformasjonskjeden via `derived_from`-edges. Ikke i scope for v1. ## 8. Avgrensning - Opererer på **hele noden** (hele `content`-feltet), ikke markert utvalg - Brukeren kan **ikke** velge modell — kun server-tildelt modellprofil - Ingen sanntids-streaming av AI-output (synkron respons via jobbkø) - Støtter kun tekst — ikke bilder, lyd eller video - Kjeding av verktøy er fremtidig funksjonalitet ## 9. Utviklingsfaser ### Fase A: Grunnleggende verktøy-panel - [x] AI-preset node-type (`node_kind: 'ai_preset'`) + metadata-skjema - [x] Standard-presets som seed-data (rens tekst, korrektør, oppsummering osv.) - [x] `POST /intentions/ai_process` endepunkt i maskinrommet - [x] Verktøy-panel UI med prompt-velger og modell-indikator - [x] Jobbkø-integrasjon med AI Gateway ### Fase B: Drag-and-drop - [x] Node → verktøy: opprett ny node med `derived_from`-edge - [x] Verktøy → node: in-place revisjon med versjonering - [x] Drop-sone feedback (farge, inkompatibilitet) - [ ] Visuell output: ny node animeres inn ved siden av verktøyet ### Fase C: Egendefinerte prompter - [x] Opprett egne AI-preset-noder (`POST /intentions/create_ai_preset`) - [x] Del via edges (samling/team) — `shared_with`-edge til samling - [x] Rediger og slett egne presets (via update_node/delete_node) - [x] Modellprofil-beskyttelse: kun admin kan endre model_profile - [ ] Prompt Lab-integrasjon for testing ## 10. Egendefinerte presets (oppgave 18.6) ### 10.1 Opprett egne AI-presets Brukere kan opprette egne AI-preset-noder via `POST /intentions/create_ai_preset`: ```json { "title": "Lag ingress", "prompt": "Skriv en kort, fengende ingress for denne teksten...", "default_direction": "node_to_tool", "icon": "pencil_square", "color": "#10B981", "share_with_collection_id": "" // valgfri } ``` Egendefinerte presets får alltid: - `category: "custom"` (kan ikke endres til "standard") - `model_profile: "flash"` (kan kun oppgraderes av admin) - `visibility: "discoverable"` (synlig for brukere med tilgang) ### 10.2 Deling via edges Presets kan deles med samlinger/team via `shared_with`-edge: - Enten direkte i `create_ai_preset` via `share_with_collection_id` - Eller via `create_edge` med `edge_type: "shared_with"` ### 10.3 Modellprofil-beskyttelse - Vanlige brukere kan **ikke** endre `model_profile` — det er alltid "flash" for egne presets - Admin (owner/admin-edge til en samling) kan oppgradere til "standard" via `update_node` - Kategori "standard" er reservert for systempresets og kan ikke velges av brukere ### 10.4 Frontend AiToolPanel har: - "+ Nytt preset"-knapp for å opprette egne presets - Rediger/slett/del-knapper for egne custom presets - Egendefinerte presets markert med "egn." i preset-velgeren - Delingsdialog for å dele med samling via UUID ## 11. Instruks for Claude Code - AI-behandling skjer **alltid** via maskinrommet, aldri direkte fra frontend - Modellprofil → LiteLLM-alias-mapping konfigureres i maskinrommet - Brukeren kan **ikke** velge modell — dette er en server-side beslutning - Standardprompter er seed-data som opprettes ved deploy, ikke hardkodet i frontend - `derived_from`-edge og `processed_by`-edge gir sporbarhet i grafen - AI-forbruk logges alltid i `ai_usage_log` per bruker, samling og preset - Hele noden prosesseres — ingen "markert utvalg"-støtte