"use server"; import { requireSession } from "@/lib/session"; import { apiFetch, ApiError } from "@/lib/api"; function extractErrorMessage(err: unknown): string { if (err instanceof ApiError) { try { const parsed = JSON.parse(err.message); if (Array.isArray(parsed.message)) return parsed.message.join(" "); if (typeof parsed.message === "string") return parsed.message; } catch { // corpo não era JSON } return err.message || "Falha inesperada na API."; } return "Falha inesperada. Tente novamente."; } type ActionResult = { ok: true; state: string } | { ok: false; error: string }; async function callAgentMe(path: string, body?: unknown): Promise { const session = await requireSession(); try { const res = await apiFetch<{ state: string }>(`/agents/me${path}`, session.accessToken, { method: "POST", ...(body !== undefined ? { body: JSON.stringify(body) } : {}), }); return { ok: true, state: res.state }; } catch (err) { return { ok: false, error: extractErrorMessage(err) }; } } // Server Actions exportadas como arrow function que só repassam // argumentos pra outra função quebram em runtime ("Server Actions must // be async functions") — achado real já documentado nesta sessão // (mesmo bug do wizard de campanhas). Precisam ser `async function` de // verdade, mesmo só repassando. export async function agentLogin(): Promise { return callAgentMe("/login"); } export async function agentLogout(): Promise { return callAgentMe("/logout"); } export async function agentResume(): Promise { return callAgentMe("/resume"); } export async function agentPause(pauseReasonId: string): Promise { return callAgentMe("/pause", { pauseReasonId }); } export type SoftphoneConfig = | { hasExtension: false } | { hasExtension: true; username: string; domain: string; password: string; displayName: string; proxyUrl: string | null }; /** * Sob demanda, não no layout (agente.md secao 39/178: decifrar senha é * sensível e fica no audit log — buscar isto em toda navegação encheria o * log à toa). Chamado uma vez pelo próprio widget do softphone quando ele * monta, só pra quem já tem um Agent com ramal vinculado. */ export async function getSoftphoneConfig(): Promise<{ ok: true; config: SoftphoneConfig } | { ok: false; error: string }> { const session = await requireSession(); try { const config = await apiFetch("/agents/me/softphone-config", session.accessToken); return { ok: true, config }; } catch (err) { return { ok: false, error: extractErrorMessage(err) }; } }