Valider fase 9–10: fiks typefeil, konsistens og feilhåndtering
Fase 9 (visninger): - graph: fiks TypeScript-feil (string|undefined → string|null) - kanban board: les kolonner fra metadata.traits.kanban.columns (konsistent med KanbanTrait), behold fallback til metadata.columns - dagbok: fiks createdAt-type (number, ikke BigInt med microsSinceUnixEpoch) Fase 10 (AI): - summarize.rs: refaktorer til cli_dispatch helper (DRY, konsistent med ai_edges.rs og tts.rs) - ai_process.rs: feil tidlig hvis LITELLM_MASTER_KEY mangler (var unwrap_or_default → tom streng → forvirrende 401) Alle 61 maskinrommet-tester bestått, alle CLI-verktøy kompilerer. LiteLLM kjører med riktig modellruting (rutine/resonering).
This commit is contained in:
parent
3ae46a05eb
commit
382f93132f
6 changed files with 19 additions and 54 deletions
|
|
@ -17,6 +17,9 @@
|
||||||
if (!boardNode) return ['todo', 'in_progress', 'done'];
|
if (!boardNode) return ['todo', 'in_progress', 'done'];
|
||||||
try {
|
try {
|
||||||
const meta = JSON.parse(boardNode.metadata ?? '{}');
|
const meta = JSON.parse(boardNode.metadata ?? '{}');
|
||||||
|
const traitConf = meta.traits?.kanban;
|
||||||
|
if (traitConf && Array.isArray(traitConf.columns) && traitConf.columns.length > 0) return traitConf.columns as string[];
|
||||||
|
// Fallback: legacy metadata.columns path
|
||||||
if (Array.isArray(meta.columns) && meta.columns.length > 0) return meta.columns as string[];
|
if (Array.isArray(meta.columns) && meta.columns.length > 0) return meta.columns as string[];
|
||||||
} catch { /* ignore */ }
|
} catch { /* ignore */ }
|
||||||
return ['todo', 'in_progress', 'done'];
|
return ['todo', 'in_progress', 'done'];
|
||||||
|
|
|
||||||
|
|
@ -42,9 +42,9 @@
|
||||||
|
|
||||||
// Sort by created_at descending (newest first)
|
// Sort by created_at descending (newest first)
|
||||||
entries.sort((a, b) => {
|
entries.sort((a, b) => {
|
||||||
const ta = a.createdAt?.microsSinceUnixEpoch ?? 0n;
|
const ta = a.createdAt ?? 0;
|
||||||
const tb = b.createdAt?.microsSinceUnixEpoch ?? 0n;
|
const tb = b.createdAt ?? 0;
|
||||||
return tb > ta ? 1 : tb < ta ? -1 : 0;
|
return tb - ta;
|
||||||
});
|
});
|
||||||
|
|
||||||
return entries;
|
return entries;
|
||||||
|
|
@ -102,8 +102,8 @@
|
||||||
const dayNames = ['søndag', 'mandag', 'tirsdag', 'onsdag', 'torsdag', 'fredag', 'lørdag'];
|
const dayNames = ['søndag', 'mandag', 'tirsdag', 'onsdag', 'torsdag', 'fredag', 'lørdag'];
|
||||||
|
|
||||||
function nodeDate(node: Node): Date {
|
function nodeDate(node: Node): Date {
|
||||||
const micros = node.createdAt?.microsSinceUnixEpoch ?? 0n;
|
const micros = node.createdAt ?? 0;
|
||||||
return new Date(Number(micros / 1000n));
|
return new Date(micros / 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatDateKey(d: Date): string {
|
function formatDateKey(d: Date): string {
|
||||||
|
|
|
||||||
|
|
@ -644,7 +644,7 @@
|
||||||
|
|
||||||
<div class="mt-4 flex flex-col gap-1">
|
<div class="mt-4 flex flex-col gap-1">
|
||||||
<button
|
<button
|
||||||
onclick={() => { focusId = selectedNode?.id; loadGraph(); }}
|
onclick={() => { focusId = selectedNode?.id ?? null; loadGraph(); }}
|
||||||
class="rounded bg-gray-100 px-2 py-1 text-xs text-gray-700 hover:bg-gray-200"
|
class="rounded bg-gray-100 px-2 py-1 text-xs text-gray-700 hover:bg-gray-200"
|
||||||
>
|
>
|
||||||
Fokuser på denne
|
Fokuser på denne
|
||||||
|
|
@ -653,7 +653,7 @@
|
||||||
onclick={() => {
|
onclick={() => {
|
||||||
showMentionsForm = true;
|
showMentionsForm = true;
|
||||||
showTopicForm = false;
|
showTopicForm = false;
|
||||||
mentionsSourceId = selectedNode?.id;
|
mentionsSourceId = selectedNode?.id ?? '';
|
||||||
}}
|
}}
|
||||||
class="rounded bg-purple-100 px-2 py-1 text-xs text-purple-700 hover:bg-purple-200"
|
class="rounded bg-purple-100 px-2 py-1 text-xs text-purple-700 hover:bg-purple-200"
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -428,7 +428,8 @@ async fn call_ai_gateway(
|
||||||
) -> Result<(String, Option<UsageInfo>, Option<String>), String> {
|
) -> Result<(String, Option<UsageInfo>, Option<String>), String> {
|
||||||
let gateway_url = std::env::var("AI_GATEWAY_URL")
|
let gateway_url = std::env::var("AI_GATEWAY_URL")
|
||||||
.unwrap_or_else(|_| "http://localhost:4000".to_string());
|
.unwrap_or_else(|_| "http://localhost:4000".to_string());
|
||||||
let api_key = std::env::var("LITELLM_MASTER_KEY").unwrap_or_default();
|
let api_key = std::env::var("LITELLM_MASTER_KEY")
|
||||||
|
.map_err(|_| "LITELLM_MASTER_KEY ikke satt — kan ikke kalle AI Gateway".to_string())?;
|
||||||
|
|
||||||
let request = ChatRequest {
|
let request = ChatRequest {
|
||||||
model: model_alias.to_string(),
|
model: model_alias.to_string(),
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,9 @@
|
||||||
// Jobbtype: "summarize_communication"
|
// Jobbtype: "summarize_communication"
|
||||||
// Payload: { "communication_id": "<uuid>", "requested_by": "<uuid>" }
|
// Payload: { "communication_id": "<uuid>", "requested_by": "<uuid>" }
|
||||||
|
|
||||||
use std::process::Stdio;
|
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use crate::cli_dispatch;
|
||||||
use crate::jobs::JobRow;
|
use crate::jobs::JobRow;
|
||||||
|
|
||||||
/// Synops-summarize binary path.
|
/// Synops-summarize binary path.
|
||||||
|
|
@ -55,24 +55,10 @@ pub async fn handle_summarize_communication(
|
||||||
.arg("--write");
|
.arg("--write");
|
||||||
|
|
||||||
// Sett miljøvariabler CLI-verktøyet trenger
|
// Sett miljøvariabler CLI-verktøyet trenger
|
||||||
let db_url = std::env::var("DATABASE_URL")
|
cli_dispatch::set_database_url(&mut cmd)?;
|
||||||
.map_err(|_| "DATABASE_URL ikke satt".to_string())?;
|
cli_dispatch::forward_env(&mut cmd, "AI_GATEWAY_URL");
|
||||||
|
cli_dispatch::forward_env(&mut cmd, "LITELLM_MASTER_KEY");
|
||||||
cmd.env("DATABASE_URL", &db_url);
|
cli_dispatch::forward_env(&mut cmd, "AI_SUMMARY_MODEL");
|
||||||
|
|
||||||
// Videresend AI-relaterte env-variabler hvis satt
|
|
||||||
if let Ok(v) = std::env::var("AI_GATEWAY_URL") {
|
|
||||||
cmd.env("AI_GATEWAY_URL", v);
|
|
||||||
}
|
|
||||||
if let Ok(v) = std::env::var("LITELLM_MASTER_KEY") {
|
|
||||||
cmd.env("LITELLM_MASTER_KEY", v);
|
|
||||||
}
|
|
||||||
if let Ok(v) = std::env::var("AI_SUMMARY_MODEL") {
|
|
||||||
cmd.env("AI_SUMMARY_MODEL", v);
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd.stdout(Stdio::piped())
|
|
||||||
.stderr(Stdio::piped());
|
|
||||||
|
|
||||||
tracing::info!(
|
tracing::info!(
|
||||||
communication_id = %communication_id,
|
communication_id = %communication_id,
|
||||||
|
|
@ -81,31 +67,7 @@ pub async fn handle_summarize_communication(
|
||||||
"Starter synops-summarize"
|
"Starter synops-summarize"
|
||||||
);
|
);
|
||||||
|
|
||||||
// Spawn og vent
|
let result = cli_dispatch::run_cli_tool(&bin, &mut cmd).await?;
|
||||||
let child = cmd
|
|
||||||
.spawn()
|
|
||||||
.map_err(|e| format!("Kunne ikke starte {bin}: {e}"))?;
|
|
||||||
let output = child
|
|
||||||
.wait_with_output()
|
|
||||||
.await
|
|
||||||
.map_err(|e| format!("Feil ved kjøring av {bin}: {e}"))?;
|
|
||||||
|
|
||||||
let stderr = String::from_utf8_lossy(&output.stderr);
|
|
||||||
if !stderr.is_empty() {
|
|
||||||
tracing::info!(stderr = %stderr, "synops-summarize stderr");
|
|
||||||
}
|
|
||||||
|
|
||||||
if !output.status.success() {
|
|
||||||
let code = output.status.code().unwrap_or(-1);
|
|
||||||
return Err(format!(
|
|
||||||
"synops-summarize feilet (exit {code}): {stderr}"
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse stdout som JSON — det er resultatet
|
|
||||||
let stdout = String::from_utf8_lossy(&output.stdout);
|
|
||||||
let result: serde_json::Value = serde_json::from_str(&stdout)
|
|
||||||
.map_err(|e| format!("Kunne ikke parse synops-summarize output: {e}"))?;
|
|
||||||
|
|
||||||
tracing::info!(
|
tracing::info!(
|
||||||
communication_id = %communication_id,
|
communication_id = %communication_id,
|
||||||
|
|
|
||||||
3
tasks.md
3
tasks.md
|
|
@ -298,8 +298,7 @@ med spesifikasjon for det som trenger en dedikert sesjon.
|
||||||
- [x] 23.1 Valider fase 1–2 (infra + maskinrommet): PG-skjema, indekser, auth-middleware, intensjoner, STDB-klient (nå erstattet av WS). Verifiser at skjema matcher docs, at auth fungerer, at skrivestien er konsistent.
|
- [x] 23.1 Valider fase 1–2 (infra + maskinrommet): PG-skjema, indekser, auth-middleware, intensjoner, STDB-klient (nå erstattet av WS). Verifiser at skjema matcher docs, at auth fungerer, at skrivestien er konsistent.
|
||||||
- [x] 23.2 Valider fase 3–4 (frontend + tilgang): SvelteKit-oppsett, OIDC-flow, sanntid, mottaksflate, TipTap-editor, node_access-matrise, team-transitivitet, visibility-filtrering.
|
- [x] 23.2 Valider fase 3–4 (frontend + tilgang): SvelteKit-oppsett, OIDC-flow, sanntid, mottaksflate, TipTap-editor, node_access-matrise, team-transitivitet, visibility-filtrering.
|
||||||
- [x] 23.3 Valider fase 5–8 (kommunikasjon + CAS + lyd + aliaser): chat-loop, kontekst-arv, CAS-hashing/deduplisering, Whisper-pipeline, segmenttabell, SRT-eksport, alias-identitet.
|
- [x] 23.3 Valider fase 5–8 (kommunikasjon + CAS + lyd + aliaser): chat-loop, kontekst-arv, CAS-hashing/deduplisering, Whisper-pipeline, segmenttabell, SRT-eksport, alias-identitet.
|
||||||
- [~] 23.4 Valider fase 9–10 (visninger + AI): kanban drag-and-drop, kalender, dagbok, kunnskapsgraf, LiteLLM-ruting, AI-foreslåtte edges, oppsummering, TTS.
|
- [x] 23.4 Valider fase 9–10 (visninger + AI): kanban drag-and-drop, kalender, dagbok, kunnskapsgraf, LiteLLM-ruting, AI-foreslåtte edges, oppsummering, TTS.
|
||||||
> Påbegynt: 2026-03-18T15:00
|
|
||||||
- [ ] 23.5 Valider fase 11 (produksjon): LiveKit-oppsett, sanntidslyd, pruning-logikk, podcast-RSS.
|
- [ ] 23.5 Valider fase 11 (produksjon): LiveKit-oppsett, sanntidslyd, pruning-logikk, podcast-RSS.
|
||||||
- [ ] 23.6 Valider fase 13–14 (traits + publisering): trait-validering, pakkevelger, Tera-templates, HTML-rendering, forside, slot-håndtering, redaksjonell flyt, planlagt publisering, A/B-testing.
|
- [ ] 23.6 Valider fase 13–14 (traits + publisering): trait-validering, pakkevelger, Tera-templates, HTML-rendering, forside, slot-håndtering, redaksjonell flyt, planlagt publisering, A/B-testing.
|
||||||
- [ ] 23.7 Valider fase 15–16 (admin + lydmixer): systemvarsler, graceful shutdown, jobbkø-oversikt, ressursstyring, serverhelse, Web Audio mixer, delt kontroll, sound pads, EQ, stemmeeffekter.
|
- [ ] 23.7 Valider fase 15–16 (admin + lydmixer): systemvarsler, graceful shutdown, jobbkø-oversikt, ressursstyring, serverhelse, Web Audio mixer, delt kontroll, sound pads, EQ, stemmeeffekter.
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue