synops/maskinrommet/src/ai_edges.rs
vegard a06b79478a AI-rutingskontroll i admin: 13 kontekster konfigurerbare uten redeploy (oppgave 28.2)
Utvider /admin/ai med full kontroll over hvilken modellalias som brukes
per AI-kontekst. Admin kan bytte modell for orkestrering, bot-chat,
oppsummering, edge-forslag, klassifisering osv. uten å restarte
maskinrommet.

Endringer:
- Migration 028: seeder 7 nye kontekster i ai_job_routing
  (orchestration_script/dream, bot_chat/triage, summarize, suggest_edges, classify)
- Backend: resolve_routing_or_default() i ai_admin.rs — felles oppslag
  mot ai_job_routing med fallback til sidelinja/rutine
- Dispatchers (ai_edges, summarize) bruker nå routing-tabellen i stedet
  for hardkodede env-variabler — endringer trer i kraft umiddelbart
- Frontend: Ruting-tab omskrevet med kategoriserte kontekster
  (Orkestrering, Bot & chat, Analyse, Prosessering), beskrivelser per
  kontekst, og støtte for egendefinerte regler
- Docs: ai_gateway.md §3.4 oppdatert med alle 13 kontekster
2026-03-18 20:06:50 +00:00

81 lines
2.5 KiB
Rust

// AI edge-forslag dispatcher — delegerer til synops-suggest-edges CLI.
//
// Maskinrommet orkestrerer, CLI-verktøyet gjør jobben (LLM-kall,
// topic-opprettelse, edge-skriving, ressurslogging).
//
// Jobbtype: "suggest_edges"
// Payload: { "node_id": "<uuid>" }
//
// Ref: docs/retninger/unix_filosofi.md, docs/infra/ai_gateway.md,
// docs/concepts/kunnskapsgrafen.md
use uuid::Uuid;
use crate::ai_admin;
use crate::cli_dispatch;
use crate::jobs::JobRow;
/// Synops-suggest-edges binary path.
fn suggest_edges_bin() -> String {
std::env::var("SYNOPS_SUGGEST_EDGES_BIN")
.unwrap_or_else(|_| "synops-suggest-edges".to_string())
}
/// Håndterer suggest_edges-jobb.
///
/// Spawner synops-suggest-edges med --write for å gjøre alt arbeidet:
/// LLM-kall, topic-opprettelse, edge-skriving, ressurslogging.
pub async fn handle_suggest_edges(
job: &JobRow,
db: &sqlx::PgPool,
) -> Result<serde_json::Value, String> {
let node_id: Uuid = job
.payload
.get("node_id")
.and_then(|v| v.as_str())
.and_then(|s| s.parse().ok())
.ok_or("Mangler gyldig node_id i payload")?;
// requested_by er valgfri — bruk node_id som fallback for --write
let requested_by = job
.payload
.get("requested_by")
.and_then(|v| v.as_str())
.unwrap_or(&node_id.to_string())
.to_string();
// Bygg kommando
let bin = suggest_edges_bin();
let mut cmd = tokio::process::Command::new(&bin);
cmd.arg("--node-id").arg(node_id.to_string())
.arg("--requested-by").arg(&requested_by)
.arg("--write");
// Sett miljøvariabler CLI-verktøyet trenger
cli_dispatch::set_database_url(&mut cmd)?;
cli_dispatch::forward_env(&mut cmd, "AI_GATEWAY_URL");
cli_dispatch::forward_env(&mut cmd, "LITELLM_MASTER_KEY");
// Modellalias fra ai_job_routing — admin kan endre uten redeploy
let model_alias = ai_admin::resolve_routing_or_default(db, "suggest_edges").await;
cmd.env("AI_EDGES_MODEL", &model_alias);
tracing::info!(
node_id = %node_id,
bin = %bin,
"Starter synops-suggest-edges"
);
let result = cli_dispatch::run_cli_tool(&bin, &mut cmd).await?;
tracing::info!(
node_id = %node_id,
topics_created = result["topics_created"].as_u64().unwrap_or(0),
edges_created = result["edges_created"].as_u64().unwrap_or(0),
status = result["status"].as_str().unwrap_or("unknown"),
"synops-suggest-edges fullført"
);
Ok(result)
}