# 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": "<uuid>"  // 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
