import { Client, handle_file } from "@gradio/client" import type { CompileResult, CloudCompilerConfig, CompilerProvider, DetectParams, LocalConfig, RuleMutationResult, RunResult, ValidationResult, } from "./types" // Single shared connection to the gradio.Server backend. let clientPromise: Promise | null = null function getClient(): Promise { if (!clientPromise) { const origin = import.meta.env.DEV && import.meta.env.VITE_API_ORIGIN ? import.meta.env.VITE_API_ORIGIN : window.location.origin clientPromise = Client.connect(origin) } return clientPromise } async function call(endpoint: string, payload: Record): Promise { const client = await getClient() const result = await client.predict(endpoint, payload) return (result.data as unknown[])[0] as T } export async function detectAndAutomate( video: File, rulesText: string, params: DetectParams, ): Promise { return call("/detect_and_automate", { video: handle_file(video), classes: params.classes, rules_text: rulesText, confidence: params.confidence, sample_interval_sec: params.sampleIntervalSec, max_frames: params.maxFrames, model_name: params.modelName, image_size: params.imageSize, device: params.device, max_detections: params.maxDetections, enable_webhooks: params.enableWebhooks, webhook_url: params.webhookUrl, }) } export async function compileRules( instruction: string, classes: string, existingRulesText: string, compiler: CloudCompilerConfig, ): Promise { const apiKeyByProvider: Record = { replicate: compiler.replicateApiKey, openai: compiler.openaiApiKey, anthropic: compiler.anthropicApiKey, } const modelByProvider: Record = { replicate: "", openai: compiler.openaiModel, anthropic: compiler.anthropicModel, } return call("/compile_rules", { instruction, classes, existing_rules_text: existingRulesText, append: true, provider: compiler.provider, api_key: apiKeyByProvider[compiler.provider], model: modelByProvider[compiler.provider], }) } export async function validateRules(rulesText: string): Promise { return call("/validate_rules", { rules_text: rulesText }) } export async function saveRules(rulesText: string): Promise<{ ok: boolean; rule_count: number }> { return call("/save_rules", { rules_text: rulesText }) } export async function setRuleEnabled( rulesText: string, ruleName: string, enabled: boolean, ): Promise { return call("/set_rule_enabled", { rules_text: rulesText, rule_name: ruleName, enabled, }) } export async function deleteRule( rulesText: string, ruleName: string, ): Promise { return call("/delete_rule", { rules_text: rulesText, rule_name: ruleName, }) } export async function loadRules(): Promise<{ rules_text: string | null }> { return call("/load_rules", {}) } export async function getConfig(): Promise { return call("/get_config", {}) } // Resolve a backend media path (e.g. "/media/foo.mp4") to a fully-qualified URL. export function mediaUrl(path: string): string { const origin = import.meta.env.DEV && import.meta.env.VITE_API_ORIGIN ? import.meta.env.VITE_API_ORIGIN : window.location.origin return path.startsWith("http") ? path : `${origin}${path}` }