Brukere kan nå opprette egne AI-preset-noder med custom prompt,
dele dem med samlinger/team via shared_with-edges, og redigere/slette
egne presets. Modellprofil (flash/standard) er låst — kun admin
kan oppgradere fra flash til standard.
Backend:
- POST /intentions/create_ai_preset: Oppretter custom preset med
tvunget category=custom og model_profile=flash. Valgfri deling
til samling i samme kall.
- update_node: Beskytter model_profile mot endring av ikke-admin.
Forhindrer kategori-endring fra custom til standard.
Frontend:
- AiToolPanel: "+ Nytt preset"-knapp, opprett/rediger-skjema med
tittel, prompt, retning, ikon og farge. Rediger/slett/del-knapper
for egne custom presets. Egendefinerte presets markert med "egn."
- createAiPreset() i api.ts.
Dokumentasjon:
- ai_verktoy.md: Oppdatert fasestatus, ny § 10 om egendefinerte
presets med API-eksempler og modellprofil-beskyttelse.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implementerer toveis drag-and-drop mellom AI-verktøypanelet og
innholdspaneler, med visuell feedback og kompatibilitetssjekking.
Nye filer:
- transfer.ts: Sentralisert transfer-tjeneste med kompatibilitetsmatrise,
DragPayload-format (application/x-synops-transfer), og
inkompatibilitets-meldinger for lyd/bilde-noder.
Endringer:
- AiToolPanel: Drop-sone bruker presetets farge (dynamisk border/bg),
viser rød sone med forklaring ved inkompatible noder (lyd/bilde),
presets er draggable ut (for tool_to_node retning).
- EditorTrait: Aksepterer AI-preset drops på innholdsnoder (tool_to_node),
viser visuell feedback (lilla=kompatibel, rød=inkompatibel),
trigger in-place revisjon via aiProcess API.
- ChatTrait: Kommunikasjonsnoder er nå draggable til AI-verktøyet.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Svelte-komponent for AI-prosessering i arbeidsflaten:
- AiToolPanel.svelte: Viser ai_preset-noder fra STDB som velgbare
verktøy, med modell-indikator (flash/standard) og prompt-forhåndsvisning
- Drag-and-drop mottak for tekstnoder med visuell feedback
- Validerer kompatibilitet (kun content/communication-noder)
- Kaller /intentions/ai_process via ny aiProcess()-funksjon i api.ts
- Integrert i collection-siden, tilgjengelig for alle innloggede brukere
- EditorTrait: innholdsnoder er nå draggable for AI-prosessering
- Fritekst-felt for egendefinert instruksjon (backend-støtte kommer i 18.6)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implementerer de to retningene for AI-verktøyet:
- tool_to_node ("Penselen"): Lagrer original content som revisjon i
ny node_revisions-tabell, deretter oppdaterer noden med AI-output
i både STDB (sanntid) og PG (persistering).
- node_to_tool ("Kverna"): Oppretter ny node med AI-output, med
derived_from-edge tilbake til kildenoden og processed_by-edge
til AI-preseten. Full sporbarhet i grafen.
Ny PG-tabell: node_revisions (node_id, content, title, metadata,
revision_type, created_by, ai_preset_id, job_id).
Ref: docs/features/ai_verktoy.md § 2.2, § 6.1
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
POST /intentions/ai_process med source_node_id, ai_preset_id og
direction (node_to_tool / tool_to_node).
Endepunktet validerer input, sjekker at kilde-node og AI-preset
finnes, verifiserer skrivetilgang for tool_to_node-retning, og
legger en ai_process-jobb i køen.
Jobb-handleren (ai_process.rs) henter kilde-content og preset-prompt,
mapper modellprofil → LiteLLM-alias (flash → sidelinja/rutine,
standard → sidelinja/resonering), kaller AI Gateway, og logger
forbruk i både ai_usage_log og resource_usage_log.
Direction-logikk (opprett ny node vs. oppdater eksisterende)
implementeres i oppgave 18.3.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Tre endringer som sammen gir brukeren innsyn i FFmpeg-feil:
1. Backend: Nytt GET /query/job_status-endepunkt i queries.rs.
Frontenden pollet allerede denne URLen, men endepunktet manglet.
Returnerer status, result og error_msg fra job_queue.
2. RenderDialog: Ny error-tilstand med formatFfmpegError() som
trekker ut lesbar feilmelding fra FFmpeg stderr-dump. Viser
kort oppsummering + ekspanderbar full feilmelding via <details>.
3. Studio-side: Sender renderError til RenderDialog som errorMessage.
Toast-varselet vises kun når dialogen er lukket (unngår duplisering).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Legger til cleanup_tmp() i CasStore som sletter orphaned .tmp-filer
eldre enn 1 time. Disse oppstår når en skriveprosess krasjer midt i
en atomisk CAS-skriveoperasjon (skriv til tmp, rename til endelig path).
Ny bakgrunnsloop start_tmp_cleanup_loop() kjører hver time og fjerner
foreldede temp-filer. Følger samme mønster som pruning- og
disk-monitor-loopene.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Tre forbedringer i studio-siden:
1. Interval/timeout-opprydding ved navigering: Polling-interval og
timeout lagres i komponent-variabler og ryddes opp via $effect
cleanup når komponenten demonteres. Forhindrer memory leaks og
ghost-requests etter navigering bort fra studio-siden.
2. Feilmelding etter N mislykkede polling-forsøk: Etter 5 feilede
statussjekker (nettverksfeil eller HTTP-feil) vises en
feilmelding til brukeren i stedet for stille ignorering.
Timeout-feil og jobb-feil vises også i UI.
3. Metadata JSON.parse i try/catch: Hindrer at ugyldig metadata-JSON
krasjer hele studio-siden. Logger feilen og returnerer null.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Legger til min/max-attributter på alle tallfelter i OperationPanel
slik at nettleseren hindrer ugyldig input før det sendes til backend.
Grensene matcher backend-valideringen i audio.rs:
- silenceThreshold: -96 til 0 dB
- silenceMinMs: 1 til 60000 ms
- normTarget: -70 til 0 LUFS
- fadeInMs/fadeOutMs: 1 til 300000 ms
- compThreshold: -60 til 0 dB
- compRatio: 1 til 20 (max lagt til, min fantes allerede)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Tre fikser i audio.rs:
1. Fade-out start clampes til 0 i stedet for å hoppes over
når effective_duration < fade_duration. Tidligere ble faden
stille droppet — nå starter den alltid fra minst 0.
2. Adaptiv silence-margin: margin (200ms) begrenses til maks
halve regionens varighet. Korte stillhetsregioner (<400ms)
fikk tidligere hele marginen spist opp og ble aldri kuttet.
3. Ny validate_fade_durations() gir feilmelding når fade-varighet
overstiger lydens totale varighet. Kalles fra process_audio
etter at vi kjenner faktisk varighet.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Legger til validate_operations() som sjekker alle numeriske verdier
i EDL-operasjoner før de interpoleres i FFmpeg-filterstrenger.
Dette forhindrer ugyldige/farlige verdier fra å nå ffmpeg subprocess.
Validerte parametere:
- Cut: start/end ikke-negativ, end > start
- Normalize: target_lufs mellom -70 og 0
- TrimSilence: threshold_db -96..0, min_duration 1..60000ms
- FadeIn/Out: duration 1..300000ms
- NoiseReduction: strength_db -80..0
- Equalizer: gain -30..+30 dB per bånd
- Compressor: threshold -60..0 dB, ratio 1..20
Validering kjøres ved inngang til process_audio() og detect_silence().
NaN/Inf-verdier avvises eksplisitt. Alle feil samles og returneres samlet.
12 enhetstester verifiserer grenseverdier og feiltilfeller.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Lydstudioet var kun desktop-optimalisert med fast sidebar (w-72).
Nå responsivt med to moduser:
- Desktop (lg+): Sidebar med verktøypanel til høyre, som før
- Mobil/tablet (< lg): Waveform fyller full bredde, verktøypanel
tilgjengelig via flytende knapp som åpner bottom sheet (modal).
Operation-badge på knappen viser antall aktive operasjoner.
Header: Kompaktere padding på mobil, tittel truncates, audio-info
skjules på små skjermer. min-w-0 på hovedområdet hindrer overflow.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Robotstemme: Ring-modulasjon via OscillatorNode som modulerer
GainNode.gain — gir metallisk, Dalek-aktig effekt. Justerbar
frekvens (30–300 Hz) og modulasjonsdybde (0–100%).
Monsterstemme: Egenutviklet AudioWorkletProcessor med phase vocoder
for sanntids pitch-shifting. Bruker overlap-add med 2048-sample FFT
og 4x overlap for ~42ms latens ved 48kHz. Pitch-faktor 0.5x–2.0x.
UI: Effektvelger-knapper (Robot/Monster) i FX-seksjon per kanal,
med fargekodede parametersliders som vises når effekten er aktiv.
On/off-state synkroniseres via STDB toggle_effect, parametere er
per-klient (ulike brukere kan ha forskjellige monitorinnstillinger).
STDB: Lagt til set_effect_param reducer for fremtidig param-synk
(krever spacetime CLI for publish — ikke deployet ennå).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implementerer lydpads (inspirert av RødeCaster Pro II) i mixeren:
- mixer.ts: Nytt pad-system med AudioBuffer-caching, GainNode per pad,
og one-shot AudioBufferSourceNode-avspilling. Funksjoner for load,
play, stop, og gain-kontroll.
- livekit.ts: Data message-støtte (sendDataMessage, onDataMessage) for
synkronisert pad-avspilling på tvers av LiveKit-deltakere. Bruker
reliable delivery med topic-filtrering.
- SoundPadGrid.svelte: 4×2 responsivt pad-grid med fargede knapper.
Forhåndslaster lydfiler fra CAS til AudioBuffer. Visuell feedback
ved avspilling (scale-animasjon). Konfigurasjonsmodus for å sette
label, farge og laste opp lydfil per pad. Pad-konfig lagres i
metadata.mixer.pads på samlingsnoden.
- MixerTrait.svelte: Integrerer SoundPadGrid mellom kanalstriper og
master-seksjon. Sender isViewer-prop for tilgangskontroll.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implementerer sanntids mixer-synkronisering mellom alle deltakere i et
LiveKit-rom via SpacetimeDB. Når én deltaker justerer gain eller muter
en kanal, oppdateres alle klienters Web Audio-graf og UI umiddelbart.
SpacetimeDB-modul (Rust):
- MixerChannel-tabell med room_id/target_user_id-indekser
- Reducers: set_gain (clamped 0.0-1.5), set_mute, toggle_effect,
create/delete_mixer_channel, set_mixer_role (editor/viewer)
- Viewer-sjekk i reducers — viewer kan ikke endre andres kanaler
- Opprydding av mixer-kanaler i close_live_room og clear_all
Frontend (SvelteKit):
- mixerChannelStore med reaktive callbacks og room_id-indeks
- MixerTrait leser delt state fra STDB, skriver endringer via reducers
- suppressRemoteSync-flagg forhindrer feedback-loop ved egne endringer
- Viewer-modus: disabled sliders/knapper for låste deltakere
- Visuell (V)-indikator for viewer-kanaler
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implementerer Mixer-UI som trait-komponent for samlingssider:
- Kanalstripe per deltaker med volumslider (0–150%), VU-meter (CSS),
nød-mute-knapp (rød, tydelig) og navnelabel
- Master-seksjon med fader, VU-meter og master-mute
- Responsivt design: stacked layout på mobil, horisontal på desktop
- Animert VU-meter via requestAnimationFrame og AnalyserNode-data
- Integrert i collection-siden som 'mixer'-trait
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Oppretter dedikert mixer-modul (mixer.ts) som eier hele Web Audio-grafen:
- AudioContext med master GainNode og master AnalyserNode
- Per-kanal signalkjede: MediaStreamSource → AnalyserNode → GainNode → MasterGain → destination
- AnalyserNode per kanal gir peak/RMS-nivådata for VU-meter
- API for gain-kontroll (per-kanal og master), mute/unmute, nivåavlesning
- livekit.ts delegerer all lydrutning til mixer.ts
Arkitekturen er klar for fremtidige faser: effektkjeder kan settes inn
mellom source og gain, sound pads kan legge til kanaler, og SpacetimeDB
kan synkronisere mixer-state.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Installerer livekit-client og bygger grunnlaget for sanntidslyd:
- $lib/livekit.ts: LiveKit-wrapper med romtilkobling, deltakersporing,
og Web Audio-ruting. Auto-attach av <audio> er deaktivert — all lyd
rutes gjennom AudioContext med GainNode per deltaker (klar for mixer).
- api.ts: joinCommunication/leaveCommunication API-funksjoner
- RecordingTrait.svelte: UI for tilkobling, mikrofon-toggle og deltakerliste
med live speaking-indikator
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Legger til to nye API-endepunkter for brukersynlig ressursforbruk:
- GET /my/usage — brukerens eget forbruk (filtrert på triggered_by)
- GET /query/node_usage — forbruk for én node (kun eier/admin)
Frontend:
- /profile — profilside med grafstatistikk og forbruksoversikt
- NodeUsage-komponent integrert i samlings-detaljsiden
- Brukernavn i header lenker nå til profilsiden
Tilgangssjekk: nodeforbruk krever created_by eller owner/admin-edge.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Aggregert ressursforbruk-dashboard som spør mot resource_usage_log
(oppgave 15.7). Tre visninger: totaler per ressurstype, per samling,
og daglig tidsserie. AI drill-down viser forbruk per jobbtype og
modellnivå (fast/smart/deep).
Backend: GET /admin/usage med days- og collection_id-filtre.
Frontend: /admin/usage med filterbare tabeller og fargekodede kort.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sentralisert logging av alle ressurskrevende operasjoner til
resource_usage_log-tabellen (opprettet i migrasjon 009).
Ny kode:
- resource_usage.rs: hjelpemodul med log() og find_collection_for_node()
- bandwidth.rs: Caddy JSON-logg-parser med nattlig batch-jobb (kl 03:00)
Logging lagt til i handlere:
- AI: summarize, ai_edges (token-telling via LiteLLM usage-felt),
agent (placeholder — claude CLI gir ikke token-info)
- Whisper: duration_seconds, model, language, mode
- TTS: refaktorert til sentralisert modul, lagt til collection_id
- CAS: logger nye filer ved upload (ikke dedup)
- LiveKit: logger join-hendelser (faktisk deltaker-minutter
krever webhook-integrasjon i fremtiden)
Caddy-config: JSON access logging aktivert for sidelinja.org og
synops.no i /srv/synops/config/caddy/Caddyfile (utenfor repo).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Nytt admin-dashboard for sanntids serverhelse med fire hoveddeler:
1. Tjeneste-status: Parallelle helsesjekker for alle 7 tjenester
(PG, STDB, Caddy, Authentik, LiteLLM, Whisper, LiveKit) med
latens-måling og statusrapportering (up/down/degraded).
2. System-metrikker: CPU-load via /proc/loadavg, minne via
/proc/meminfo, disk via statvfs, oppetid via /proc/uptime.
Vises med progress-bars og fargekodede terskler.
3. PG-statistikk: Aktive tilkoblinger, maks-tilkoblinger,
databasestørrelse og aktive spørringer.
4. Logg-tilgang: Filtrerbar visning av logger fra alle tjenester.
Bruker journalctl for systemd-tjenester og docker logs for
containere. Konfigurerbart antall linjer per tjeneste.
Backend: health.rs med tokio::join! for parallelle sjekker.
Frontend: /admin/health med auto-polling hvert 10. sekund.
Backup-sjekk rapporterer ok/stale/missing (ingen backup satt opp ennå).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implementerer prioritetsregler, ressursgrenser og LiveKit-bevisst
resource governor for jobbkø-workeren, pluss disk-overvåking med varsling.
Hovedkomponenter:
1. Prioritetsregler (job_priority_rules-tabell):
- Konfigurerbar base_priority, cpu_weight, max_concurrent per jobbtype
- LiveKit-justering: livekit_priority_adj og block_during_livekit
- Timeout per jobbtype
- Admin-API for å endre regler uten restart
2. Ressurs-governor i worker-loopen:
- Semaphore: maks 3 samtidige jobber
- CPU-vektgrense: total vekt maks 8 (Whisper=5, render=1, etc.)
- Per-type concurrency-grense
- LiveKit-status sjekkes med 10s cache-TTL
- Jobber utsettes/nedprioriteres ved aktive LiveKit-rom
- Individuell timeout per jobb (default 600s)
- Jobber kjøres i egne tokio-tasks (parallell dispatch)
3. Disk-overvåking:
- Sjekker diskbruk hvert 60. sekund via statvfs
- Terskler: 85% warning, 90% critical, 95% emergency
- Logger til disk_status_log (siste 1000 målinger beholdes)
- Admin-API: GET /admin/resources/disk med historikk
4. Admin-API:
- GET /admin/resources — samlet ressursstatus
- GET /admin/resources/disk — diskstatus med historikk
- POST /admin/resources/update_rule — oppdater prioritetsregel
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>