import { get, post } from "./serviceHelper";
export const AGENT_BASE_URL = "/parhelia/agent";
export async function getAgentAvailableTools(agentId) {
    const result = await get(AGENT_BASE_URL + "/getAvailableTools?agentId=" + agentId);
    if (result.type !== "success") {
        throw new Error(`Failed to get available tools: ${result.summary || "Unknown error"} ${result.details || ""}`);
    }
    const raw = Array.isArray(result.data) ? result.data : [];
    return raw
        .map((tool) => String(tool ?? "").trim())
        .filter((tool) => tool.length > 0);
}
export async function approveToolCall(params) {
    const result = await post(AGENT_BASE_URL + "/approveToolCall", params);
    if (result.type !== "success") {
        throw new Error(`Failed to approve tool call: ${result.summary || "Unknown error"} ${result.details || ""}`);
    }
    return result.data ?? { success: true };
}
export async function approveToolCalls(params) {
    const result = await post(AGENT_BASE_URL + "/approveToolCalls", params);
    if (result.type !== "success") {
        throw new Error(`Failed to approve tool calls: ${result.summary || "Unknown error"} ${result.details || ""}`);
    }
    return result.data ?? { success: true, approvedToolCallIds: [] };
}
export async function rejectToolCall(params) {
    const result = await post(AGENT_BASE_URL + "/rejectToolCall", params);
    if (result.type !== "success") {
        throw new Error(`Failed to reject tool call: ${result.summary || "Unknown error"} ${result.details || ""}`);
    }
    return result.data ?? { success: true };
}
export async function createOperationAllowance(params) {
    const result = await post(AGENT_BASE_URL + "/createOperationAllowance", params);
    if (result.type !== "success") {
        throw new Error(`Failed to create operation allowance: ${result.summary || "Unknown error"} ${result.details || ""}`);
    }
    return result.data ?? { success: true };
}
export const AGENT_DOCUMENT_UPLOADED_EVENT = "agent:document:uploaded";
export const AGENT_DOCUMENTS_CHANGED_EVENT = "agent:documents:changed";
function emitAgentDocumentUploaded(detail) {
    if (typeof window === "undefined") {
        return;
    }
    window.dispatchEvent(new CustomEvent(AGENT_DOCUMENT_UPLOADED_EVENT, {
        detail,
    }));
}
export function emitAgentDocumentsChanged(detail) {
    if (typeof window === "undefined") {
        return;
    }
    window.dispatchEvent(new CustomEvent(AGENT_DOCUMENTS_CHANGED_EVENT, {
        detail,
    }));
}
/**
 * Starts an agent execution and returns immediately
 */
export async function startAgent(request) {
    const result = await post(AGENT_BASE_URL + "/start", request);
    if (result.type !== "success") {
        const summary = (result.summary || "").trim();
        const details = (result.details || "").trim();
        const meaningfulSummary = summary && !/^error$/i.test(summary) && !/^unknown error$/i.test(summary)
            ? summary
            : "";
        const combinedMessage = [meaningfulSummary, details]
            .filter(Boolean)
            .join(": ");
        throw new Error(`Failed to start agent: ${combinedMessage || "Unknown error"}`);
    }
    return result.data;
}
/**
 * Starts a suggestion agent to describe an image based on context.
 */
export async function startSuggestionAgent(request) {
    const result = await post(AGENT_BASE_URL + "/startSuggestionAgent", request);
    if (result.type !== "success") {
        throw new Error(`Failed to start suggestion agent: ${result.summary || "Unknown error"} ${result.details || ""}`);
    }
    return result.data;
}
/**
 * Awaits an agent's response via WebSocket messages.
 * Subscribes to the agent, accumulates streaming content, and resolves when complete.
 */
export function awaitAgentResponse(options) {
    const { agentId, addSocketMessageListener, timeout = 60000, onContentUpdate, } = options;
    return new Promise((resolve) => {
        let accumulatedContent = "";
        let unsubscribe = null;
        let timeoutId = null;
        let resolved = false;
        const cleanup = () => {
            if (timeoutId) {
                clearTimeout(timeoutId);
                timeoutId = null;
            }
            if (unsubscribe) {
                unsubscribe();
                unsubscribe = null;
            }
            // Unsubscribe from WebSocket
            const socket = globalThis.editorSocket;
            if (socket && socket.readyState === WebSocket.OPEN) {
                socket.send(JSON.stringify({
                    type: "agent:unsubscribe",
                    agentId: agentId,
                }));
            }
        };
        const complete = (result) => {
            if (resolved)
                return;
            resolved = true;
            cleanup();
            resolve(result);
        };
        // Set up timeout
        timeoutId = setTimeout(() => {
            complete({
                content: accumulatedContent,
                success: false,
                error: "Request timed out",
            });
        }, timeout);
        // Subscribe to WebSocket messages
        const socket = globalThis.editorSocket;
        if (socket && socket.readyState === WebSocket.OPEN) {
            socket.send(JSON.stringify({
                type: "agent:subscribe",
                agentId: agentId,
            }));
        }
        // Add message listener
        const handleMessage = (message) => {
            // Only handle messages for our agent
            if (message.agentId !== agentId && message.payload?.agentId !== agentId) {
                return;
            }
            const msgType = message.type;
            if (msgType === "agent:run:delta") {
                // Content chunks come via agent:run:delta with data.deltaContent
                const deltaData = message.payload?.data;
                const content = deltaData?.deltaContent || "";
                const isIncremental = deltaData?.isIncremental !== false;
                if (content) {
                    if (isIncremental) {
                        accumulatedContent += content;
                    }
                    else {
                        accumulatedContent = content;
                    }
                    onContentUpdate?.(accumulatedContent);
                }
            }
            else if (msgType === "agent:message:complete" ||
                msgType === "agent:run:complete") {
                // Agent completed successfully
                complete({
                    content: accumulatedContent.trim(),
                    success: true,
                });
            }
            else if (msgType === "agent:error") {
                const errorMsg = message.payload?.error || message.data?.error || "An error occurred";
                complete({
                    content: accumulatedContent,
                    success: false,
                    error: errorMsg,
                });
            }
            else if (msgType === "agent:status:update") {
                const status = message.payload?.status;
                if (status === "completed" || status === "idle") {
                    complete({
                        content: accumulatedContent.trim(),
                        success: true,
                    });
                }
                else if (status === "error") {
                    complete({
                        content: accumulatedContent,
                        success: false,
                        error: message.payload?.message || "Agent error",
                    });
                }
            }
        };
        unsubscribe = addSocketMessageListener(handleMessage);
    });
}
/**
 * Gets the current status of an agent execution
 */
export async function getAgentStatus(agentId) {
    const result = await get(AGENT_BASE_URL + "/getAgentStatus?agentId=" + agentId);
    if (result.type !== "success") {
        throw new Error(`Failed to get agent status: ${result.summary || "Unknown error"} ${result.details || ""}`);
    }
    return result.data;
}
/**
 * Gets all currently running agents for monitoring
 */
export async function getRunningAgents() {
    const result = await get(AGENT_BASE_URL + "/getRunningAgents");
    if (result.type !== "success") {
        throw new Error(`Failed to get running agents: ${result.summary || "Unknown error"} ${result.details || ""}`);
    }
    return result.data;
}
/**
 * Gets a single agent by ID with complete message history and cost information
 */
export async function getAgent(agentId) {
    const result = await get(AGENT_BASE_URL + "/getAgent?agentId=" + agentId);
    if (result.type !== "success") {
        throw new Error(`Failed to get agent: ${result.summary || "Unknown error"} ${result.details || ""}`);
    }
    return result.data;
}
/**
 * Gets the last API payload and raw response for an agent (for debugging purposes)
 */
export async function getLastPayload(agentId) {
    const result = await get(AGENT_BASE_URL + "/getLastPayload?agentId=" + agentId);
    if (result.type !== "success") {
        throw new Error(`Failed to get last payload: ${result.summary || "Unknown error"} ${result.details || ""}`);
    }
    return {
        payload: result.data?.payload || "",
        rawResponse: result.data?.rawResponse || "",
    };
}
export async function getAgentDiagnostics(agentId, sessionId) {
    const query = new URLSearchParams({ agentId });
    if (sessionId) {
        query.set("sessionId", sessionId);
    }
    const result = await get(`${AGENT_BASE_URL}/getDiagnostics?${query.toString()}`);
    if (result.type !== "success") {
        throw new Error(`Failed to get agent diagnostics: ${result.summary || "Unknown error"} ${result.details || ""}`);
    }
    return (result.data ?? {
        agentId,
        execution: {
            status: "unknown",
            isInMemoryExecution: false,
        },
        transport: {
            targetSessionCount: 0,
            successfulSessionCount: 0,
            failedSessionCount: 0,
            connectedSubscriberCount: 0,
            recentEvents: [],
        },
        currentSession: {
            sessionFound: false,
            browserMatched: false,
            isConnected: false,
            isSubscribed: false,
        },
        persistentLogs: [],
    });
}
const AGENT_COLLECTION_CACHE_TTL_MS = 2000;
const activeAgentsResponseCache = new Map();
const activeAgentsInFlightRequests = new Map();
const groupedAgentsResponseCache = new Map();
const groupedAgentsInFlightRequests = new Map();
function createAbortError() {
    const abortError = new Error("The operation was aborted.");
    abortError.name = "AbortError";
    return abortError;
}
function cloneAgent(agent) {
    return { ...agent };
}
function cloneGetAgentsResponse(response) {
    return {
        ...response,
        agents: response.agents.map(cloneAgent),
    };
}
function cloneGetAgentsGroupedResponse(response) {
    return {
        activeAgents: response.activeAgents.map(cloneAgent),
        closedAgentsByProfile: response.closedAgentsByProfile.map((group) => ({
            ...group,
            agents: group.agents.map(cloneAgent),
        })),
    };
}
function getFreshCachedValue(cache, key) {
    const entry = cache.get(key);
    if (!entry)
        return null;
    if (entry.expiresAt <= Date.now()) {
        cache.delete(key);
        return null;
    }
    return entry.value;
}
function invalidateAgentCollectionCaches() {
    activeAgentsResponseCache.clear();
    activeAgentsInFlightRequests.clear();
    groupedAgentsResponseCache.clear();
    groupedAgentsInFlightRequests.clear();
}
/**
 * Gets all agents for the current user with pagination and search support
 */
export async function getActiveAgents(params) {
    const queryParams = new URLSearchParams();
    if (params?.skip !== undefined)
        queryParams.append("skip", params.skip.toString());
    if (params?.limit !== undefined)
        queryParams.append("limit", params.limit.toString());
    if (params?.includeShared !== undefined)
        queryParams.append("includeShared", params.includeShared.toString());
    if (params?.includeOwned !== undefined)
        queryParams.append("includeOwned", params.includeOwned.toString());
    if (params?.searchTerm)
        queryParams.append("searchTerm", params.searchTerm);
    if (params?.excludeClosed !== undefined)
        queryParams.append("excludeClosed", params.excludeClosed.toString());
    const queryString = queryParams.toString();
    const url = AGENT_BASE_URL + "/getAgents" + (queryString ? `?${queryString}` : "");
    if (params?.signal?.aborted) {
        throw createAbortError();
    }
    const cachedResponse = getFreshCachedValue(activeAgentsResponseCache, url);
    if (cachedResponse) {
        return cloneGetAgentsResponse(cachedResponse);
    }
    if (!params?.signal) {
        const existingRequest = activeAgentsInFlightRequests.get(url);
        if (existingRequest) {
            return cloneGetAgentsResponse(await existingRequest);
        }
    }
    const requestPromise = (async () => {
        const result = await get(url, undefined, params?.signal);
        if (result.type !== "success") {
            const detailText = (result.details || "").toLowerCase();
            const summaryText = (result.summary || "").toLowerCase();
            const isAbortedRequest = !!params?.signal?.aborted ||
                detailText.includes("aborted") ||
                summaryText.includes("aborted");
            if (isAbortedRequest) {
                throw createAbortError();
            }
            throw new Error(`Failed to get active agents: ${result.summary || "Unknown error"} ${result.details || ""}`);
        }
        const response = result.data || { agents: [], totalCount: 0, hasMore: false };
        if (!params?.signal) {
            activeAgentsResponseCache.set(url, {
                value: cloneGetAgentsResponse(response),
                expiresAt: Date.now() + AGENT_COLLECTION_CACHE_TTL_MS,
            });
        }
        return response;
    })();
    if (!params?.signal) {
        activeAgentsInFlightRequests.set(url, requestPromise);
    }
    try {
        const response = await requestPromise;
        return cloneGetAgentsResponse(response);
    }
    finally {
        if (!params?.signal) {
            activeAgentsInFlightRequests.delete(url);
        }
    }
}
/**
 * Gets all active agents and closed agents grouped by profile for the current user
 */
export async function getAgentsGrouped(searchTerm, includeShared = true, includeOwned = true) {
    const queryParams = new URLSearchParams();
    if (searchTerm)
        queryParams.append("searchTerm", searchTerm);
    queryParams.append("includeShared", includeShared.toString());
    queryParams.append("includeOwned", includeOwned.toString());
    const queryString = queryParams.toString();
    const url = AGENT_BASE_URL +
        "/getAgentsGroupedByProfile" +
        (queryString ? `?${queryString}` : "");
    const cachedResponse = getFreshCachedValue(groupedAgentsResponseCache, url);
    if (cachedResponse) {
        return cloneGetAgentsGroupedResponse(cachedResponse);
    }
    const existingRequest = groupedAgentsInFlightRequests.get(url);
    if (existingRequest) {
        return cloneGetAgentsGroupedResponse(await existingRequest);
    }
    const requestPromise = (async () => {
        const result = await get(url);
        if (result.type !== "success") {
            throw new Error(`Failed to get grouped agents: ${result.summary || "Unknown error"} ${result.details || ""}`);
        }
        const response = result.data || { activeAgents: [], closedAgentsByProfile: [] };
        groupedAgentsResponseCache.set(url, {
            value: cloneGetAgentsGroupedResponse(response),
            expiresAt: Date.now() + AGENT_COLLECTION_CACHE_TTL_MS,
        });
        return response;
    })();
    groupedAgentsInFlightRequests.set(url, requestPromise);
    try {
        const response = await requestPromise;
        return cloneGetAgentsGroupedResponse(response);
    }
    finally {
        groupedAgentsInFlightRequests.delete(url);
    }
}
/**
 * Gets more closed agents for a specific profile
 */
export async function getClosedAgentsByProfile(profileId, skip, limit, searchTerm) {
    const queryParams = new URLSearchParams();
    queryParams.append("profileId", profileId);
    queryParams.append("skip", skip.toString());
    queryParams.append("limit", limit.toString());
    if (searchTerm)
        queryParams.append("searchTerm", searchTerm);
    const queryString = queryParams.toString();
    const url = AGENT_BASE_URL +
        "/getClosedAgentsByProfile" +
        (queryString ? `?${queryString}` : "");
    const result = await get(url);
    if (result.type !== "success") {
        throw new Error(`Failed to get closed agents by profile: ${result.summary || "Unknown error"} ${result.details || ""}`);
    }
    return result.data || { agents: [], totalCount: 0, hasMore: false };
}
/**
 * Gets all non-closed agents across all users (admin only)
 */
export async function getAllAgents(limit) {
    const params = new URLSearchParams();
    if (limit)
        params.append("limit", limit.toString());
    const queryString = params.toString();
    const url = AGENT_BASE_URL + "/getAllAgents" + (queryString ? `?${queryString}` : "");
    const result = await get(url);
    if (result.type !== "success") {
        throw new Error(`Failed to get all agents: ${result.summary || "Unknown error"} ${result.details || ""}`);
    }
    return result.data || [];
}
/**
 * Cancels a running agent execution
 */
export async function cancelAgent(agentId) {
    const result = await post(AGENT_BASE_URL + "/cancel", {
        agentId,
        source: "frontend.agentService.cancelAgent",
    });
    if (result.type !== "success") {
        throw new Error(`Failed to cancel agent: ${result.summary || "Unknown error"} ${result.details || ""}`);
    }
    invalidateAgentCollectionCaches();
    return result.data;
}
/**
 * Permanently deletes an agent and all its messages
 */
export async function deleteAgent(agentId) {
    const result = await post(AGENT_BASE_URL + "/deleteAgent", { agentId });
    if (result.type !== "success") {
        throw new Error(`Failed to delete agent: ${result.summary || "Unknown error"} ${result.details || ""}`);
    }
    invalidateAgentCollectionCaches();
    return result.data;
}
/**
 * Closes an agent by canceling execution and setting status to closed
 */
export async function closeAgent(agentId) {
    const result = await post(AGENT_BASE_URL + "/closeAgent", { agentId });
    if (result.type !== "success") {
        const summary = result.summary || "Unknown error";
        const details = result.details || "";
        const combined = `${summary} ${details}`.trim();
        // Sitecore can render 404 pages as "Document Not Found"; map it to a useful agent-specific message.
        if (/document\s+not\s+found/i.test(combined)) {
            throw new Error("Agent not found or no longer accessible");
        }
        throw new Error(combined);
    }
    invalidateAgentCollectionCaches();
    return result.data;
}
/**
 * Updates the selected model for an agent chat (persists to DB)
 */
// (Deprecated) updateAgentModel removed in favor of updateAgentSettings
/**
 * Updates agent settings like model name and mode in one call.
 */
export async function updateAgentSettings(agentId, settings) {
    const result = await post(AGENT_BASE_URL + "/updateSettings", {
        agentId,
        model: settings.model ?? undefined,
        mode: settings.mode ?? undefined,
        profileId: settings.profileId ?? undefined,
        profileName: settings.profileName ?? undefined,
    });
    if (result.type !== "success") {
        throw new Error(`Failed to update agent settings: ${result.summary || "Unknown error"} ${result.details || ""}`);
    }
    invalidateAgentCollectionCaches();
    return result.data ?? { success: true };
}
export async function getAgentMembers(agentId) {
    const result = await get(AGENT_BASE_URL + "/members?agentId=" + encodeURIComponent(agentId));
    if (result.type !== "success") {
        throw new Error(`Failed to load agent members: ${result.summary || "Unknown error"} ${result.details || ""}`);
    }
    return result.data ?? [];
}
export async function addAgentMember(agentId, principalType, identifier, accessLevel) {
    const result = await post(AGENT_BASE_URL + "/addMember", {
        agentId,
        memberType: principalType,
        memberIdentifier: identifier,
        accessLevel,
    });
    if (result.type !== "success") {
        throw new Error(`Failed to add agent member: ${result.summary || "Unknown error"} ${result.details || ""}`);
    }
    invalidateAgentCollectionCaches();
    return result.data;
}
export async function removeAgentMember(memberId) {
    const result = await post(AGENT_BASE_URL + "/removeMember", { memberId });
    if (result.type !== "success") {
        throw new Error(`Failed to remove agent member: ${result.summary || "Unknown error"} ${result.details || ""}`);
    }
    invalidateAgentCollectionCaches();
    return result.data ?? { success: true };
}
export async function searchAgentPrincipals(query, type = "all", limit = 20) {
    const params = new URLSearchParams({
        query,
        type,
        limit: String(limit),
    });
    const result = await get(AGENT_BASE_URL + "/searchPrincipals?" + params.toString());
    if (result.type !== "success") {
        throw new Error(`Failed to search principals: ${result.summary || "Unknown error"} ${result.details || ""}`);
    }
    return result.data ?? [];
}
/**
 * Updates the metadata (context) for an agent chat
 */
export async function updateAgentContext(agentId, metadata) {
    // Normalize and sanitize metadata to avoid duplicate/case-variant keys
    const clean = canonicalizeAgentMetadata(metadata);
    // Ensure no top-level context field is sent (only use additionalData.context)
    const { context: _drop, ...cleanNoTop } = clean;
    const result = await post(AGENT_BASE_URL + "/updateContext", { agentId, ...cleanNoTop });
    if (result.type !== "success") {
        throw new Error(`Failed to update agent metadata: ${result.summary || "Unknown error"} ${result.details || ""}`);
    }
    invalidateAgentCollectionCaches();
    return result.data ?? { success: true };
}
export async function persistDraftAgent(params) {
    const result = await post(AGENT_BASE_URL + "/persistDraft", {
        agentId: params.agentId,
        sessionId: params.sessionId ?? undefined,
        profileId: params.profileId,
        mode: params.mode ?? undefined,
        model: params.model ?? undefined,
        name: params.name ?? undefined,
        context: params.context
            ? canonicalizeAgentMetadata(params.context)
            : undefined,
    });
    if (result.type !== "success") {
        throw new Error(`Failed to persist draft agent: ${result.summary || "Unknown error"} ${result.details || ""}`);
    }
    if (!result.data) {
        throw new Error("Failed to persist draft agent: missing agent response");
    }
    invalidateAgentCollectionCaches();
    return result.data;
}
export async function assignAgentSkill(params) {
    const result = await post(AGENT_BASE_URL + "/assignSkill", params);
    if (result.type !== "success") {
        throw new Error(`Failed to assign skill: ${result.summary || "Unknown error"} ${result.details || ""}`);
    }
    return result.data ?? { success: true };
}
export async function revokeAgentSkill(params) {
    const result = await post(AGENT_BASE_URL + "/revokeSkill", params);
    if (result.type !== "success") {
        throw new Error(`Failed to revoke skill: ${result.summary || "Unknown error"} ${result.details || ""}`);
    }
    return result.data ?? { success: true };
}
export async function claimAgentBrowser(params) {
    const query = new URLSearchParams({
        agentId: params.agentId,
        sessionId: params.sessionId,
    });
    const result = await post(`${AGENT_BASE_URL}/claimBrowser?${query.toString()}`, params);
    if (result.type !== "success") {
        throw new Error(`Failed to attach browser: ${result.summary || "Unknown error"} ${result.details || ""}`);
    }
    return result.data ?? { success: true };
}
export async function releaseAgentBrowser(params) {
    const query = new URLSearchParams({
        agentId: params.agentId,
        sessionId: params.sessionId,
    });
    const result = await post(`${AGENT_BASE_URL}/releaseBrowser?${query.toString()}`, params);
    if (result.type !== "success") {
        throw new Error(`Failed to release browser: ${result.summary || "Unknown error"} ${result.details || ""}`);
    }
    return result.data ?? { success: true };
}
export async function cancelAgentDialog(params) {
    const result = await post(`${AGENT_BASE_URL}/submitDialogResponse`, {
        callbackId: params.callbackId,
        cancelled: true,
        error: params.error,
    }, params.sessionId);
    if (result.type !== "success") {
        throw new Error(`Failed to cancel dialog: ${result.summary || "Unknown error"} ${result.details || ""}`);
    }
    return result.data ?? { success: true };
}
export async function updateAgentCostLimit(agentId, action, amount) {
    const result = await post(AGENT_BASE_URL + "/updateCostLimit", { agentId, action, amount });
    if (result.type !== "success") {
        throw new Error(`Failed to update cost limit: ${result.summary || "Unknown error"} ${result.details || ""}`);
    }
    invalidateAgentCollectionCaches();
    return result.data ?? { success: true };
}
/**
 * Uploads a document to an agent
 * Server uses Pandoc for PDF text extraction
 */
export async function uploadDocument(agentId, file, profileId) {
    const formData = new FormData();
    formData.append("file", file);
    const url = profileId
        ? `/parhelia/agent/uploadDocument?agentId=${agentId}&profileId=${profileId}`
        : `/parhelia/agent/uploadDocument?agentId=${agentId}`;
    const response = await fetch(url, {
        method: "POST",
        credentials: "include",
        body: formData,
    });
    const data = await response.json();
    const success = Boolean(data?.success ?? data?.Success ?? false);
    const rawError = typeof data?.error === "string"
        ? data.error
        : typeof data?.Error === "string"
            ? data.Error
            : undefined;
    const rawDocument = data?.document ?? data?.Document;
    const normalized = {
        success,
        error: rawError,
    };
    // Normalize document data to ensure consistent property names
    if (success && rawDocument) {
        const doc = rawDocument;
        normalized.document = {
            id: doc.id ?? doc.Id,
            agentId: doc.agentId ?? doc.AgentId,
            fileName: doc.fileName ?? doc.FileName,
            fileSize: doc.fileSize ?? doc.FileSize ?? 0,
            contentType: doc.contentType ?? doc.ContentType,
            extractedText: doc.extractedText ?? doc.ExtractedText,
            uploadedBy: doc.uploadedBy ?? doc.UploadedBy,
            uploadedDate: doc.uploadedDate ?? doc.UploadedDate,
        };
        emitAgentDocumentUploaded({
            agentId,
            document: normalized.document,
        });
    }
    return normalized;
}
function normalizeAgentSkill(skill) {
    return {
        id: String(skill.id ?? ""),
        name: String(skill.name ?? ""),
        disabled: !!skill.disabled,
        description: skill.description ?? undefined,
        instructions: skill.instructions ?? undefined,
        allowedAgentProfiles: Array.isArray(skill.allowedAgentProfiles)
            ? skill.allowedAgentProfiles.map((p) => ({
                id: String(p.id ?? ""),
                name: String(p.name ?? ""),
            }))
            : [],
        additionalAllowedTools: Array.isArray(skill.additionalAllowedTools)
            ? skill.additionalAllowedTools
                .map((name) => String(name ?? "").trim())
                .filter((name) => !!name)
            : [],
    };
}
export async function getAgentSkillCatalog(includeDisabled = false) {
    const result = await get(AGENT_BASE_URL +
        "/skills?includeDisabled=" +
        encodeURIComponent(String(includeDisabled)));
    if (result.type !== "success") {
        throw new Error(`Failed to get agent skills: ${result.summary || "Unknown error"} ${result.details || ""}`);
    }
    const data = result.data;
    const skills = Array.isArray(data)
        ? data
        : Array.isArray(data?.skills)
            ? data?.skills
            : [];
    const rootIds = Array.isArray(data?.rootIds)
        ? data?.rootIds.map((id) => String(id ?? ""))
        : [];
    const selectableTemplateIds = Array.isArray(data?.selectableTemplateIds)
        ? data?.selectableTemplateIds.map((id) => String(id ?? ""))
        : [];
    return {
        skills: skills.map(normalizeAgentSkill),
        rootIds,
        selectableTemplateIds,
    };
}
export async function getAgentSkills(includeDisabled = false) {
    const catalog = await getAgentSkillCatalog(includeDisabled);
    return catalog.skills;
}
/**
 * Gets all documents for an agent
 */
export async function getAgentDocuments(agentId) {
    const result = await get(`/parhelia/agent/getDocuments?agentId=${agentId}`);
    if (result.type !== "success") {
        throw new Error(`Failed to get documents: ${result.summary || "Unknown error"} ${result.details || ""}`);
    }
    // Normalize document data to ensure consistent property names
    const normalizedDocuments = result.data?.documents?.map((doc) => ({
        id: doc.id,
        agentId: doc.agentId,
        fileName: doc.fileName,
        fileSize: doc.fileSize ?? 0,
        contentType: doc.contentType,
        extractedText: doc.extractedText,
        uploadedBy: doc.uploadedBy,
        uploadedDate: doc.uploadedDate,
    }));
    return {
        success: result.data?.success ?? false,
        documents: normalizedDocuments,
        error: result.data?.error,
    };
}
/**
 * Deletes a document
 */
export async function deleteDocument(documentId) {
    const response = await fetch(`/parhelia/agent/deleteDocument?documentId=${documentId}`, {
        method: "DELETE",
        credentials: "include",
        headers: {
            "Content-Type": "application/json",
        },
    });
    const data = await response.json();
    return data;
}
/**
 * Downloads a document file
 */
export async function downloadDocument(documentId) {
    const response = await fetch(`/parhelia/agent/downloadDocument?documentId=${documentId}`, {
        method: "GET",
        credentials: "include",
    });
    if (!response.ok) {
        throw new Error(`Failed to download document: ${response.statusText}`);
    }
    return await response.blob();
}
/**
 * Gets pending queued prompts for an agent
 */
export async function getPendingPrompts(agentId) {
    const result = await get(AGENT_BASE_URL + "/getPendingPrompts?agentId=" + agentId);
    if (result.type !== "success") {
        throw new Error(`Failed to get pending prompts: ${result.summary || "Unknown error"} ${result.details || ""}`);
    }
    return result.data || [];
}
/**
 * Gets trigger subscriptions for an agent
 */
export async function getAgentTriggerSubscriptions(agentId) {
    const result = await get(AGENT_BASE_URL + "/getTriggerSubscriptions?agentId=" + agentId);
    if (result.type !== "success") {
        throw new Error(`Failed to get trigger subscriptions: ${result.summary || "Unknown error"} ${result.details || ""}`);
    }
    const raw = (result.data || []);
    return raw
        .map((sub) => ({
        id: String(sub?.id ?? ""),
        agentId: String(sub?.agentId ?? ""),
        triggerName: String(sub?.triggerName ?? ""),
        filter: (sub?.filter ?? null),
        isActive: Boolean(sub?.isActive ?? false),
        createdAtUtc: String(sub?.createdAtUtc ?? ""),
    }))
        .filter((sub) => sub.id && sub.triggerName);
}
function normalizeAgentSitecoreAllowance(row) {
    return {
        itemId: String(row?.itemId ?? ""),
        itemPath: String(row?.itemPath ?? ""),
        operationType: String(row?.operationType ?? "*"),
        scopeType: String(row?.scopeType ?? "itemSubtree"),
        source: (row?.source ?? null),
        grantedBy: (row?.grantedBy ?? null),
        grantedAt: (row?.grantedAt ?? null),
    };
}
function normalizeAgentFilesystemAllowance(row) {
    return {
        normalizedPath: String(row?.normalizedPath ?? ""),
        operationType: String(row?.operationType ?? "*"),
        source: (row?.source ?? null),
        grantedBy: (row?.grantedBy ?? null),
        grantedAt: (row?.grantedAt ?? null),
    };
}
export async function getAgentOperationAllowances(agentId) {
    const result = await get(AGENT_BASE_URL + "/getOperationAllowances?agentId=" + agentId);
    if (result.type !== "success") {
        throw new Error(`Failed to get operation allowances: ${result.summary || "Unknown error"} ${result.details || ""}`);
    }
    const raw = result.data || {};
    const rawSitecore = Array.isArray(raw?.sitecore)
        ? raw?.sitecore
        : [];
    const rawFilesystem = Array.isArray(raw?.filesystem)
        ? raw?.filesystem
        : [];
    return {
        sitecore: rawSitecore
            .map(normalizeAgentSitecoreAllowance)
            .filter((row) => row.itemId && row.itemPath),
        filesystem: rawFilesystem
            .map(normalizeAgentFilesystemAllowance)
            .filter((row) => row.normalizedPath),
    };
}
// Canonicalize metadata to a stable, collision-free shape for both client use and POST payloads
export function canonicalizeAgentMetadata(meta) {
    const m = { ...(meta || {}) };
    // Explicitly drop deprecated cost limit fields from metadata to avoid confusion
    if (Object.prototype.hasOwnProperty.call(m, "costLimit")) {
        delete m.costLimit;
    }
    if (Object.prototype.hasOwnProperty.call(m, "initialCostLimit")) {
        delete m.initialCostLimit;
    }
    // Handle legacy context nested structure - lift to top level
    const contextSources = [];
    if (m.context && typeof m.context === "object") {
        contextSources.push(m.context);
        delete m.context;
    }
    // Merge additionalData context entries
    const additionalDataSources = [];
    if (m.additionalData && typeof m.additionalData === "object") {
        additionalDataSources.push(m.additionalData);
    }
    for (const src of additionalDataSources) {
        for (const key of Object.keys(src)) {
            if (key.toLowerCase() === "context" && src[key]) {
                contextSources.push(src[key]);
            }
        }
    }
    // Process items
    const allPages = [];
    if (Array.isArray(m.items))
        allPages.push(...m.items);
    for (const ctx of contextSources) {
        if (Array.isArray(ctx.items))
            allPages.push(...ctx.items);
    }
    if (allPages.length > 0) {
        const dedup = [];
        const seen = new Set();
        for (const p of allPages) {
            const id = p?.id;
            if (!id)
                continue;
            const lang = (p?.language ?? "").toString();
            const ver = (p?.version ?? "").toString();
            const key = `${String(id)}-${lang}-${ver}`.toLowerCase();
            if (seen.has(key))
                continue;
            seen.add(key);
            dedup.push({
                id: String(id),
                language: p?.language,
                version: p?.version,
                name: p?.name,
                path: p?.path,
            });
        }
        m.items = dedup;
    }
    else {
        delete m.items;
    }
    // Process components with page info
    const allComponents = [];
    if (Array.isArray(m.components))
        allComponents.push(...m.components);
    for (const ctx of contextSources) {
        if (Array.isArray(ctx.components))
            allComponents.push(...ctx.components);
    }
    if (allComponents.length > 0) {
        const dedup = [];
        const seen = new Set();
        for (const c of allComponents) {
            if (!c)
                continue;
            const componentId = c.componentId;
            if (!componentId || typeof componentId !== "string")
                continue;
            const key = componentId.toLowerCase();
            if (seen.has(key))
                continue;
            seen.add(key);
            const pageItem = c.pageItem;
            dedup.push({
                componentId: String(componentId),
                componentName: c.componentName,
                componentType: c.componentType,
                renderingItemId: c.renderingItemId,
                createdByAgent: c.createdByAgent,
                pageItem: pageItem
                    ? {
                        id: String(pageItem.id ?? ""),
                        language: pageItem.language,
                        version: pageItem.version,
                        name: pageItem.name,
                        path: pageItem.path,
                    }
                    : undefined,
            });
        }
        m.components = dedup;
    }
    // Process field - merge/complete from context sources if needed
    for (const ctx of contextSources) {
        if (ctx.field) {
            // If field doesn't exist, create it from context
            if (!m.field) {
                m.field = {
                    fieldId: ctx.field.fieldId,
                    fieldName: ctx.field.fieldName,
                    fieldType: ctx.field.fieldType,
                    item: ctx.field.item,
                };
                break;
            }
            // If field exists but is incomplete, fill in missing properties
            if (m.field && !m.field.item && ctx.field.item) {
                m.field.item = ctx.field.item;
            }
            if (m.field && !m.field.fieldName && ctx.field.fieldName) {
                m.field.fieldName = ctx.field.fieldName;
            }
            if (m.field && !m.field.fieldType && ctx.field.fieldType) {
                m.field.fieldType = ctx.field.fieldType;
            }
        }
    }
    // Process comment
    if (!m.comment) {
        for (const ctx of contextSources) {
            if (ctx.comment) {
                m.comment = ctx.comment;
                break;
            }
        }
    }
    // Merge extension-style additional data (excluding context which we've lifted).
    // The backend uses JsonExtensionData, so these values must be emitted as
    // top-level properties rather than nested under "additionalData".
    const additional = {};
    for (const src of additionalDataSources) {
        for (const k of Object.keys(src)) {
            if (k.toLowerCase() !== "context") {
                if (additional[k] === undefined)
                    additional[k] = src[k];
            }
        }
    }
    delete m.additionalData;
    delete m.AdditionalData;
    for (const [key, value] of Object.entries(additional)) {
        if (m[key] === undefined) {
            m[key] = value;
        }
    }
    return m;
}
//# sourceMappingURL=agentService.js.map