Når en bruker limer inn en URL i chatten, gjenkjenner synops-respond URL-en automatisk, kaller synops-clip --write for å hente, parse og oppsummere artikkelen, og inkluderer resultatet i prompten slik at Claude kan presentere oppsummeringen naturlig. Ved betalingsmur: Claude informerer brukeren og ber om innlimt innhold. Maks 3 URL-er per melding, 60s timeout per klipp. Endringer: - synops-respond: URL-deteksjon (regex), synops-clip-kall, prompt-kontekst - maskinrommet/agent.rs: videresend env-variabler for synops-clip - maskinrommet-env.sh: SYNOPS_CLIP_SCRIPTS env-variabel - docs/infra/claude_agent.md: dokumentert URL-klipping-flyten
134 lines
4.8 KiB
Markdown
134 lines
4.8 KiB
Markdown
# Infrastruktur: Claude som chat-deltaker
|
|
|
|
## Oversikt
|
|
|
|
Claude deltar i samtaler som en agent-node i grafen. Når en bruker sender
|
|
en melding i en kommunikasjonsnode der Claude er deltaker, trigger maskinrommet
|
|
en `agent_respond`-jobb som delegerer til `synops-respond` CLI-verktøyet.
|
|
|
|
## Arkitektur
|
|
|
|
```
|
|
Bruker sender melding (via frontend)
|
|
→ create_node() i maskinrommet
|
|
→ sjekker: har kommunikasjonsnoden en agent-deltaker?
|
|
→ ja: enqueue agent_respond-jobb (prioritet 8)
|
|
→ jobbkø-worker plukker opp (poll hvert 2s)
|
|
→ maskinrommet: kill switch, rate limit, loop-prevensjon
|
|
→ spawner: synops-respond --communication-id ... --write
|
|
→ henter meldingshistorikk + kontekst fra PG
|
|
→ bygger prompt
|
|
→ kaller: claude -p "<prompt>" --output-format json
|
|
→ oppretter svar-node i PG, logger ai_usage + resource_usage
|
|
→ returnerer JSON med reply_node_id + response_text
|
|
→ PG NOTIFY propagerer til frontend via WebSocket
|
|
→ frontend viser melding i sanntid
|
|
```
|
|
|
|
Ansvarsdeling (unix-filosofi):
|
|
- **Maskinrommet:** Auth, kill switch, rate limiting, loop-prevensjon, env-videresending
|
|
- **synops-respond:** Kontekst-henting, URL-deteksjon, synops-clip-kall, prompt-bygging, claude-kall, PG-skriving
|
|
- **synops-clip:** Artikkelhenting, parsing, paywall-deteksjon, AI-oppsummering, node-opprettelse
|
|
|
|
Latens: ~3-5 sekunder uten URL, ~10-20 sekunder med URL (synops-clip + LLM-oppsummering).
|
|
|
|
### URL-klipping i chat (oppgave 25.3)
|
|
|
|
Når en bruker limer inn en URL i chatten, gjenkjenner `synops-respond` URL-en
|
|
og kaller `synops-clip --write` automatisk før Claude svarer:
|
|
|
|
```
|
|
Bruker: "Sjekk denne: https://nrk.no/artikkel"
|
|
→ synops-respond detekterer URL med regex
|
|
→ spawner: synops-clip --url ... --write --created-by <bruker>
|
|
→ synops-clip henter, parser, oppsummerer, oppretter node
|
|
→ resultat (tittel, oppsummering, paywall) inkluderes i prompt
|
|
→ Claude svarer med oppsummering basert på klipp-kontekst
|
|
```
|
|
|
|
Ved betalingsmur: Claude informerer om at artikkelen er bak betalingsmur,
|
|
presenterer det som er tilgjengelig (tittel/ingress), og ber brukeren
|
|
lime inn innholdet om de vil dele resten.
|
|
|
|
Begrensninger: Maks 3 URL-er per melding. 60 sekunders timeout per klipp.
|
|
|
|
## Noder og tabeller
|
|
|
|
### Claude-noden
|
|
- **UUID:** `d3eebc99-9c0b-4ef8-bb6d-6bb9bd380a44`
|
|
- **node_kind:** `agent`
|
|
- **visibility:** `discoverable`
|
|
|
|
### agent_identities
|
|
Kobler agent-noder til konfigurasjon og nøkkel.
|
|
|
|
| Felt | Verdi |
|
|
|------|-------|
|
|
| agent_key | `claude-main` |
|
|
| agent_type | `claude` |
|
|
| config | max_context_messages, rate_limit_per_hour, etc. |
|
|
|
|
### agent_permissions
|
|
Autorisasjonsnivåer per bruker/agent-par.
|
|
|
|
| Nivå | Betydning |
|
|
|------|-----------|
|
|
| `direct` | Kan bestille endringer som implementeres direkte |
|
|
| `propose` | Kan foreslå endringer som krever godkjenning |
|
|
|
|
### ai_usage_log
|
|
Logger hvert agent-svar med timestamps, job_id, og kommunikasjons-ID.
|
|
|
|
## Sikkerhet
|
|
|
|
| Mekanisme | Beskrivelse |
|
|
|-----------|-------------|
|
|
| **Kill switch** | `agent_identities.is_active = false` stopper all aktivitet |
|
|
| **Rate limiting** | Maks 60 responser per time (konfigurerbart) |
|
|
| **Loop-prevensjon** | Stopper hvis siste 3 meldinger er fra agenten |
|
|
| **Egne meldinger** | Svarer aldri på egne meldinger (sjekk i trigger) |
|
|
|
|
## Oppsett av ny chat med Claude
|
|
|
|
```sql
|
|
-- 1. Opprett kommunikasjonsnode
|
|
INSERT INTO nodes (id, node_kind, title, visibility, metadata, created_by)
|
|
VALUES ('<uuid>', 'communication', 'Min chat med Claude', 'hidden', '{}', '<bruker-uuid>');
|
|
|
|
-- 2. Legg til bruker som owner
|
|
INSERT INTO edges (id, source_id, target_id, edge_type, metadata, system, created_by)
|
|
VALUES ('<uuid>', '<bruker-uuid>', '<comm-uuid>', 'owner', '{}', false, '<bruker-uuid>');
|
|
|
|
-- 3. Legg til Claude som member_of
|
|
INSERT INTO edges (id, source_id, target_id, edge_type, metadata, system, created_by)
|
|
VALUES ('<uuid>', 'd3eebc99-9c0b-4ef8-bb6d-6bb9bd380a44', '<comm-uuid>', 'member_of', '{}', false, '<bruker-uuid>');
|
|
|
|
-- 4. Recompute access
|
|
SELECT recompute_access('<bruker-uuid>', '<comm-uuid>', 'owner', '<owner-edge-uuid>');
|
|
SELECT recompute_access('d3eebc99-9c0b-4ef8-bb6d-6bb9bd380a44', '<comm-uuid>', 'member', '<member-edge-uuid>');
|
|
```
|
|
|
|
Etter dette vil alle meldinger i chatten automatisk trigge Claude-svar.
|
|
|
|
## Drift
|
|
|
|
Maskinrommet kjører som systemd-tjeneste direkte på hosten:
|
|
|
|
```bash
|
|
sudo systemctl status maskinrommet # status
|
|
sudo systemctl restart maskinrommet # restart etter ny build
|
|
sudo journalctl -u maskinrommet -f # live-logger
|
|
```
|
|
|
|
Bygg og deploy:
|
|
```bash
|
|
cd ~/synops/maskinrommet && cargo build --release
|
|
sudo systemctl restart maskinrommet
|
|
```
|
|
|
|
## Faser
|
|
|
|
- **Fase A (MVP):** Chat-agent — implementert og verifisert
|
|
- **Fase B:** Autorisasjon og oppgaver (direct vs propose flyt)
|
|
- **Fase C:** Autonom implementering (claude Code som subprocess for kode-endringer)
|
|
- **Fase D:** @mentions, typing-indikator, admin-panel
|