Legg til orchestration-validering i maskinrommet (oppgave 24.1)
Ny node_kind 'orchestration' med strukturert metadata-validering: - trigger.event valideres mot kjent liste (node.created, edge.created, communication.ended, node.published, scheduled.due, manual) - trigger.conditions må være objekt hvis satt - executor valideres mot script/bot/dream - intelligence og effort valideres som heltall 1-3 - compiled valideres som boolean - pipeline valideres som array Valideringen kjører i både create_node og update_node, identisk mønster som validate_collection_traits og validate_ai_preset_metadata. Ref: docs/concepts/orkestrering.md
This commit is contained in:
parent
77e3d59b46
commit
6dabdcf8ec
2 changed files with 117 additions and 2 deletions
|
|
@ -102,6 +102,21 @@ fn validate_collection_traits(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gyldige trigger-events for orchestration-noder.
|
||||||
|
/// Ref: docs/concepts/orkestrering.md § 5 "Kjente trigger-events"
|
||||||
|
const VALID_TRIGGER_EVENTS: &[&str] = &[
|
||||||
|
"node.created",
|
||||||
|
"edge.created",
|
||||||
|
"communication.ended",
|
||||||
|
"node.published",
|
||||||
|
"scheduled.due",
|
||||||
|
"manual",
|
||||||
|
];
|
||||||
|
|
||||||
|
/// Gyldige executor-verdier for orchestration-noder.
|
||||||
|
/// Ref: docs/concepts/orkestrering.md § 4 "Tre utførelsesnivåer"
|
||||||
|
const VALID_EXECUTORS: &[&str] = &["script", "bot", "dream"];
|
||||||
|
|
||||||
/// Gyldige modellprofiler for AI-presets.
|
/// Gyldige modellprofiler for AI-presets.
|
||||||
/// Ref: docs/infra/ai_gateway.md § "Modellprofiler"
|
/// Ref: docs/infra/ai_gateway.md § "Modellprofiler"
|
||||||
const VALID_MODEL_PROFILES: &[&str] = &["flash", "standard"];
|
const VALID_MODEL_PROFILES: &[&str] = &["flash", "standard"];
|
||||||
|
|
@ -188,6 +203,101 @@ fn validate_ai_preset_metadata(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Validerer metadata for `node_kind == "orchestration"`.
|
||||||
|
///
|
||||||
|
/// Påkrevde felter i metadata:
|
||||||
|
/// - `trigger` (objekt med `event` og valgfri `conditions`)
|
||||||
|
/// - `trigger.event` (string, må finnes i VALID_TRIGGER_EVENTS)
|
||||||
|
/// - `executor` (string, må finnes i VALID_EXECUTORS)
|
||||||
|
///
|
||||||
|
/// Valgfrie felter:
|
||||||
|
/// - `trigger.conditions` (objekt — fri filtrering)
|
||||||
|
/// - `intelligence` (heltall 1–3)
|
||||||
|
/// - `effort` (heltall 1–3)
|
||||||
|
/// - `compiled` (boolean — om scriptet er kompilert fra AI-modus)
|
||||||
|
/// - `pipeline` (array — sekvens av steg)
|
||||||
|
///
|
||||||
|
/// Ref: docs/concepts/orkestrering.md
|
||||||
|
fn validate_orchestration_metadata(
|
||||||
|
node_kind: &str,
|
||||||
|
metadata: &serde_json::Value,
|
||||||
|
) -> Result<(), String> {
|
||||||
|
if node_kind != "orchestration" {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Påkrevd: trigger (objekt)
|
||||||
|
let trigger = metadata
|
||||||
|
.get("trigger")
|
||||||
|
.ok_or("orchestration krever metadata.trigger")?;
|
||||||
|
let trigger_obj = trigger
|
||||||
|
.as_object()
|
||||||
|
.ok_or("metadata.trigger må være et objekt")?;
|
||||||
|
|
||||||
|
// Påkrevd: trigger.event
|
||||||
|
match trigger_obj.get("event").and_then(|v| v.as_str()) {
|
||||||
|
None | Some("") => {
|
||||||
|
return Err("orchestration krever metadata.trigger.event (ikke-tom streng)".into())
|
||||||
|
}
|
||||||
|
Some(ev) if !VALID_TRIGGER_EVENTS.contains(&ev) => {
|
||||||
|
return Err(format!(
|
||||||
|
"Ukjent trigger-event: '{ev}'. Gyldige verdier: {VALID_TRIGGER_EVENTS:?}"
|
||||||
|
));
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Valgfri: trigger.conditions (må være objekt hvis satt)
|
||||||
|
if let Some(conditions) = trigger_obj.get("conditions") {
|
||||||
|
if !conditions.is_object() {
|
||||||
|
return Err("metadata.trigger.conditions må være et objekt".into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Påkrevd: executor
|
||||||
|
match metadata.get("executor").and_then(|v| v.as_str()) {
|
||||||
|
None => return Err("orchestration krever metadata.executor".into()),
|
||||||
|
Some(ex) if !VALID_EXECUTORS.contains(&ex) => {
|
||||||
|
return Err(format!(
|
||||||
|
"Ugyldig executor: '{ex}'. Gyldige verdier: {VALID_EXECUTORS:?}"
|
||||||
|
));
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Valgfri: intelligence (1–3)
|
||||||
|
if let Some(val) = metadata.get("intelligence") {
|
||||||
|
match val.as_i64() {
|
||||||
|
Some(n) if (1..=3).contains(&n) => {}
|
||||||
|
_ => return Err("metadata.intelligence må være et heltall 1–3".into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Valgfri: effort (1–3)
|
||||||
|
if let Some(val) = metadata.get("effort") {
|
||||||
|
match val.as_i64() {
|
||||||
|
Some(n) if (1..=3).contains(&n) => {}
|
||||||
|
_ => return Err("metadata.effort må være et heltall 1–3".into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Valgfri: compiled (boolean)
|
||||||
|
if let Some(val) = metadata.get("compiled") {
|
||||||
|
if !val.is_boolean() {
|
||||||
|
return Err("metadata.compiled må være en boolean".into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Valgfri: pipeline (array)
|
||||||
|
if let Some(val) = metadata.get("pipeline") {
|
||||||
|
if !val.is_array() {
|
||||||
|
return Err("metadata.pipeline må være et array".into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
pub struct ErrorResponse {
|
pub struct ErrorResponse {
|
||||||
pub error: String,
|
pub error: String,
|
||||||
|
|
@ -517,6 +627,9 @@ pub async fn create_node(
|
||||||
// -- Valider metadata for AI-presets (oppgave 18.1) --
|
// -- Valider metadata for AI-presets (oppgave 18.1) --
|
||||||
validate_ai_preset_metadata(&node_kind, &metadata).map_err(|e| bad_request(&e))?;
|
validate_ai_preset_metadata(&node_kind, &metadata).map_err(|e| bad_request(&e))?;
|
||||||
|
|
||||||
|
// -- Valider metadata for orchestration-noder (oppgave 24.1) --
|
||||||
|
validate_orchestration_metadata(&node_kind, &metadata).map_err(|e| bad_request(&e))?;
|
||||||
|
|
||||||
// -- Kontekstbasert identitet (oppgave 8.2) --
|
// -- Kontekstbasert identitet (oppgave 8.2) --
|
||||||
// Hvis context_id er satt, sjekk om brukeren har et alias som er
|
// Hvis context_id er satt, sjekk om brukeren har et alias som er
|
||||||
// deltaker i kommunikasjonsnoden. I så fall brukes aliaset som created_by.
|
// deltaker i kommunikasjonsnoden. I så fall brukes aliaset som created_by.
|
||||||
|
|
@ -1051,6 +1164,9 @@ pub async fn update_node(
|
||||||
// -- Valider metadata for AI-presets (oppgave 18.1) --
|
// -- Valider metadata for AI-presets (oppgave 18.1) --
|
||||||
validate_ai_preset_metadata(&node_kind, &metadata).map_err(|e| bad_request(&e))?;
|
validate_ai_preset_metadata(&node_kind, &metadata).map_err(|e| bad_request(&e))?;
|
||||||
|
|
||||||
|
// -- Valider metadata for orchestration-noder (oppgave 24.1) --
|
||||||
|
validate_orchestration_metadata(&node_kind, &metadata).map_err(|e| bad_request(&e))?;
|
||||||
|
|
||||||
// -- Beskytt model_profile for egendefinerte AI-presets (oppgave 18.6) --
|
// -- Beskytt model_profile for egendefinerte AI-presets (oppgave 18.6) --
|
||||||
// Kun admin/owner på en samling kan endre model_profile. Vanlige brukere
|
// Kun admin/owner på en samling kan endre model_profile. Vanlige brukere
|
||||||
// som eier et custom preset kan redigere alt annet (prompt, icon, farge osv.)
|
// som eier et custom preset kan redigere alt annet (prompt, icon, farge osv.)
|
||||||
|
|
|
||||||
3
tasks.md
3
tasks.md
|
|
@ -316,8 +316,7 @@ Ref: `docs/concepts/orkestrering.md`. Orkestreringsnoder (`node_kind: 'orchestra
|
||||||
med fritekst-instruksjoner som boten utfører via function calling. Strukturerte triggere,
|
med fritekst-instruksjoner som boten utfører via function calling. Strukturerte triggere,
|
||||||
automatisk eskalering av intelligens ved feil, kompilering av velprøvde mønstre.
|
automatisk eskalering av intelligens ved feil, kompilering av velprøvde mønstre.
|
||||||
|
|
||||||
- [~] 24.1 Orchestration node-type: legg til `orchestration` i maskinrommets node-validering. Metadata-skjema: `trigger` (event + conditions), `executor`, `intelligence`, `effort`, `compiled`, `pipeline`. Valider trigger-events mot kjent liste.
|
- [x] 24.1 Orchestration node-type: legg til `orchestration` i maskinrommets node-validering. Metadata-skjema: `trigger` (event + conditions), `executor`, `intelligence`, `effort`, `compiled`, `pipeline`. Valider trigger-events mot kjent liste.
|
||||||
> Påbegynt: 2026-03-18T16:35
|
|
||||||
- [ ] 24.2 Trigger-evaluering i portvokteren: ved node/edge-events, sjekk om noen `orchestration`-noder matcher triggeren. Effektiv lookup (indeksert på `metadata.trigger.event`). Ingen LLM-kall for trigger-matching.
|
- [ ] 24.2 Trigger-evaluering i portvokteren: ved node/edge-events, sjekk om noen `orchestration`-noder matcher triggeren. Effektiv lookup (indeksert på `metadata.trigger.event`). Ingen LLM-kall for trigger-matching.
|
||||||
- [ ] 24.3 Bot-utførelse: utvid `synops-respond` (eller nytt `synops-orchestrate`) til å ta orchestration-node som input. Bygg prompt med trigger-kontekst + instruksjoner + tilgjengelige verktøy. Function calling for hvert steg. Logg i `orchestration_log`.
|
- [ ] 24.3 Bot-utførelse: utvid `synops-respond` (eller nytt `synops-orchestrate`) til å ta orchestration-node som input. Bygg prompt med trigger-kontekst + instruksjoner + tilgjengelige verktøy. Function calling for hvert steg. Logg i `orchestration_log`.
|
||||||
- [ ] 24.4 Auto-eskalering: start med lavt intelligens/effort-nivå. Ved feil (tool_error, ambiguous_instruction) bump automatisk til neste nivå og retry. Maks 3 nivåer.
|
- [ ] 24.4 Auto-eskalering: start med lavt intelligens/effort-nivå. Ved feil (tool_error, ambiguous_instruction) bump automatisk til neste nivå og retry. Maks 3 nivåer.
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue