synops/maskinrommet/src/clip.rs
vegard 8af4265b6e synops-clip orkestrering-støtte: cli_tool-registrering + clip_url jobb/API (oppgave 25.4)
Gjør synops-clip tilgjengelig i orkestreringer ved å:

1. Registrere synops-clip som cli_tool-node (migration 026) med norske
   aliases (clip, klipp, hent artikkel) og args_hints for script-kompilatoren.
   Orkestreringer kan nå skrive "1. clip fra event (lagre node, bruker)"
   som kompileres til "synops-clip --url {event.url} --write --created-by ...".

2. Legge til clip_url som jobbtype i jobbkøen (clip.rs) — spawner
   synops-clip med riktige env-variabler (DATABASE_URL, AI_GATEWAY_URL, etc).

3. Legge til POST /intentions/clip_url API-endepunkt slik at frontend
   og andre klienter kan trigge URL-klipping direkte.

4. Utvide trigger-konteksten med event.url og event.created_by slik at
   orkestreringer som reagerer på URL-deling kan videresende URL til
   synops-clip via variabel-substitusjon.
2026-03-18 18:55:11 +00:00

105 lines
2.7 KiB
Rust

// URL-klipping dispatcher — delegerer til synops-clip CLI.
//
// Maskinrommet orkestrerer (payload-parsing, sikkerhetskontroller),
// CLI-verktøyet gjør jobben (HTTP-henting, Readability-parsing,
// node-opprettelse, AI-oppsummering).
//
// Jobbtype: "clip_url"
// Payload: { "url": "<url>", "created_by": "<uuid>", "write": true }
//
// Ref: docs/retninger/unix_filosofi.md
use uuid::Uuid;
use crate::cli_dispatch;
use crate::jobs::JobRow;
/// Synops-clip binary path.
fn clip_bin() -> String {
std::env::var("SYNOPS_CLIP_BIN")
.unwrap_or_else(|_| "synops-clip".to_string())
}
/// Håndterer clip_url-jobb.
///
/// Spawner synops-clip med URL og valgfri --write for å gjøre alt arbeidet:
/// HTTP-henting, Readability-parsing, node-opprettelse, AI-oppsummering.
pub async fn handle_clip_url(
job: &JobRow,
_db: &sqlx::PgPool,
) -> Result<serde_json::Value, String> {
let url = job
.payload
.get("url")
.and_then(|v| v.as_str())
.ok_or("Mangler url i payload")?;
let write = job
.payload
.get("write")
.and_then(|v| v.as_bool())
.unwrap_or(true);
let created_by: Option<Uuid> = job
.payload
.get("created_by")
.and_then(|v| v.as_str())
.and_then(|s| s.parse().ok());
let playwright = job
.payload
.get("playwright")
.and_then(|v| v.as_bool())
.unwrap_or(false);
let timeout = job
.payload
.get("timeout")
.and_then(|v| v.as_u64());
// Bygg kommando
let bin = clip_bin();
let mut cmd = tokio::process::Command::new(&bin);
cmd.arg("--url").arg(url);
if write {
cmd.arg("--write");
if let Some(uid) = created_by {
cmd.arg("--created-by").arg(uid.to_string());
}
}
if playwright {
cmd.arg("--playwright");
}
if let Some(t) = timeout {
cmd.arg("--timeout").arg(t.to_string());
}
// 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");
cli_dispatch::forward_env(&mut cmd, "AI_CLIP_MODEL");
cli_dispatch::forward_env(&mut cmd, "SYNOPS_CLIP_SCRIPTS");
tracing::info!(
url = %url,
write = write,
bin = %bin,
"Starter synops-clip"
);
let result = cli_dispatch::run_cli_tool(&bin, &mut cmd).await?;
tracing::info!(
url = %url,
title = result["title"].as_str().unwrap_or("n/a"),
paywall = result["paywall"].as_bool().unwrap_or(false),
"synops-clip fullført"
);
Ok(result)
}