"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.MablApiClient = void 0;
const ApiError_1 = require("./ApiError");
const env_1 = require("../env/env");
const axios_1 = __importDefault(require("axios"));
const mablApi_1 = require("../mablApi");
const agentNames_1 = require("../observers/agentNames");
const cliConfigProvider_1 = require("../providers/cliConfigProvider");
const basicApiClient_1 = require("./basicApiClient");
const query_string_1 = __importDefault(require("query-string"));
const featureSet_1 = require("./featureSet");
class MablApiClient extends basicApiClient_1.BasicApiClient {
    constructor(options) {
        super(options);
        this.baseApiUrl =
            options.apiUrl ?? process.env.MABL_API_URL ?? env_1.BASE_API_URL;
        this.baseApiAgentUrl = this.baseApiUrl;
    }
    async getPlan(planId) {
        try {
            return await this.makeGetRequest(`${this.baseApiUrl}/schedule/runPolicy/${planId}`);
        }
        catch (error) {
            throw toApiError(`Failed to get plan (${planId})`, error);
        }
    }
    async getPlans(options) {
        try {
            const queryArg = query_string_1.default.stringify(options);
            const plans = await this.makeGetRequest(`${this.baseApiUrl}/schedule/runPolicy/?${queryArg}`);
            sortTemporallyAscending(plans.run_policies ?? []);
            return plans.run_policies ?? [];
        }
        catch (error) {
            throw toApiError(`Failed to get plans (workspace: ${options.organization_id})`, error);
        }
    }
    async getApplication(applicationId) {
        try {
            return await this.makeGetRequest(`${this.baseApiUrl}/v1/applications/${applicationId}`);
        }
        catch (error) {
            throw toApiError(`Failed to get application (${applicationId})`, error);
        }
    }
    async getApplications(workspaceId, limit) {
        try {
            const applicationQueryString = query_string_1.default.stringify({
                organization_id: workspaceId,
                limit,
            });
            const applications = await this.makeGetRequest(`${this.baseApiUrl}/applications?${applicationQueryString}`).then((result) => result.applications ?? []);
            sortTemporallyAscending(applications);
            return applications;
        }
        catch (error) {
            throw toApiError(`Failed to get applications`, error);
        }
    }
    async getEnvironment(environmentId, decryptVariables) {
        try {
            const queryStringArgs = {
                decrypt: decryptVariables,
            };
            const envQueryString = query_string_1.default.stringify(queryStringArgs);
            return await this.makeGetRequest(`${this.baseApiUrl}/v1/environments/${environmentId}?${envQueryString}`);
        }
        catch (error) {
            throw toApiError(`Failed to get environment (${environmentId})`, error);
        }
    }
    async deleteEnvironment(id) {
        try {
            return await this.makeDeleteRequest(`${this.baseApiUrl}/environments/${id}`);
        }
        catch (error) {
            throw toApiError(`Failed to delete environment`, error);
        }
    }
    async createEnvironment(environment) {
        try {
            return await this.makePostRequest(`${this.baseApiUrl}/environments`, environment);
        }
        catch (error) {
            throw toApiError(`Failed to create environment`, error);
        }
    }
    async updateEnvironment(id, environment) {
        try {
            return await this.makePatchRequest(`${this.baseApiUrl}/environments/${id}`, environment);
        }
        catch (error) {
            throw toApiError(`Failed to update environment`, error);
        }
    }
    async getAgentInstruction(instructionId) {
        try {
            return await this.makeGetRequest(`${this.baseApiUrl}/agentInstruction/${instructionId}`);
        }
        catch (error) {
            throw toApiError(`Failed to get agent instruction (${instructionId})`, error);
        }
    }
    async getAgentInstructions(workspaceId, limit) {
        try {
            const qs = query_string_1.default.stringify({
                workspace_id: workspaceId,
                limit,
            });
            return await this.makeGetRequest(`${this.baseApiUrl}/agentInstruction?${qs}`).then((result) => result.agent_instructions ?? []);
        }
        catch (error) {
            throw toApiError(`Failed to get agent instructions`, error);
        }
    }
    async createAgentInstruction(request) {
        try {
            return await this.makePostRequest(`${this.baseApiUrl}/agentInstruction`, request);
        }
        catch (error) {
            throw toApiError(`Failed to create agent instruction`, error);
        }
    }
    async updateAgentInstruction(instructionId, update) {
        try {
            return await this.makePatchRequest(`${this.baseApiUrl}/agentInstruction/${instructionId}`, update);
        }
        catch (error) {
            throw toApiError(`Failed to update agent instruction`, error);
        }
    }
    async deleteAgentInstruction(instructionId) {
        try {
            return await this.makeDeleteRequest(`${this.baseApiUrl}/agentInstruction/${instructionId}`);
        }
        catch (error) {
            throw toApiError(`Failed to delete agent instruction`, error);
        }
    }
    async generateTestPlan({ workspaceId, messages, artifact, generationReferences, trainingSessionId, }) {
        try {
            const requestBody = {
                messages,
                artifact,
                generation_references: generationReferences,
                session_id: trainingSessionId,
                training_session_id: trainingSessionId,
            };
            return await this.makePostRequest(`${this.baseApiUrl}/agent/testCreation/plan?workspaceId=${workspaceId}`, requestBody);
        }
        catch (error) {
            throw toApiError(`Failed to generate test pre plan`, error);
        }
    }
    async getEnvironments(workspaceId, limit) {
        try {
            const environmentQueryString = query_string_1.default.stringify({
                organization_id: workspaceId,
                limit,
            });
            const environments = await this.makeGetRequest(`${this.baseApiUrl}/v1/environments/?${environmentQueryString}`).then((result) => result.environments ?? []);
            sortTemporallyAscending(environments);
            return environments;
        }
        catch (error) {
            throw toApiError(`Failed to get environments`, error);
        }
    }
    async createDeployment(deployment) {
        try {
            return await this.makePostRequest(`${this.baseApiUrl}/deployments`, deployment);
        }
        catch (error) {
            throw toApiError(`Failed to create deployment`, error);
        }
    }
    async getTestRunsByPlanRunId(planRunId) {
        try {
            return await this.makeGetRequest(`${this.baseApiUrl}/journeyRuns/planRun/${planRunId}`);
        }
        catch (error) {
            throw toApiError(`Failed to get test runs by plan run id`, error);
        }
    }
    async getExternalTcmBindingById(testId) {
        try {
            return await this.makeGetRequest(`${this.baseApiUrl}/tcm/external/bindings/xray/test/${testId}`);
        }
        catch (error) {
            throw toApiError(`Failed to query external tcm`, error);
        }
    }
    async createExternalTcmBinding(requestBody) {
        try {
            return await this.makePostRequest(`${this.baseApiUrl}/tcm/external/bindings`, requestBody);
        }
        catch (error) {
            throw toApiError(`Failed to create external tcm binding`, error);
        }
    }
    async deleteExternalTcmBinding(externalTcmPlatform, mablEntityType, mablEntityId) {
        try {
            return await this.makeDeleteRequest(`${this.baseApiUrl}/tcm/external/bindings/${externalTcmPlatform}/${mablEntityType}/${mablEntityId}`);
        }
        catch (error) {
            throw toApiError(`Failed to delete external tcm binding`, error);
        }
    }
    async createTestCase(requestBody) {
        try {
            return await this.makePostRequest(`${this.baseApiUrl}/testCases`, requestBody);
        }
        catch (error) {
            throw toApiError(`Failed to create test case`, error);
        }
    }
    async associateTestCaseWithTest(testId, testCaseId) {
        try {
            return await this.makePostRequest(`${this.baseApiUrl}/testCases/${testCaseId}/binding/${testId}`);
        }
        catch (error) {
            throw toApiError(`Failed to associate test case with test`, error);
        }
    }
    async editTestMetadata(testId, requestBody) {
        try {
            return await this.makePatchRequest(`${this.baseApiUrl}/test/journey/${testId}/metadata`, requestBody);
        }
        catch (error) {
            throw toApiError(`Failed to edit test`, error);
        }
    }
    async queryTests(workspaceId, query, limit, applicationId) {
        try {
            return await this.makePostRequest(`${this.baseApiUrl}/test/references/chunk?${query_string_1.default.stringify({
                workspace_id: workspaceId,
            })}`, {
                task_description: query,
                application_id: applicationId,
                limit,
            });
        }
        catch (error) {
            throw toApiError(`Failed to query tests`, error);
        }
    }
    async updateDeployment(id, deployment) {
        try {
            return await this.makePatchRequest(`${this.baseApiUrl}/deployments/${id}`, deployment);
        }
        catch (error) {
            throw toApiError(`Failed to update environment`, error);
        }
    }
    async analyzeTestRun(workspaceId, request) {
        try {
            return await this.makePostRequestWithRetries(`${this.baseApiUrl}/analysis/${workspaceId}/run/summary`, request);
        }
        catch (error) {
            throw toApiError('Failed to analyze test run failure', error);
        }
    }
    async getTestRunFailureAnalysis(workspaceId, testRunId) {
        try {
            return await this.makeGetRequest(`${this.baseApiUrl}/analysis/${workspaceId}/testRun/${testRunId}/summary`);
        }
        catch (error) {
            throw toApiError('Failed to analyze test run failure', error);
        }
    }
    async getPlanRunFailureAnalysis(workspaceId, planRunId) {
        try {
            return await this.makeGetRequest(`${this.baseApiUrl}/analysis/${workspaceId}/planRun/${planRunId}/summary`);
        }
        catch (error) {
            throw toApiError('Failed to analyze plan run failure', error);
        }
    }
    async analyzePlanRun(workspaceId, request) {
        try {
            return await this.makePostRequestWithRetries(`${this.baseApiUrl}/analysis/${workspaceId}/planRun/summary`, request);
        }
        catch (error) {
            throw toApiError('Failed to analyze plan run failure', error);
        }
    }
    async selectLinkServers(workspaceId, labels) {
        try {
            const queryParams = query_string_1.default.stringify({
                workspace_id: workspaceId,
                labels,
            }, { arrayFormat: 'comma' });
            return (await this.makeGetRequest(`${this.baseApiUrl}/link/servers/select-multiple?${queryParams}`)).link_servers;
        }
        catch (error) {
            throw toApiError(`Failed to get selected link server`, error);
        }
    }
    async deleteLinkLabel(workspaceId, linkLabel) {
        try {
            return await this.makeDeleteRequest(`${this.baseApiUrl}/link/${workspaceId}/label/${linkLabel}`);
        }
        catch (error) {
            throw toApiError(`Failed to delete link label`, error);
        }
    }
    async getLinkAgentsWithRecentHeartbeats(workspaceId, limit, maxHeartbeatAgeSeconds) {
        try {
            return ((await this.makeGetRequest(`${env_1.BASE_API_URL}/link/agents?workspace_id=${workspaceId}&limit=${limit}&max_heartbeat_age_sec=${maxHeartbeatAgeSeconds}`)).link_agents ?? []);
        }
        catch (error) {
            throw toApiError(`Failed to get active link agents`, error);
        }
    }
    async terminateLinkAgent(id) {
        try {
            await this.makePostRequest(`${env_1.BASE_API_URL}/link/agents/${id}/terminate`);
        }
        catch (error) {
            throw toApiError(`Failed to terminate link agent`, error);
        }
    }
    async getExportRequest(id) {
        return this.getEntity(id, 'exports', 'ExportRequest');
    }
    async getEntity(id, path, entityName = 'Entity') {
        try {
            return await this.makeGetRequest(`${this.baseApiUrl}/v1/${path}/${id}`);
        }
        catch (error) {
            throw toApiError(`Failed to get ${entityName} (${id})`, error);
        }
    }
    async getCredentials(workspaceId, limit) {
        try {
            const credentialsQueryString = query_string_1.default.stringify({
                organization_id: workspaceId,
                limit,
            });
            return await this.makeGetRequest(`${this.baseApiUrl}/credentials?${credentialsQueryString}`).then((result) => result.credentials ?? []);
        }
        catch (error) {
            throw toApiError(`Failed to get credentials`, error);
        }
    }
    async queryIntegrations(workspaceId, integrationType) {
        try {
            return await this.makeGetRequest(`${this.baseApiUrl}/workspaces/${workspaceId}/integrations?${query_string_1.default.stringify({
                integration_type: integrationType,
            })}`);
        }
        catch (error) {
            throw toApiError(`Failed to get integrations`, error);
        }
    }
    async queryXrayTests(xrayProjectId, search, limit, cursor) {
        try {
            return await this.makeGetRequest(`${this.baseApiUrl}/integrations/${xrayProjectId}/xray/tests?${query_string_1.default.stringify({
                search,
                limit,
                cursor,
            })}`);
        }
        catch (error) {
            throw toApiError(`Failed to get xray test cases`, error);
        }
    }
    async getDatabaseConnections(workspaceId, limit) {
        try {
            const query = query_string_1.default.stringify({
                organization_id: workspaceId,
                limit,
            });
            return await this.makeGetRequest(`${this.baseApiUrl}/database/connections?${query}`).then((result) => result.database_connections ?? []);
        }
        catch (error) {
            throw toApiError(`Failed to get database connections`, error);
        }
    }
    async getCredential(credentialId, withSecrets, withComputedTotpCount) {
        const queryStringParams = query_string_1.default.stringify({
            with_secrets: withSecrets,
            with_computed_totp_count: withComputedTotpCount,
        });
        try {
            return await this.makeGetRequest(`${this.baseApiUrl}/credentials/${credentialId}?${queryStringParams}`);
        }
        catch (error) {
            throw toApiError(`Failed to get credential`, error);
        }
    }
    async getDeploymentEvents(workspaceId, limit) {
        try {
            const deploymentQueryString = query_string_1.default.stringify({
                workspace_id: workspaceId,
                limit,
            });
            return await this.makeGetRequest(`${this.baseApiUrl}/events/deployment?${deploymentQueryString}`).then((result) => result.deployments ?? []);
        }
        catch (error) {
            throw toApiError(`Failed to get deployment events`, error);
        }
    }
    async getDeploymentEventsByRevision(workspaceId, revision) {
        try {
            const deploymentQueryString = query_string_1.default.stringify({
                workspace_id: workspaceId,
                revision,
            });
            return await this.makeGetRequest(`${this.baseApiUrl}/events/deployment/revision/?${deploymentQueryString}`).then((result) => result.deployments ?? []);
        }
        catch (error) {
            throw toApiError(`Failed to get deployment events`, error);
        }
    }
    async getDeploymentEvent(deploymentId) {
        try {
            return await this.makeGetRequest(`${this.baseApiUrl}/events/deployment/${deploymentId}`);
        }
        catch (error) {
            throw toApiError(`Failed to get deployment event`, error);
        }
    }
    async getDeploymentEntity(deploymentId) {
        try {
            return await this.makeGetRequest(`${this.baseApiUrl}/deployments/${deploymentId}`);
        }
        catch (error) {
            throw toApiError(`Failed to get deployment entity`, error);
        }
    }
    async queryDeploymentEntities(workspaceId, environmentId, applicationId, limit = 50) {
        try {
            const queryStringParams = query_string_1.default.stringify({
                organization_id: workspaceId,
                environment_id: environmentId,
                application_id: applicationId,
                limit,
            });
            const query = `${this.baseApiUrl}/deployments?${queryStringParams}`;
            return await this.makeGetRequest(query);
        }
        catch (error) {
            throw toApiError(`Failed to query url entities`, error);
        }
    }
    async getDeploymentResults(deploymentEventId) {
        try {
            return await this.makeGetRequest(`${this.baseApiUrl}/execution/result/event/${deploymentEventId}`);
        }
        catch (error) {
            throw toApiError(`Failed to get deployment results`, error);
        }
    }
    async evaluateFindAttributes(workspaceId, evaluateAttributes) {
        try {
            return await this.makePostRequest(`${this.baseApiUrl}/find/${workspaceId}/evaluate/attributes`, evaluateAttributes);
        }
        catch (error) {
            return undefined;
        }
    }
    async evaluateFindCandidatesText(workspaceId, request) {
        try {
            return await this.makePostRequest(`${this.baseApiUrl}/find/${workspaceId}/evaluate/textSimilarity`, request);
        }
        catch (error) {
            return undefined;
        }
    }
    async getTestFindSummaries(testId, environmentId) {
        try {
            return await this.makeGetRequest(`${this.baseApiUrl}/findSummary?journey_id=${testId}&environment_id=${environmentId}`).then((result) => result.findsummaries ?? []);
        }
        catch (error) {
            throw toApiError(`Failed to get test find summaries results`, error);
        }
    }
    async getTestFindModels(testId, environmentId) {
        try {
            return await this.makeGetRequest(`${this.baseApiUrl}/findModel/test/${testId}?environment_id=${environmentId}`).then((result) => result.findModels ?? []);
        }
        catch (error) {
            throw toApiError(`Failed to get test find model results`, error);
        }
    }
    async getTestOverrides(testId, environmentId, selectorOverrideLimit = 10) {
        try {
            return await this.makeGetRequest(`${this.baseApiUrl}/tests/testScripts/${testId}/overrides?environment_id=${environmentId}&selector_override_limit=${selectorOverrideLimit}`).then((result) => result.overrides ?? []);
        }
        catch (error) {
            throw toApiError(`Failed to get selector overrides`, error);
        }
    }
    async getTestRun(testRunId) {
        try {
            return await this.makeGetRequest(`${this.baseApiUrl}/journeyRuns/${testRunId}`);
        }
        catch (error) {
            throw toApiError(`Failed to get test run info`, error);
        }
    }
    async getPlanRun(planRunId) {
        try {
            return await this.makeGetRequest(`${this.baseApiUrl}/planRuns/${planRunId}`);
        }
        catch (error) {
            throw toApiError(`Failed to get plan run info`, error);
        }
    }
    async getPlanRunsByDeploymentEventId(deploymentEventId) {
        try {
            return await this.makeGetRequest(`${this.baseApiUrl}/planRuns/deployment/${deploymentEventId}`);
        }
        catch (error) {
            throw toApiError(`Failed to get plan run info`, error);
        }
    }
    async getWorkspaces(limit) {
        try {
            const userInfo = await this.getSelf();
            const requests = userInfo.roles
                ?.slice(0, limit)
                .flatMap((role) => role.organization_id
                ? [this.getWorkspace(role.organization_id)]
                : []) ?? [];
            const workspaces = await Promise.all(requests);
            sortTemporallyAscending(workspaces);
            return workspaces;
        }
        catch (error) {
            throw toApiError(`Failed to get workspaces`, error);
        }
    }
    async getWorkspace(workspaceId) {
        try {
            return await this.makeGetRequest(`${this.baseApiUrl}/organizations/${workspaceId}`);
        }
        catch (error) {
            throw toApiError(`Failed to get workspace`, error);
        }
    }
    async getAccount(accountId) {
        try {
            return await this.makeGetRequest(`${this.baseApiUrl}/accounts/${accountId}`);
        }
        catch (error) {
            throw toApiError(`Failed to get account`, error);
        }
    }
    async getAccountByWorkspaceId(workspaceId) {
        try {
            return await this.makeGetRequest(`${this.baseApiUrl}/organizations/${workspaceId}/account`);
        }
        catch (error) {
            throw toApiError(`Failed to get account from workspace id`, error);
        }
    }
    async getApiKeyDetails() {
        try {
            return await this.makeGetRequest(`${this.baseApiUrl}/apiKeys/self`);
        }
        catch (error) {
            throw toApiError(`Failed to validate API Key`, error);
        }
    }
    async getSelf() {
        try {
            const selfInfo = await this.makeGetRequest(`${this.baseApiUrl}/self`);
            if (selfInfo.preferences?.default_workspace_id &&
                !(await cliConfigProvider_1.CliConfigProvider.getWorkspace())) {
                const workspace = await this.getWorkspace(selfInfo.preferences.default_workspace_id);
                await cliConfigProvider_1.CliConfigProvider.setWorkspace(workspace);
            }
            else if (selfInfo.roles?.length === 1 &&
                selfInfo.roles[0].organization_id) {
                const workspace = await this.getWorkspace(selfInfo.roles[0].organization_id);
                await cliConfigProvider_1.CliConfigProvider.setWorkspace(workspace);
            }
            return selfInfo;
        }
        catch (error) {
            throw toApiError(`Failed to validate user`, error);
        }
    }
    async getJourney(journeyId, branchName = 'none', forExportFormat = 'none') {
        try {
            const queryStringArgs = {
                cliExport: forExportFormat,
                sourceControlTag: branchName,
            };
            const journeyQueryString = query_string_1.default.stringify(queryStringArgs);
            return await this.makeGetRequest(`${this.baseApiUrl}/test/journey/${journeyId}?${journeyQueryString}`);
        }
        catch (error) {
            throw toApiError(`Failed to get Test [${journeyId}]`, error);
        }
    }
    async getJourneys(options) {
        try {
            const queryArg = query_string_1.default.stringify(options);
            const journeys = (await this.makeGetRequest(`${this.baseApiUrl}/test/journeys?${queryArg}`)).journeys ?? [];
            sortTemporallyAscending(journeys);
            return journeys;
        }
        catch (error) {
            throw toApiError(`Failed to get Tests`, error);
        }
    }
    async getFlow(flowId, branchName) {
        try {
            const queryStringArgs = {
                sourceControlTag: branchName,
            };
            const flowQueryString = query_string_1.default.stringify(queryStringArgs);
            return await this.makeGetRequest(`${this.baseApiUrl}/flows/${flowId}?${flowQueryString}`);
        }
        catch (error) {
            throw toApiError(`Failed to get Flow [${flowId}]`, error);
        }
    }
    async getFlowReferences(flowId, branchName) {
        try {
            const queryStringArgs = {
                sourceControlTag: branchName,
                include_flows: true,
            };
            const qs = query_string_1.default.stringify(queryStringArgs);
            const result = await this.makeGetRequest(`${this.baseApiUrl}/flows/${flowId}/flowReferences?${qs}`);
            return (result.references
                ?.map((ref) => ref.flow)
                .filter((flow) => !!flow) ?? []);
        }
        catch (error) {
            throw toApiError(`Failed to get flow references for Flow [${flowId}]`, error);
        }
    }
    async getBatchNestedFlowReferences(flowIds, branchName) {
        try {
            const qs = query_string_1.default.stringify({
                flow_ids: flowIds.join(','),
                source_control_tag: branchName,
                include_flows: true,
            });
            const result = await this.makeGetRequest(`${this.baseApiUrl}/flows/flowReferences?${qs}`);
            return (result.references
                ?.map((ref) => ref.flow)
                .filter((flow) => !!flow) ?? []);
        }
        catch (error) {
            throw toApiError(`Failed to get batch nested flow references`, error);
        }
    }
    async getFlows(options) {
        try {
            const queryArg = query_string_1.default.stringify(options);
            const flows = (await this.makeGetRequest(`${this.baseApiUrl}/flows?${queryArg}`)).flows ?? [];
            sortTemporallyAscending(flows);
            return flows;
        }
        catch (error) {
            throw toApiError(`Failed to get Flows`, error);
        }
    }
    async getSnippet(snippetId, isQuery, preferLatestIfReusable, workspaceId) {
        const entity = isQuery ? 'query' : 'snippet';
        try {
            const queryParameter = typeof preferLatestIfReusable === 'boolean'
                ? `?preferLatestIfReusable=${preferLatestIfReusable}`
                : '';
            return await this.makeGetRequest(`${this.baseApiUrl}/snippets/${snippetId}${queryParameter}`);
        }
        catch (error) {
            throw toApiError(`Failed to get ${entity} [${snippetId}]. ${workspaceId
                ? `The ${entity} was likely deleted. To recover this ${entity}, visit the activity feed [workspaces/${workspaceId}/settings/activity-log?activityLogEntity=${entity}&activityLogEvent=delete]`
                : `The ${entity} was likely deleted. To recover this ${entity}, visit the activity feed.`}`, error);
        }
    }
    async getBranchById(branchId) {
        try {
            return await this.makeGetRequest(`${this.baseApiUrl}/branch/${branchId}`);
        }
        catch (error) {
            throw toApiError(`Failed to get Branch [${branchId}] by id`, error);
        }
    }
    async getBranchByName(workspaceId, branchName) {
        try {
            return await this.makeGetRequest(`${this.baseApiUrl}/branch/${workspaceId}/${branchName}`);
        }
        catch (error) {
            throw toApiError(`Failed to get Branch [${branchName}] by name`, error);
        }
    }
    async getBranches(workspaceId, limit, statusFilter) {
        try {
            const branchQueryString = query_string_1.default.stringify({
                workspace_id: workspaceId,
                limit,
                status: statusFilter,
            });
            return await this.makeGetRequest(`${this.baseApiUrl}/branch?${branchQueryString}`).then((result) => result.branches ?? []);
        }
        catch (error) {
            throw toApiError(`Failed to get Branches`, error);
        }
    }
    async deleteBranch(branchId) {
        try {
            return await this.makeDeleteRequest(`${this.baseApiUrl}/branch/${branchId}`);
        }
        catch (error) {
            throw toApiError(`Failed to delete Branch [${branchId}]`, error);
        }
    }
    async getArtifactUrl(artifactPath) {
        try {
            return await this.makeGetRequest(`${this.baseApiUrl}/artifact/url?path=${encodeURIComponent(artifactPath)}`);
        }
        catch (error) {
            throw toApiError('Failed to get artifact URL', error);
        }
    }
    async getFileUploadUrl(fileId) {
        try {
            return await this.makeGetRequest(`${this.baseApiUrl}/files/fileUpload/url/${fileId}`);
        }
        catch (error) {
            throw toApiError(`Failed to get File Upload URL`, error);
        }
    }
    async queryDataTables(workspaceId, limit, cursor) {
        try {
            const dataTablesQueryString = query_string_1.default.stringify({
                workspace_id: workspaceId,
                limit,
                cursor,
            });
            return await this.makeGetRequest(`${this.baseApiUrl}/dataTables?${dataTablesQueryString}`).then((result) => result);
        }
        catch (error) {
            throw toApiError(`Failed to retrieve DataTables`, error);
        }
    }
    async getDataTable(dataTableId) {
        try {
            return await this.makeGetRequest(`${this.baseApiUrl}/dataTables/${dataTableId}`);
        }
        catch (error) {
            throw toApiError(`Failed to get DataTable`, error);
        }
    }
    async createDataTable(dataTableCreateRequest) {
        try {
            return await this.makePostRequest(`${this.baseApiUrl}/dataTables`, dataTableCreateRequest);
        }
        catch (error) {
            throw toApiError(`Failed to create DataTable`, error);
        }
    }
    async queryScenarios(dataTableId, limit, cursor) {
        try {
            const scenariosQueryString = query_string_1.default.stringify({
                data_table_id: dataTableId,
                limit,
                cursor,
            });
            return await this.makeGetRequest(`${this.baseApiUrl}/dataTables/scenarios?${scenariosQueryString}`);
        }
        catch (error) {
            throw toApiError(`Failed to get Scenarios`, error);
        }
    }
    async getScenario(scenarioId) {
        try {
            return await this.makeGetRequest(`${this.baseApiUrl}/dataTables/scenarios/${scenarioId}`);
        }
        catch (error) {
            throw toApiError(`Failed to get Scenario`, error);
        }
    }
    async putScenario(scenarioId, scenario) {
        try {
            return await this.makePutRequest(`${this.baseApiUrl}/dataTables/scenarios/${scenarioId}`, scenario);
        }
        catch (error) {
            throw toApiError(`Failed to update Scenario`, error);
        }
    }
    async createScenario(dataTableId, scenario) {
        try {
            return await this.makePostRequest(`${this.baseApiUrl}/dataTables/${dataTableId}/scenarios`, scenario);
        }
        catch (error) {
            throw toApiError(`Failed to create Scenario`, error);
        }
    }
    async removeScenario(scenarioId) {
        try {
            await this.makeDeleteRequest(`${this.baseApiUrl}/dataTables/scenarios/${scenarioId}`);
        }
        catch (error) {
            throw toApiError(`Failed to remove Scenario`, error);
        }
    }
    async getSessionEmails(sessionId) {
        try {
            const emailQueryString = query_string_1.default.stringify({
                context_id: sessionId?.slice(0, 8),
            });
            return await this.makeGetRequest(`${this.baseApiUrl}/execution/inputs?${emailQueryString}`);
        }
        catch (error) {
            throw toApiError(`Failed to get emails for session ID ${sessionId} with error`, error);
        }
    }
    async getEmailsToPermanentAddress(address, earliestReceivedTime, lookbackMilliseconds) {
        try {
            const emailQueryString = query_string_1.default.stringify({
                email_address: address,
                earliest_received_time: earliestReceivedTime,
                lookback_millis: lookbackMilliseconds,
            });
            return await this.makeGetRequest(`${this.baseApiUrl}/execution/inputs?${emailQueryString}`);
        }
        catch (error) {
            throw toApiError(`Failed to get emails for permanent address ${address} with error`, error);
        }
    }
    async createMailboxAddress(workspaceId, sessionId) {
        const contextId = sessionId?.slice(0, 8);
        try {
            const body = {
                context_id: contextId,
                workspace_id: workspaceId,
            };
            return await this.makePostRequestWithRetries(`${this.baseApiUrl}/mailbox/address`, body);
        }
        catch (error) {
            throw toApiError('Failed to create mailbox email address', error);
        }
    }
    async getMailboxAddress(emailAddressOrId) {
        try {
            return await this.makeGetRequest(`${this.baseApiUrl}/mailbox/address/${emailAddressOrId}`);
        }
        catch (error) {
            throw toApiError(`Failed to get mailbox ${emailAddressOrId} with error`, error);
        }
    }
    async updateMailboxStatus(mailboxId, status) {
        try {
            const body = { status };
            return await this.makePatchRequest(`${this.baseApiUrl}/mailbox/address/${mailboxId}/status`, body);
        }
        catch (error) {
            throw toApiError(`Failed to update mailbox ${mailboxId} with error`, error);
        }
    }
    async generateSteps(workspaceId, intent, context) {
        const body = {
            intent,
            context,
        };
        try {
            return await this.makePostRequestWithRetries(`${this.baseApiUrl}/generate/steps?workspaceId=${workspaceId}`, body);
        }
        catch (error) {
            throw toApiError('Failed to generate steps', error);
        }
    }
    async checkFileMetadataForGenAIAssertion(workspaceId, mimeType) {
        try {
            const uri = `${this.baseApiUrl}/agent/checkFileMetadataForGenAIAssertion?workspaceId=${encodeURIComponent(workspaceId)}&mimeType=${encodeURIComponent(mimeType)}`;
            return await this.makeGetRequest(uri);
        }
        catch (error) {
            throw toApiError('Failed to check file metadata for GenAI assertion', error);
        }
    }
    async evaluateAiAssertion(workspaceId, testRunId, screenshot, userPrompt, metaPrompt, criteria, test, variables, retryConfig, files) {
        const requestUrl = `${this.baseApiUrl}/agent/assertion?workspaceId=${workspaceId}`;
        return this.evaluateAiAssertionInternal(requestUrl, testRunId, screenshot, userPrompt, metaPrompt, criteria, test, variables, retryConfig, files);
    }
    async evaluateAiAssertionInternal(requestUrl, testRunId, screenshot, userPrompt, metaPrompt, criteria, test, variables, retryConfig = {
        requestTimeoutMillis: 120_000,
    }, files) {
        try {
            const body = {
                test_run_id: testRunId,
                assertion_prompt: userPrompt,
                assertion_criteria: criteria,
                screenshot: screenshot.toString('base64'),
                test_invariant_id: test?.invariant_id,
                test_type: test?.test_type,
                variables,
                files,
            };
            if (metaPrompt !== undefined) {
                body.override = {
                    meta_prompt: metaPrompt,
                };
            }
            return await this.makePostRequestWithRetries(requestUrl, body, retryConfig);
        }
        catch (error) {
            throw toApiError('Failed to evaluate the AI assertion', error);
        }
    }
    async createBranch(workspaceId, branchName) {
        try {
            const body = {
                workspace_id: workspaceId,
                name: branchName,
            };
            return await this.makePostRequest(`${this.baseApiUrl}/branch`, body);
        }
        catch (error) {
            throw toApiError(`Failed to create Branch [${branchName}]`, error);
        }
    }
    async mergeBranch(workspaceId, fromBranchName, toBranchName) {
        try {
            const queryStringArgs = {
                from: fromBranchName,
                to: toBranchName,
            };
            const mergeQueryString = query_string_1.default.stringify(queryStringArgs);
            const url = `${this.baseApiUrl}/branch/${workspaceId}/merge?${mergeQueryString}`;
            return await this.makePostRequest(url, {});
        }
        catch (error) {
            throw toApiError(`Failed to merge from branch [${fromBranchName}] to branch [${toBranchName}]`, error);
        }
    }
    async createExportRequest(journeyRunId, targetContent) {
        try {
            const body = {
                target_content: targetContent,
                target_entity_id: journeyRunId,
            };
            return await this.makePostRequest(`${this.baseApiUrl}/exports/journeyRuns/${journeyRunId}`, body);
        }
        catch (error) {
            throw toApiError(`Failed to create export`, error);
        }
    }
    async postDeploymentEvent(options) {
        try {
            const requestBody = this.buildDeploymentRequestBody(options);
            return await this.makePostRequestWithRetries(`${this.baseApiUrl}/events/deployment/`, requestBody);
        }
        catch (error) {
            throw toApiError(`Failed to create deployment`, error);
        }
    }
    buildDeploymentRequestBody(options) {
        const requestBody = { properties: {} };
        if (options.environmentId) {
            requestBody.environment_id = options.environmentId;
        }
        if (options.applicationId) {
            requestBody.application_id = options.applicationId;
        }
        if (options.debug) {
            requestBody.debug = true;
        }
        requestBody.revision = options.sourceControlMetadata?.revision;
        if (options.mablBranch) {
            requestBody.source_control_tag = options.mablBranch;
        }
        requestBody.properties.repository_branch_name =
            options.sourceControlMetadata?.branchName;
        requestBody.properties.repository_tag_name =
            options.sourceControlMetadata?.branchName;
        requestBody.properties.repository_url =
            options.sourceControlMetadata?.repoUrl;
        requestBody.properties.repository_name =
            options.sourceControlMetadata?.repoName;
        requestBody.properties.build_info_url =
            options.sourceControlMetadata?.buildInfoUrl;
        requestBody.properties.deployment_origin = options.sourceControlMetadata
            ?.integrationType
            ?
                `mabl-${options.sourceControlMetadata.integrationType}`
            : undefined;
        requestBody.properties.build_id = options.sourceControlMetadata?.buildId;
        const planOverrides = {};
        if (options.browserTypes?.length) {
            planOverrides.browser_types = options.browserTypes;
        }
        if (options.labels?.length) {
            requestBody.plan_labels = options.labels;
        }
        if (options.uri) {
            planOverrides.uri = options.uri;
        }
        if (options.appUrl) {
            planOverrides.web_url = options.appUrl;
        }
        if (options.apiUrl) {
            planOverrides.api_url = options.apiUrl;
        }
        if (options.deploymentIds) {
            planOverrides.deployment_ids = options.deploymentIds;
        }
        if (options.androidMobileAppFileId) {
            planOverrides.mobile_app_file_ids = {
                ...planOverrides.mobile_app_file_ids,
                [mablApi_1.MobilePlatformEnum.Android]: options.androidMobileAppFileId,
            };
        }
        if (options.iOSMobileAppFileId) {
            planOverrides.mobile_app_file_ids = {
                ...planOverrides.mobile_app_file_ids,
                [mablApi_1.MobilePlatformEnum.Ios]: options.iOSMobileAppFileId,
            };
        }
        if (options.httpHeaders?.length) {
            planOverrides.http_headers = options.httpHeaders.map((header) => {
                const parts = header.split(':', 2);
                return {
                    name: parts[0],
                    value: parts[1],
                    log_header_value: false,
                };
            });
            planOverrides.http_headers_required = true;
        }
        requestBody.plan_overrides = planOverrides;
        const actions = {};
        if (options.rebaselineImages) {
            actions.rebaseline_images = options.rebaselineImages;
        }
        if (options.setStaticBaseline) {
            actions.set_static_baseline = options.setStaticBaseline;
        }
        if (options.snapshotFromBranch) {
            actions.snapshot = { from: options.snapshotFromBranch };
        }
        if (options.targetRuntimeVersion) {
            requestBody.target_runtime_version = options.targetRuntimeVersion;
        }
        requestBody.actions = actions;
        return requestBody;
    }
    async getRecentTestRunsForTest(testId) {
        try {
            return await this.makeGetRequest(`${this.baseApiUrl}/journeyRuns/journey/${testId}`);
        }
        catch (error) {
            throw toApiError(`Failed to retrieve test runs for test`, error);
        }
    }
    async getRecentPlanRunsForPlan(workspaceId, planId) {
        try {
            return await this.makeGetRequest(`${this.baseApiUrl}/planRuns/workspace/${workspaceId}?plan_id=${planId}`);
        }
        catch (error) {
            throw toApiError(`Failed to retrieve plan runs for plan`, error);
        }
    }
    async getTestRunsForPlan(planRunId) {
        try {
            return this.makeGetRequest(`${this.baseApiUrl}/journeyRuns/planRun/${planRunId}`);
        }
        catch (error) {
            throw toApiError(`Failed to retrieve tests for plan`, error);
        }
    }
    async postPlanRun(organizationId, testId, branchName, browserTypes, appUrl, apiUrl, deploymentId, credentialsId, deploymentIds, basicAuthCredentialsId, localizationOptions) {
        try {
            const requestBody = this.buildAdHocPlanRunRequestBody(organizationId, testId, browserTypes, branchName, appUrl, apiUrl, deploymentId, credentialsId, deploymentIds, basicAuthCredentialsId, localizationOptions);
            return await this.makePostRequest(`${this.baseApiUrl}/planRuns/`, requestBody);
        }
        catch (error) {
            throw toApiError(`Failed to create planRun`, error);
        }
    }
    buildAdHocPlanRunRequestBody(organizationId, testId, browserTypes, branchName, appUrl, apiUrl, deploymentId, credentialsId, deploymentIds, basicAuthCredentialsId, localizationOptions) {
        const requestBody = {
            ad_hoc_run_info: {
                is_ad_hoc_run: true,
            },
        };
        const planOverrides = {};
        if (organizationId) {
            planOverrides.organization_id = organizationId;
        }
        if (deploymentId) {
            planOverrides.deployment_id = deploymentId;
        }
        if (browserTypes?.length) {
            planOverrides.browser_types = browserTypes;
        }
        if (appUrl) {
            planOverrides.web_url = appUrl;
        }
        if (apiUrl) {
            planOverrides.api_url = apiUrl;
        }
        if (credentialsId) {
            planOverrides.credentials_id = credentialsId;
            planOverrides.credentials_required = true;
        }
        if (basicAuthCredentialsId) {
            planOverrides.http_auth_credentials_id = basicAuthCredentialsId;
            planOverrides.http_auth_credentials_required = true;
        }
        if (localizationOptions) {
            planOverrides.localization_options = [localizationOptions];
        }
        if (testId) {
            planOverrides.journeys = [{ journey_id: testId }];
            planOverrides.execution_stages = [
                {
                    concurrency: mablApi_1.ExecutionStage.ConcurrencyEnum.Parallel,
                    journeys: [
                        {
                            journey_id: testId,
                        },
                    ],
                },
            ];
        }
        if (deploymentIds) {
            planOverrides.deployment_ids = deploymentIds;
        }
        requestBody.plan_overrides = planOverrides;
        if (branchName) {
            requestBody.source_control_tag_override = branchName;
        }
        return requestBody;
    }
    async createFlow(prototype, branch) {
        try {
            const url = branch
                ? `${this.baseApiUrl}/flows?branch=${branch}`
                : `${this.baseApiUrl}/flows`;
            return await this.makePostRequest(url, prototype);
        }
        catch (error) {
            throw toApiError(`Failed to create flow`, error);
        }
    }
    async updateFlow(flowId, prototype, branch, ifMatch) {
        try {
            const url = branch
                ? `${this.baseApiUrl}/flows/${flowId}?branch=${branch}`
                : `${this.baseApiUrl}/flows/${flowId}`;
            return await this.makePatchRequest(url, prototype, ifMatch);
        }
        catch (error) {
            throw toApiError(`Failed to update flow ${flowId}`, error);
        }
    }
    async batchUpdateFlows(flowUpdates, branch) {
        if (!flowUpdates.length) {
            return { flows: [] };
        }
        try {
            const url = branch
                ? `${this.baseApiUrl}/flows?branch=${branch}`
                : `${this.baseApiUrl}/flows`;
            return await this.makePutRequest(url, { flows: flowUpdates });
        }
        catch (error) {
            throw toApiError(`Failed to batch update flows`, error);
        }
    }
    async createJourney(prototype, branch) {
        try {
            const url = branch
                ? `${this.baseApiUrl}/test/journeys?branch=${branch}`
                : `${this.baseApiUrl}/test/journeys`;
            return await this.makePostRequest(url, prototype);
        }
        catch (error) {
            throw toApiError(`Failed to create journey`, error);
        }
    }
    async updateJourney(journeyId, prototype, ifMatch, branch) {
        try {
            const url = branch
                ? `${this.baseApiUrl}/test/journey/${journeyId}?branch=${branch}`
                : `${this.baseApiUrl}/test/journey/${journeyId}`;
            return await this.makePatchRequest(url, prototype, ifMatch);
        }
        catch (error) {
            throw toApiError(`Failed to update journey ${journeyId}`, error);
        }
    }
    async getJourneyRun(journeyRunId) {
        try {
            return await this.makeGetRequestWithETag(`${this.baseApiUrl}/journeyRuns/${journeyRunId}`);
        }
        catch (error) {
            throw toApiError(`Failed to get journey run info`, error);
        }
    }
    async updateJourneyRun(journeyRunId, journeyRunUpdate, ifMatch, retry) {
        try {
            const response = retry
                ? await this.makePatchRequestWithRetries(`${this.baseApiUrl}/journeyRuns/${journeyRunId}`, journeyRunUpdate, ifMatch)
                : await this.makePatchRequest(`${this.baseApiUrl}/journeyRuns/${journeyRunId}`, journeyRunUpdate, ifMatch);
            return response;
        }
        catch (error) {
            throw toApiError(`Failed to update journey run ${journeyRunId}`, error);
        }
    }
    async failJourneyRun(journeyRunId, cause) {
        try {
            const response = await this.makePatchRequest(`${this.baseApiUrl}/journeyRuns/${journeyRunId}`, {
                functionally_completed: false,
                status: mablApi_1.TestRun.StatusEnum.Failed,
                status_cause: cause,
            });
            return response;
        }
        catch (error) {
            throw toApiError(`Failed to update journey run ${journeyRunId}`, error);
        }
    }
    async terminateJourneyRun(journeyRunId, terminationReason) {
        const terminateParams = query_string_1.default.stringify({
            terminationReason: terminationReason.toString(),
        });
        try {
            const response = await this.makePostRequestWithRetries(`${this.baseApiUrl}/journeyRun/${journeyRunId}/terminate?${terminateParams}`);
            return response;
        }
        catch (error) {
            throw toApiError(`Failed to terminate journey run ${journeyRunId}`, error);
        }
    }
    async copyWorkspace(sourceWorkspaceId, destinationWorkspaceId, includeDefaults, includedTests, excludedTests) {
        const requestBody = {
            source_workspace_id: sourceWorkspaceId,
            destination_workspace_id: destinationWorkspaceId,
            include_defaults: includeDefaults,
            included_tests: includedTests,
            excluded_tests: excludedTests,
        };
        return this.makePostRequest(`${this.baseApiUrl}/copy/workspaces`, requestBody, {
            timeout: 3600000,
        });
    }
    async getEnabledAccountFeaturesByWorkspaceId(workspaceId) {
        try {
            const account = await this.getAccountByWorkspaceId(workspaceId);
            return new featureSet_1.FeatureSet(new Set(account.effective_features ?? []));
        }
        catch (error) {
            throw toApiError(`Failed to get effective account features for workspace ${workspaceId}`, error);
        }
    }
    async getEnabledLabsFeaturesForWorkspace(workspaceId) {
        try {
            const workspace = await this.getWorkspace(workspaceId);
            return new featureSet_1.FeatureSet(new Set(workspace.labs_features ?? []));
        }
        catch (error) {
            throw toApiError(`Failed to get labs features for workspace ${workspaceId}`, error);
        }
    }
    async getUsers(workspaceId, limit) {
        try {
            const userQueryString = query_string_1.default.stringify({
                organization_id: workspaceId,
                limit,
            });
            const users = await this.makeGetRequest(`${this.baseApiUrl}/users/?${userQueryString}`).then((result) => result.users ?? []);
            sortTemporallyAscending(users);
            return users;
        }
        catch (error) {
            throw toApiError(`Failed to get users`, error);
        }
    }
    async getStepIdsInJourneyByFlow(journeyInvariantId, flowIds) {
        try {
            const stepIdsQueryString = query_string_1.default.stringify({
                flow_variant_ids: flowIds.join(','),
            });
            return await this.makeGetRequest(`${this.baseApiUrl}/test/journey/${journeyInvariantId}/stepIdsByFlow?${stepIdsQueryString}`).then((result) => result ?? []);
        }
        catch (error) {
            throw toApiError(`Failed to get step ids in journey by flow`, error);
        }
    }
    async recordTimeSeriesMetricMeasurement(type, value, options) {
        try {
            return this.makePostRequest(`${this.baseApiUrl}/metrics/timeSeries`, createTimeSeriesMetricMeasurement(type, value, options));
        }
        catch (error) {
            throw toApiError('Failed to record time series metric measurement', error);
        }
    }
    async recordWorkspaceTimeSeriesMetricMeasurement(type, value, workspaceId, options) {
        const labels = { ...options?.labels, workspaceId };
        return this.recordTimeSeriesMetricMeasurement(type, value, {
            ...options,
            labels,
        });
    }
    async reportLocalGenAiAssertionUsage(workspaceId, testId, sessionId) {
        const requestBody = {
            workspace_id: workspaceId,
            test_id: testId,
            session_id: sessionId,
            usage_type: mablApi_1.LocalTestRunUsageType.LocalTestGenaiAssertions,
        };
        try {
            await this.makePostRequest(`${this.baseApiUrl}/testRun/local/usage`, requestBody);
        }
        catch (error) {
            throw toApiError('Failed to report local GenAI assertion usage', error);
        }
    }
    async getMobileAppFile(id, sign = false) {
        let url = `${this.baseApiUrl}/mobile/apps/files/${id}`;
        if (sign) {
            url += '?sign=true';
        }
        try {
            return await this.makeGetRequest(url);
        }
        catch (error) {
            throw toApiError(`Failed to get mobile app file ${id}`, error);
        }
    }
    async getMobileAppFiles(workspaceId, limit, platform) {
        try {
            const query = query_string_1.default.stringify({
                workspace_id: workspaceId,
                limit,
            });
            const filterConditions = [];
            if (platform !== undefined) {
                filterConditions.push({
                    column_name: 'platform',
                    comparator: mablApi_1.ComparatorEnum.Equal,
                    string_value: platform,
                });
            }
            const mobileAppFiles = await this.makePostRequest(`${this.baseApiUrl}/mobile/apps/files/queryFiles?${query}`, {
                filter_conditions: filterConditions,
                sort_columns: [
                    {
                        column_name: 'created_time',
                        sort_direction: 'DESC',
                    },
                ],
            }).then((result) => result.mobile_app_files ?? []);
            sortTemporallyDescending(mobileAppFiles);
            return mobileAppFiles;
        }
        catch (error) {
            throw toApiError(`Failed to get mobile app files`, error);
        }
    }
    async deleteMobileAppFile(id) {
        try {
            const response = await this.makeDeleteRequest(`${this.baseApiUrl}/mobile/apps/files/${id}`);
            return response;
        }
        catch (error) {
            throw toApiError(`Failed to delete mobile app file ${id}`, error);
        }
    }
    async createMobileTrainingSession(prototype) {
        try {
            return await this.makePostRequest(`${this.baseApiUrl}/mobile/training/sessions`, prototype);
        }
        catch (error) {
            throw toApiError(`Failed to create mobile training session`, error);
        }
    }
    async getMobileTrainingSession(id) {
        try {
            return await this.makeGetRequest(`${this.baseApiUrl}/mobile/training/session/${id}`);
        }
        catch (error) {
            throw toApiError(`Failed to get mobile training session ${id}`, error);
        }
    }
    async generateTestSummary(workspaceId, request) {
        try {
            return await this.makePostRequest(`${this.baseApiUrl}/agent/testSummary?workspaceId=${workspaceId}`, request);
        }
        catch (error) {
            throw toApiError(`Failed to generate test summary`, error);
        }
    }
    async initiateTestRecoverySession(workspaceId, request) {
        try {
            return await this.makePostRequest(`${this.baseApiUrl}/agent/testRecovery/session/initiate?workspaceId=${workspaceId}`, request);
        }
        catch (error) {
            throw toApiError(`Failed to initiate runtime recovery session`, error);
        }
    }
    async executeTestRecovery(workspaceId, request, requestTimeoutMs) {
        try {
            return await this.makePostRequest(`${this.baseApiUrl}/agent/testRecovery/execute?workspaceId=${workspaceId}`, request, { timeout: requestTimeoutMs });
        }
        catch (error) {
            throw toApiError(`Failed to execute runtime recovery`, error);
        }
    }
    async initiateRuntimeRecoverySummarySession(workspaceId, request) {
        try {
            return await this.makePostRequest(`${this.baseApiUrl}/agent/runtimeRecoverySummary/session/initiate?workspaceId=${workspaceId}`, request);
        }
        catch (error) {
            throw toApiError(`Failed to initiate ${agentNames_1.RUNTIME_RECOVERY_SUMMARY_AGENT_NAME} session`, error);
        }
    }
    async executeRuntimeRecoverySummary(workspaceId, request, retryConfig = {
        requestTimeoutMillis: 120_000,
    }) {
        try {
            return await this.makePostRequestWithRetries(`${this.baseApiUrl}/agent/runtimeRecoverySummary/execute?workspaceId=${workspaceId}`, request, retryConfig);
        }
        catch (error) {
            throw toApiError(`Failed to execute ${agentNames_1.RUNTIME_RECOVERY_SUMMARY_AGENT_NAME}`, error);
        }
    }
    async initiateTestAuthoringSession(workspaceId, request) {
        try {
            return await this.makePostRequest(`${this.baseApiUrl}/agent/testAuthoring/session/initiate?workspaceId=${workspaceId}`, request);
        }
        catch (error) {
            throw toApiError(`Failed to initiate test authoring session`, error);
        }
    }
    async executeTestAuthoring(workspaceId, request) {
        try {
            return await this.makePostRequest(`${this.baseApiUrl}/agent/testAuthoring/nextStep?workspaceId=${workspaceId}`, request);
        }
        catch (error) {
            throw toApiError(`Failed to execute test authoring`, error);
        }
    }
    async getAgentSession(id) {
        try {
            return await this.makeGetRequest(`${this.baseApiUrl}/agentSession/${id}`);
        }
        catch (error) {
            throw toApiError(`Failed to get agent session ${id}`, error);
        }
    }
    async initiateTestPlanningSession(workspaceId, request = {}) {
        try {
            return await this.makePostRequest(`${this.baseApiUrl}/agent/testPlanning/session/initiate?workspaceId=${workspaceId}`, request);
        }
        catch (error) {
            throw toApiError(`Failed to initiate test planning session`, error);
        }
    }
    async executeTestPlanNextStep(workspaceId, request) {
        try {
            return await this.makePostRequest(`${this.baseApiUrl}/agent/testPlanning/nextStep?workspaceId=${workspaceId}`, request);
        }
        catch (error) {
            throw toApiError(`Failed to execute test planning step`, error);
        }
    }
    async getAgentCloudInstance(agentSessionId, cloudInstanceId) {
        try {
            return await this.makeGetRequest(`${this.baseApiUrl}/agentSession/${agentSessionId}/cloudInstance/${cloudInstanceId}`);
        }
        catch (error) {
            throw toApiError(`Failed to get cloud instance ${cloudInstanceId} for session ${agentSessionId}`, error);
        }
    }
    async appendAgentSessionMessage(sessionId, message, relatedArtifacts) {
        try {
            return await this.makePostRequest(`${this.baseApiUrl}/agentSession/${sessionId}/messages`, {
                message,
                related_artifacts: relatedArtifacts,
            });
        }
        catch (error) {
            throw toApiError(`Failed to append messages to agent session ${sessionId}`, error);
        }
    }
    async runDatabaseQuery(queryExecution) {
        try {
            return await this.makePostRequest(`${this.baseApiUrl}/database/queryExecution`, queryExecution);
        }
        catch (error) {
            throw toApiError(`Failed to schedule database query execution`, error);
        }
    }
    async getDatabaseQueryExecution(executionId) {
        try {
            return await this.makeGetRequest(`${this.baseApiUrl}/database/queryExecution/${executionId}`);
        }
        catch (error) {
            throw toApiError(`Failed to schedule database query execution`, error);
        }
    }
    async terminateMobileTrainingSession(id, reason) {
        try {
            return await this.makePostRequest(`${this.baseApiUrl}/mobile/training/session/${id}/terminate`, { termination_reason: reason });
        }
        catch (error) {
            throw toApiError(`Failed to terminate mobile training session ${id}`, error);
        }
    }
    async generateElementDescription(workspaceId, request) {
        try {
            return await this.makePostRequest(`${this.baseApiUrl}/generate/elementDescription?workspaceId=${workspaceId}`, request);
        }
        catch (error) {
            throw toApiError(`Failed to generate element description`, error);
        }
    }
    async generateStepDescription(workspaceId, request) {
        try {
            return await this.makePostRequest(`${this.baseApiUrl}/agent/generate/stepDescription?workspaceId=${workspaceId}`, request);
        }
        catch (error) {
            throw toApiError(`Failed to generate step description`, error);
        }
    }
    async findElementImage(screenshot, findPrompt, workspaceId, includeElementImage, context) {
        try {
            const response = await this.makePostRequest(`${this.baseApiAgentUrl}/agent/find/findElementImage?workspaceId=${workspaceId}`, {
                screenshot,
                description: findPrompt,
                context,
                include_element_image: includeElementImage,
            });
            return response;
        }
        catch (error) {
            throw toApiError(`Failed to find element image ${findPrompt}`, error);
        }
    }
    async validateVisualFind(screenshot, findPrompt, boundingBox, workspaceId, context) {
        try {
            const response = await this.makePostRequest(`${this.baseApiAgentUrl}/agent/validate/visualFind?workspaceId=${workspaceId}`, {
                screenshot,
                description: findPrompt,
                bounding_box: boundingBox,
                context,
            });
            return response;
        }
        catch (error) {
            throw toApiError(`Failed to check element image ${findPrompt}`, error);
        }
    }
    async logoutJwt() {
        try {
            await this.makeDeleteRequest(`${this.baseApiUrl}/logout/jwt`);
        }
        catch (error) {
            throw toApiError('Failed to revoke token', error);
        }
    }
}
exports.MablApiClient = MablApiClient;
function sortTemporallyAscending(entities) {
    entities.sort((a, b) => a.created_time - b.created_time);
}
function sortTemporallyDescending(entities) {
    entities.sort((a, b) => b.created_time - a.created_time);
}
function toApiError(summary, cause) {
    if (cause instanceof ApiError_1.ApiError) {
        return cause;
    }
    if (axios_1.default.isAxiosError(cause)) {
        const errorResponse = cause.response;
        const code = errorResponse?.status;
        const mablError = errorResponse?.data;
        const message = `${summary}: ${mablError?.message ?? cause.toString()}`;
        return new ApiError_1.ApiError(message, code, cause);
    }
    return new ApiError_1.ApiError(summary, undefined, cause);
}
function createTimeSeriesMetricMeasurement(type, numberValue, options) {
    return {
        labels: options?.labels,
        event_time: options?.event_time,
        type,
        value: Number.isInteger(numberValue)
            ? { int64_value: numberValue }
            : { double_value: numberValue },
    };
}
