import { useEffect, useMemo, useState } from "react"; import type { FormEvent } from "react"; import { authorizedHeaders, authTokenFromStorage, jsonHeaders, api } from "./api"; type PublicWebhook = { id: string; label: string; description?: string; method: string; required_roles: string[]; confirmation_required: boolean; }; type RunResult = | { kind: "idle" } | { kind: "running" } | { kind: "success"; responseStatus: number | null; runId: string } | { kind: "error"; message: string }; type WebhookFormTabProps = { webhookId: string; sessionId: string; onBack: () => void; }; const labelsEn = { title: "Run webhook", description: "Description", requiredRoles: "Required roles", confirmation: "Requires confirmation", method: "Method", payload: "Payload (optional JSON)", payloadHelp: "These fields are merged with the backend template. Available variables: {user}, {session}, {message}.", run: "Run", running: "Running...", resultOk: "Webhook executed", resultErr: "Failed to execute", httpStatus: "HTTP", runId: "Audit ID", back: "Back to chat", notFound: "Webhook not found or insufficient permissions", loading: "Loading webhook...", user: "User", session: "Session", }; const detectLanguage = (): "en" => "en"; const WebhookFormTabInner = ({ webhookId, sessionId, onBack }: WebhookFormTabProps) => { const [labels] = useState(() => labelsEn); const [webhook, setWebhook] = useState(null); const [payload, setPayload] = useState("{}"); const [result, setResult] = useState({ kind: "idle" }); const [error, setError] = useState(null); useEffect(() => { void (async () => { try { const data = await api<{ items: PublicWebhook[] }>("/api/webhooks"); const found = data.items.find((item) => item.id === webhookId); if (!found) { setError(labels.notFound); return; } setWebhook(found); } catch (err) { console.error(err); setError(labels.notFound); } })(); }, [webhookId, labels.notFound]); const submit = async (event: FormEvent) => { event.preventDefault(); if (!webhook) return; if (webhook.confirmation_required) { const ok = window.confirm(`Run ${webhook.label}?`); if (!ok) return; } let parsed: Record = {}; if (payload.trim().length > 0) { try { const value = JSON.parse(payload); if (value && typeof value === "object" && !Array.isArray(value)) { parsed = value as Record; } } catch { setResult({ kind: "error", message: "Payload is not valid JSON" }); return; } } setResult({ kind: "running" }); try { const response = await fetch(`/api/webhooks/${webhook.id}/run`, { method: "POST", headers: jsonHeaders(), body: JSON.stringify({ sessionId, confirmed: true, lastUserMessage: undefined, payload: parsed, }), }); if (!response.ok) { const detail = await response.text().catch(() => ""); throw new Error(`http_${response.status}: ${detail.slice(0, 200)}`); } const body = (await response.json()) as { id: string; response_status: number | null }; setResult({ kind: "success", responseStatus: body.response_status, runId: body.id }); } catch (err) { console.error(err); const message = err instanceof Error ? err.message : "error"; setResult({ kind: "error", message }); } }; const tokenInfo = useMemo(() => { const t = authTokenFromStorage(); return t ? `${t.slice(0, 12)}…` : labels.notFound; }, [labels.notFound]); if (error) { return (

{labels.title}

{error}

); } if (!webhook) { return (

{labels.title}

{labels.loading}

); } return (
SIC

{webhook.label}

{webhook.description ? (
{labels.description}
{webhook.description}
) : null}
{labels.method}
{webhook.method}
{labels.requiredRoles}
{webhook.required_roles.join(", ")}
{labels.confirmation}
{webhook.confirmation_required ? "Yes" : "No"}
{labels.session}
{sessionId.slice(0, 8)}…
{labels.user}
{tokenInfo}