From d18dfc260f947c5089ead4b562d0e805f3f07e20 Mon Sep 17 00:00:00 2001 From: vegard Date: Wed, 18 Mar 2026 17:47:32 +0000 Subject: [PATCH] AI-assistert oppretting: synops-ai genererer orkestreringsscript fra fritekst (oppgave 24.7) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Nytt CLI-verktøy `synops-ai` som leser cli_tool-noder fra PG, bygger en systemprompt med tilgjengelige verktøy og script-grammatikk, og bruker LLM til å foreslå orkestreringsscript fra fritekst-beskrivelse. Tre moduser: - Synkron: --description "..." → LLM genererer script → JSON output - System prompt: --generate-system-prompt → skriver auto-generert prompt - Eventually: --eventually → lagrer som work_item for Claude Code Maskinrommet: nytt endepunkt POST /intentions/ai_suggest_script som kaller synops-ai, validerer resultatet med script_compiler, og returnerer script + kompileringsresultat til frontend. Frontend: AI-assistent-knapp i OrchestrationTrait med fritekst-input, generer-knapp, og feilvisning. Generert script settes direkte i editoren. Migration: synops-ai seeded som cli_tool-node med norske verb-alias. --- frontend/src/lib/api.ts | 28 + .../traits/OrchestrationTrait.svelte | 176 + maskinrommet/src/intentions.rs | 149 + maskinrommet/src/main.rs | 3 +- migrations/024_cli_tool_synops_ai.sql | 36 + tools/synops-ai/Cargo.lock | 2929 +++++++++++++++++ tools/synops-ai/Cargo.toml | 21 + tools/synops-ai/src/main.rs | 599 ++++ 8 files changed, 3940 insertions(+), 1 deletion(-) create mode 100644 migrations/024_cli_tool_synops_ai.sql create mode 100644 tools/synops-ai/Cargo.lock create mode 100644 tools/synops-ai/Cargo.toml create mode 100644 tools/synops-ai/src/main.rs diff --git a/frontend/src/lib/api.ts b/frontend/src/lib/api.ts index 81d35d7..1a52027 100644 --- a/frontend/src/lib/api.ts +++ b/frontend/src/lib/api.ts @@ -1433,3 +1433,31 @@ export async function setMixerRole( role, }); } + +// ========================================================================= +// AI-assistert script-generering (oppgave 24.7) +// ========================================================================= + +export interface AiSuggestScriptRequest { + description: string; + trigger_event?: string; + trigger_conditions?: Record; + eventually?: boolean; + collection_id?: string; +} + +export interface AiSuggestScriptResponse { + status: string; + script?: string; + compile_result?: CompileScriptResponse; + work_item_id?: string; + message?: string; +} + +/** AI-assistert generering av orkestreringsscript fra fritekst-beskrivelse. */ +export function aiSuggestScript( + accessToken: string, + req: AiSuggestScriptRequest +): Promise { + return post(accessToken, '/intentions/ai_suggest_script', req); +} diff --git a/frontend/src/lib/components/traits/OrchestrationTrait.svelte b/frontend/src/lib/components/traits/OrchestrationTrait.svelte index ae8f5f6..fab115e 100644 --- a/frontend/src/lib/components/traits/OrchestrationTrait.svelte +++ b/frontend/src/lib/components/traits/OrchestrationTrait.svelte @@ -6,6 +6,7 @@ compileScript, testOrchestration, fetchOrchestrationLog, + aiSuggestScript, type CompileScriptResponse, type OrchestrationLogEntry } from '$lib/api'; @@ -77,6 +78,12 @@ let triggerConditions = $state(''); let executor = $state('script'); + // AI-assist + let showAiAssist = $state(false); + let aiDescription = $state(''); + let aiGenerating = $state(false); + let aiError: string | null = $state(null); + // History let logEntries: OrchestrationLogEntry[] = $state([]); let showHistory = $state(false); @@ -214,6 +221,42 @@ if (showHistory) loadHistory(); } + async function generateWithAi() { + if (!accessToken || !aiDescription.trim()) return; + aiGenerating = true; + aiError = null; + try { + const result = await aiSuggestScript(accessToken, { + description: aiDescription, + trigger_event: triggerEvent !== 'manual' ? triggerEvent : undefined, + collection_id: collection?.id, + }); + + if (result.script) { + scriptContent = result.script; + aiDescription = ''; + showAiAssist = false; + } + + if (result.status === 'generated_with_errors' && result.compile_result) { + const errors = result.compile_result.diagnostics + ?.filter((d) => d.severity === 'Error') + .map((d) => d.message) + .join('; '); + if (errors) { + aiError = `Script generert med feil: ${errors}`; + } + } else if (result.status === 'deferred') { + aiError = null; + showAiAssist = false; + } + } catch (err) { + aiError = err instanceof Error ? err.message : 'Ukjent feil'; + } finally { + aiGenerating = false; + } + } + // ========================================================================= // Trigger event options // ========================================================================= @@ -383,6 +426,35 @@ {/if} + + {#if showAiAssist} +
+
+ AI-assistent + +
+ + {#if aiError} +
{aiError}
+ {/if} +
+ +
+
+ {/if} +
+