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(())
|
||||
}
|
||||
|
||||
/// 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.
|
||||
/// Ref: docs/infra/ai_gateway.md § "Modellprofiler"
|
||||
const VALID_MODEL_PROFILES: &[&str] = &["flash", "standard"];
|
||||
|
|
@ -188,6 +203,101 @@ fn validate_ai_preset_metadata(
|
|||
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)]
|
||||
pub struct ErrorResponse {
|
||||
pub error: String,
|
||||
|
|
@ -517,6 +627,9 @@ pub async fn create_node(
|
|||
// -- Valider metadata for AI-presets (oppgave 18.1) --
|
||||
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) --
|
||||
// Hvis context_id er satt, sjekk om brukeren har et alias som er
|
||||
// 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) --
|
||||
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) --
|
||||
// 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.)
|
||||
|
|
|
|||
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,
|
||||
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.
|
||||
> Påbegynt: 2026-03-18T16:35
|
||||
- [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.
|
||||
- [ ] 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.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