var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
    return function (target, key) { decorator(target, key, paramIndex); }
};
var AskSkipResolver_1;
import { Arg, Ctx, Field, ObjectType, PubSub, PubSubEngine, Query, Resolver } from 'type-graphql';
import { LogError, LogStatus, Metadata, RunView, CompositeKey } from '@memberjunction/core';
import { BehaviorSubject } from 'rxjs';
import { UserCache } from '@memberjunction/sqlserver-dataprovider';
import { DataContext } from '@memberjunction/data-context';
import { LoadDataContextItemsServer } from '@memberjunction/data-context-server';
LoadDataContextItemsServer();
import { PUSH_STATUS_UPDATES_TOPIC } from '../generic/PushStatusResolver.js';
import { apiKey as callbackAPIKey, baseUrl, publicUrl, configInfo, graphqlPort, graphqlRootPath } from '../config.js';
import mssql from 'mssql';
import { registerEnumType } from 'type-graphql';
import { MJGlobal, CopyScalarsAndArrays } from '@memberjunction/global';
import { GetReadWriteProvider, sendPostRequest } from '../util.js';
import { GetAIAPIKey } from '@memberjunction/ai';
import { CompositeKeyInputType } from '../generic/KeyInputOutputTypes.js';
import { AIEngine } from '@memberjunction/aiengine';
import { deleteAccessToken, registerAccessToken, tokenExists } from './GetDataResolver.js';
const SKIP_API_ENDPOINTS = {
    CHAT: '/chat',
    LEARNING: '/learning',
    FEEDBACK_COMPONENT: '/feedback/component',
    REGISTRY: '/registry',
};
class ActiveConversationStreams {
    static instance;
    streams = new Map();
    constructor() { }
    static getInstance() {
        if (!ActiveConversationStreams.instance) {
            ActiveConversationStreams.instance = new ActiveConversationStreams();
        }
        return ActiveConversationStreams.instance;
    }
    updateStatus(conversationId, status, sessionId) {
        const existing = this.streams.get(conversationId);
        if (existing) {
            existing.lastStatus = status;
            existing.lastUpdate = new Date();
            if (sessionId) {
                existing.sessionIds.add(sessionId);
            }
        }
        else {
            const now = new Date();
            this.streams.set(conversationId, {
                lastStatus: status,
                lastUpdate: now,
                startTime: now,
                sessionIds: sessionId ? new Set([sessionId]) : new Set()
            });
        }
    }
    getStatus(conversationId) {
        const stream = this.streams.get(conversationId);
        return stream ? stream.lastStatus : null;
    }
    getStartTime(conversationId) {
        const stream = this.streams.get(conversationId);
        return stream ? stream.startTime : null;
    }
    addSession(conversationId, sessionId) {
        const stream = this.streams.get(conversationId);
        if (stream) {
            stream.sessionIds.add(sessionId);
        }
        else {
            const now = new Date();
            this.streams.set(conversationId, {
                lastStatus: 'Processing...',
                lastUpdate: now,
                startTime: now,
                sessionIds: new Set([sessionId])
            });
        }
    }
    removeConversation(conversationId) {
        this.streams.delete(conversationId);
    }
    isActive(conversationId) {
        const stream = this.streams.get(conversationId);
        if (!stream)
            return false;
        const fiveMinutesAgo = new Date(Date.now() - 5 * 60 * 1000);
        return stream.lastUpdate > fiveMinutesAgo;
    }
    getSessionIds(conversationId) {
        const stream = this.streams.get(conversationId);
        return stream ? Array.from(stream.sessionIds) : [];
    }
    cleanupStaleStreams() {
        const now = new Date();
        const staleThreshold = new Date(now.getTime() - 30 * 60 * 1000);
        const staleConversations = [];
        this.streams.forEach((stream, conversationId) => {
            if (stream.lastUpdate < staleThreshold) {
                staleConversations.push(conversationId);
            }
        });
        staleConversations.forEach(conversationId => {
            this.streams.delete(conversationId);
            LogStatus(`Cleaned up stale stream for conversation ${conversationId}`);
        });
        if (staleConversations.length > 0) {
            LogStatus(`Cleaned up ${staleConversations.length} stale conversation streams`);
        }
    }
}
const activeStreams = ActiveConversationStreams.getInstance();
setInterval(() => {
    activeStreams.cleanupStaleStreams();
}, 10 * 60 * 1000);
let ReattachConversationResponse = class ReattachConversationResponse {
    lastStatusMessage;
    startTime;
};
__decorate([
    Field(() => String, { nullable: true }),
    __metadata("design:type", String)
], ReattachConversationResponse.prototype, "lastStatusMessage", void 0);
__decorate([
    Field(() => Date, { nullable: true }),
    __metadata("design:type", Date)
], ReattachConversationResponse.prototype, "startTime", void 0);
ReattachConversationResponse = __decorate([
    ObjectType()
], ReattachConversationResponse);
var SkipResponsePhase;
(function (SkipResponsePhase) {
    SkipResponsePhase["ClarifyingQuestion"] = "clarifying_question";
    SkipResponsePhase["DataRequest"] = "data_request";
    SkipResponsePhase["AnalysisComplete"] = "analysis_complete";
})(SkipResponsePhase || (SkipResponsePhase = {}));
registerEnumType(SkipResponsePhase, {
    name: 'SkipResponsePhase',
    description: 'The phase of the respons: clarifying_question, data_request, or analysis_complete',
});
let AskSkipResultType = class AskSkipResultType {
    Success;
    Status;
    ResponsePhase;
    Result;
    ConversationId;
    UserMessageConversationDetailId;
    AIMessageConversationDetailId;
};
__decorate([
    Field(() => Boolean),
    __metadata("design:type", Boolean)
], AskSkipResultType.prototype, "Success", void 0);
__decorate([
    Field(() => String),
    __metadata("design:type", String)
], AskSkipResultType.prototype, "Status", void 0);
__decorate([
    Field(() => SkipResponsePhase),
    __metadata("design:type", String)
], AskSkipResultType.prototype, "ResponsePhase", void 0);
__decorate([
    Field(() => String),
    __metadata("design:type", String)
], AskSkipResultType.prototype, "Result", void 0);
__decorate([
    Field(() => String),
    __metadata("design:type", String)
], AskSkipResultType.prototype, "ConversationId", void 0);
__decorate([
    Field(() => String),
    __metadata("design:type", String)
], AskSkipResultType.prototype, "UserMessageConversationDetailId", void 0);
__decorate([
    Field(() => String),
    __metadata("design:type", String)
], AskSkipResultType.prototype, "AIMessageConversationDetailId", void 0);
AskSkipResultType = __decorate([
    ObjectType()
], AskSkipResultType);
export { AskSkipResultType };
let ManualLearningCycleResultType = class ManualLearningCycleResultType {
    Success;
    Message;
};
__decorate([
    Field(() => Boolean),
    __metadata("design:type", Boolean)
], ManualLearningCycleResultType.prototype, "Success", void 0);
__decorate([
    Field(() => String),
    __metadata("design:type", String)
], ManualLearningCycleResultType.prototype, "Message", void 0);
ManualLearningCycleResultType = __decorate([
    ObjectType()
], ManualLearningCycleResultType);
export { ManualLearningCycleResultType };
let CycleDetailsType = class CycleDetailsType {
    LearningCycleId;
    StartTime;
    RunningForMinutes;
};
__decorate([
    Field(() => String),
    __metadata("design:type", String)
], CycleDetailsType.prototype, "LearningCycleId", void 0);
__decorate([
    Field(() => String),
    __metadata("design:type", String)
], CycleDetailsType.prototype, "StartTime", void 0);
__decorate([
    Field(() => Number),
    __metadata("design:type", Number)
], CycleDetailsType.prototype, "RunningForMinutes", void 0);
CycleDetailsType = __decorate([
    ObjectType()
], CycleDetailsType);
export { CycleDetailsType };
let RunningOrganizationType = class RunningOrganizationType {
    OrganizationId;
    LearningCycleId;
    StartTime;
    RunningForMinutes;
};
__decorate([
    Field(() => String),
    __metadata("design:type", String)
], RunningOrganizationType.prototype, "OrganizationId", void 0);
__decorate([
    Field(() => String),
    __metadata("design:type", String)
], RunningOrganizationType.prototype, "LearningCycleId", void 0);
__decorate([
    Field(() => String),
    __metadata("design:type", String)
], RunningOrganizationType.prototype, "StartTime", void 0);
__decorate([
    Field(() => Number),
    __metadata("design:type", Number)
], RunningOrganizationType.prototype, "RunningForMinutes", void 0);
RunningOrganizationType = __decorate([
    ObjectType()
], RunningOrganizationType);
export { RunningOrganizationType };
let LearningCycleStatusType = class LearningCycleStatusType {
    IsSchedulerRunning;
    LastRunTime;
    RunningOrganizations;
};
__decorate([
    Field(() => Boolean),
    __metadata("design:type", Boolean)
], LearningCycleStatusType.prototype, "IsSchedulerRunning", void 0);
__decorate([
    Field(() => String, { nullable: true }),
    __metadata("design:type", String)
], LearningCycleStatusType.prototype, "LastRunTime", void 0);
__decorate([
    Field(() => [RunningOrganizationType], { nullable: true }),
    __metadata("design:type", Array)
], LearningCycleStatusType.prototype, "RunningOrganizations", void 0);
LearningCycleStatusType = __decorate([
    ObjectType()
], LearningCycleStatusType);
export { LearningCycleStatusType };
let StopLearningCycleResultType = class StopLearningCycleResultType {
    Success;
    Message;
    WasRunning;
    CycleDetails;
};
__decorate([
    Field(() => Boolean),
    __metadata("design:type", Boolean)
], StopLearningCycleResultType.prototype, "Success", void 0);
__decorate([
    Field(() => String),
    __metadata("design:type", String)
], StopLearningCycleResultType.prototype, "Message", void 0);
__decorate([
    Field(() => Boolean),
    __metadata("design:type", Boolean)
], StopLearningCycleResultType.prototype, "WasRunning", void 0);
__decorate([
    Field(() => CycleDetailsType, { nullable: true }),
    __metadata("design:type", CycleDetailsType)
], StopLearningCycleResultType.prototype, "CycleDetails", void 0);
StopLearningCycleResultType = __decorate([
    ObjectType()
], StopLearningCycleResultType);
export { StopLearningCycleResultType };
let AskSkipResolver = class AskSkipResolver {
    static { AskSkipResolver_1 = this; }
    static _defaultNewChatName = 'New Chat';
    static _maxHistoricalMessages = 30;
    async ExecuteAskSkipRecordChat(UserQuestion, ConversationId, EntityName, compositeKey, { dataSource, userPayload, providers }, pubSub) {
        const user = UserCache.Instance.Users.find((u) => u.Email.trim().toLowerCase() === userPayload.email.trim().toLowerCase());
        if (!user)
            throw new Error(`User ${userPayload.email} not found in UserCache`);
        let messages = [];
        if (ConversationId && ConversationId.length > 0) {
            messages = await this.LoadConversationDetailsIntoSkipMessages(dataSource, ConversationId, AskSkipResolver_1._maxHistoricalMessages);
        }
        const md = GetReadWriteProvider(providers);
        const { convoEntity, dataContextEntity, convoDetailEntity, dataContext } = await this.HandleSkipChatInitialObjectLoading(dataSource, ConversationId, UserQuestion, user, userPayload, md, null);
        if (!ConversationId || ConversationId.length === 0) {
            const dci = await md.GetEntityObject('Data Context Items', user);
            dci.DataContextID = dataContext.ID;
            dci.Type = 'single_record';
            dci.EntityID = md.Entities.find((e) => e.Name === EntityName)?.ID;
            const ck = new CompositeKey();
            ck.KeyValuePairs = compositeKey.KeyValuePairs;
            dci.RecordID = ck.Values();
            let dciSaveResult = await dci.Save();
            if (!dciSaveResult) {
                LogError(`Error saving DataContextItemEntity for record chat: ${EntityName} ${ck.Values()}`, undefined, dci.LatestResult);
            }
            await dataContext.Load(dataContext.ID, dataSource, false, true, 10, user);
            await dataContext.SaveItems(user, true);
            convoEntity.LinkedEntityID = dci.EntityID;
            convoEntity.LinkedRecordID = ck.Values();
            convoEntity.DataContextID = dataContext.ID;
            const convoEntitySaveResult = await convoEntity.Save();
            if (!convoEntitySaveResult) {
                LogError(`Error saving ConversationEntity for record chat: ${EntityName} ${ck.Values()}`, undefined, convoEntity.LatestResult);
            }
        }
        const input = await this.buildSkipChatAPIRequest(messages, ConversationId, dataContext, 'chat_with_a_record', false, false, false, false, user, dataSource, false, false);
        messages.push({
            content: UserQuestion,
            role: 'user',
            conversationDetailID: convoDetailEntity.ID,
        });
        return this.handleSimpleSkipChatPostRequest(input, convoEntity, convoDetailEntity, true, user, userPayload);
    }
    async handleSimpleSkipChatPostRequest(input, convoEntity = null, convoDetailEntity = null, createAIMessageConversationDetail = false, user = null, userPayload = null) {
        const skipConfigInfo = configInfo.askSkip;
        const chatURL = skipConfigInfo.url ? `${skipConfigInfo.url}${SKIP_API_ENDPOINTS.CHAT}` : skipConfigInfo.chatURL;
        LogStatus(`   >>> HandleSimpleSkipChatPostRequest Sending request to Skip API: ${chatURL}`);
        try {
            const response = await sendPostRequest(chatURL, input, true, this.buildSkipPostHeaders());
            if (response && response.length > 0) {
                const apiResponse = response[response.length - 1].value;
                const AIMessageConversationDetailID = createAIMessageConversationDetail && convoEntity
                    ? await this.CreateAIMessageConversationDetail(apiResponse, convoEntity.ID, user, userPayload)
                    : '';
                LogStatus(`  Skip API response: ${apiResponse.responsePhase}`);
                return {
                    Success: true,
                    Status: 'OK',
                    ResponsePhase: SkipResponsePhase.AnalysisComplete,
                    ConversationId: convoEntity ? convoEntity.ID : '',
                    UserMessageConversationDetailId: convoDetailEntity ? convoDetailEntity.ID : '',
                    AIMessageConversationDetailId: AIMessageConversationDetailID,
                    Result: JSON.stringify(apiResponse),
                };
            }
            else {
                if (convoEntity) {
                    await this.setConversationStatus(convoEntity, 'Available', userPayload);
                }
                return {
                    Success: false,
                    Status: 'Error',
                    Result: `Request failed`,
                    ResponsePhase: SkipResponsePhase.AnalysisComplete,
                    ConversationId: convoEntity ? convoEntity.ID : '',
                    UserMessageConversationDetailId: convoDetailEntity ? convoDetailEntity.ID : '',
                    AIMessageConversationDetailId: '',
                };
            }
        }
        catch (error) {
            if (convoEntity) {
                await this.setConversationStatus(convoEntity, 'Available', userPayload);
            }
            LogError(`Error in handleSimpleSkipChatPostRequest: ${error}`);
            throw error;
        }
    }
    async CreateAIMessageConversationDetail(apiResponse, conversationID, user, userPayload) {
        const md = new Metadata();
        const convoDetailEntityAI = await md.GetEntityObject('Conversation Details', user);
        convoDetailEntityAI.NewRecord();
        convoDetailEntityAI.HiddenToUser = false;
        convoDetailEntityAI.ConversationID = conversationID;
        const systemMessages = apiResponse.messages.filter((m) => m.role === 'system');
        const lastSystemMessage = systemMessages[systemMessages.length - 1];
        convoDetailEntityAI.Message = lastSystemMessage?.content;
        convoDetailEntityAI.Role = 'AI';
        if (await convoDetailEntityAI.Save()) {
            return convoDetailEntityAI.ID;
        }
        else {
            LogError(`Error saving conversation detail entity for AI message: ${lastSystemMessage?.content}`, undefined, convoDetailEntityAI.LatestResult);
            return '';
        }
    }
    async buildBaseSkipRequest(contextUser, dataSource, includeEntities, includeQueries, includeNotes, filterUserNotesToContextUser, includeRequests, forceEntitiesRefresh = false, includeCallBackKeyAndAccessToken = false, additionalTokenInfo = {}) {
        const skipConfigInfo = configInfo.askSkip;
        const entities = includeEntities ? await this.BuildSkipEntities(dataSource, forceEntitiesRefresh) : [];
        const queries = includeQueries ? this.BuildSkipQueries() : [];
        const requests = includeRequests ? await this.BuildSkipRequests(contextUser) : [];
        let accessToken;
        if (includeCallBackKeyAndAccessToken) {
            const tokenInfo = {
                type: 'skip_api_request',
                userEmail: contextUser.Email,
                userName: contextUser.Name,
                userID: contextUser.ID,
                ...additionalTokenInfo
            };
            accessToken = registerAccessToken(undefined, 1000 * 60 * 10, tokenInfo);
        }
        return {
            entities,
            queries,
            notes: undefined,
            noteTypes: undefined,
            userEmail: contextUser.Email,
            requests,
            accessToken,
            organizationID: skipConfigInfo.orgID,
            organizationInfo: configInfo?.askSkip?.organizationInfo,
            apiKeys: this.buildSkipAPIKeys(),
            callingServerURL: accessToken ? (publicUrl || `${baseUrl}:${graphqlPort}${graphqlRootPath}`) : undefined,
            callingServerAPIKey: accessToken ? callbackAPIKey : undefined,
            callingServerAccessToken: accessToken ? accessToken.Token : undefined
        };
    }
    async buildSkipLearningAPIRequest(learningCycleId, lastLearningCycleDate, includeEntities, includeQueries, includeNotes, includeRequests, dataSource, contextUser, forceEntitiesRefresh = false, includeCallBackKeyAndAccessToken = false) {
        const baseRequest = await this.buildBaseSkipRequest(contextUser, dataSource, includeEntities, includeQueries, includeNotes, false, includeRequests, forceEntitiesRefresh, includeCallBackKeyAndAccessToken);
        const newConversations = await this.BuildSkipLearningCycleNewConversations(lastLearningCycleDate, dataSource, contextUser);
        const input = {
            organizationId: baseRequest.organizationID,
            organizationInfo: baseRequest.organizationInfo,
            learningCycleId,
            lastLearningCycleDate,
            newConversations,
            entities: baseRequest.entities,
            queries: baseRequest.queries,
            notes: baseRequest.notes,
            noteTypes: baseRequest.noteTypes,
            requests: baseRequest.requests,
            apiKeys: baseRequest.apiKeys
        };
        return input;
    }
    async BuildSkipLearningCycleNewConversations(lastLearningCycleDate, dataSource, contextUser) {
        try {
            const rv = new RunView();
            const conversationsSinceLastLearningCycle = await rv.RunView({
                EntityName: 'Conversations',
                ExtraFilter: `ID IN (SELECT ConversationID FROM __mj.vwConversationDetails WHERE __mj_UpdatedAt >= '${lastLearningCycleDate.toISOString()}')`,
                ResultType: 'entity_object',
            }, contextUser);
            if (!conversationsSinceLastLearningCycle.Success || conversationsSinceLastLearningCycle.Results.length === 0) {
                return [];
            }
            return await Promise.all(conversationsSinceLastLearningCycle.Results.map(async (c) => {
                return {
                    id: c.ID,
                    name: c.Name,
                    userId: c.UserID,
                    user: c.User,
                    description: c.Description,
                    messages: await this.LoadConversationDetailsIntoSkipMessages(dataSource, c.ID),
                    createdAt: c.__mj_CreatedAt,
                    updatedAt: c.__mj_UpdatedAt
                };
            }));
        }
        catch (e) {
            LogError(`Error loading conversations since last learning cycle: ${e}`);
            return [];
        }
    }
    async BuildSkipRequests(contextUser) {
        try {
            const md = new Metadata();
            const requestEntity = await md.GetEntityObject('AI Agent Requests', contextUser);
            const allRequests = await requestEntity.GetAll();
            const requests = allRequests.map((r) => {
                return {
                    id: r.ID,
                    agentId: r.AIAgentID,
                    agnet: r.AIAgent,
                    requestedAt: r.RequestedAt,
                    requestForUserId: r.RequestedForUserID,
                    requestForUser: r.RequestedForUser,
                    status: r.Status,
                    request: r.Request,
                    response: r.Response,
                    responseByUserId: r.ResponseByUserID,
                    responseByUser: r.ResponseByUser,
                    respondedAt: r.RespondedAt,
                    comments: r.Comments,
                    createdAt: r.__mj_CreatedAt,
                    updatedAt: r.__mj_UpdatedAt,
                };
            });
            return requests;
        }
        catch (e) {
            LogError(`Error loading requests: ${e}`);
            return [];
        }
    }
    async GetLastCompleteLearningCycleDate(agentID, user) {
        const md = new Metadata();
        const rv = new RunView();
        const lastLearningCycleRV = await rv.RunView({
            EntityName: 'AI Agent Learning Cycles',
            ExtraFilter: `AgentID = '${agentID}' AND Status = 'Complete'`,
            ResultType: 'entity_object',
            OrderBy: 'StartedAt DESC',
            MaxRows: 1,
        }, user);
        const lastLearningCycle = lastLearningCycleRV.Results[0];
        if (lastLearningCycle) {
            return lastLearningCycle.StartedAt;
        }
        else {
            return new Date(0);
        }
    }
    async buildSkipChatAPIRequest(messages, conversationId, dataContext, requestPhase, includeEntities, includeQueries, includeNotes, includeRequests, contextUser, dataSource, forceEntitiesRefresh = false, includeCallBackKeyAndAccessToken = false) {
        const additionalTokenInfo = {
            conversationId,
            requestPhase,
        };
        const baseRequest = await this.buildBaseSkipRequest(contextUser, dataSource, includeEntities, includeQueries, includeNotes, true, includeRequests, forceEntitiesRefresh, includeCallBackKeyAndAccessToken, additionalTokenInfo);
        const artifacts = await this.buildSkipAPIArtifacts(contextUser, dataSource, conversationId);
        const input = {
            ...baseRequest,
            messages,
            conversationID: conversationId.toString(),
            dataContext: CopyScalarsAndArrays(dataContext),
            requestPhase,
            artifacts: artifacts
        };
        return input;
    }
    async buildSkipAPIArtifacts(contextUser, dataSource, conversationId) {
        const md = new Metadata();
        const ei = md.EntityByName('MJ: Conversation Artifacts');
        const rv = new RunView();
        const results = await rv.RunViews([
            {
                EntityName: "MJ: Conversation Artifacts",
                ExtraFilter: `ConversationID='${conversationId}'`,
                OrderBy: "__mj_CreatedAt"
            },
            {
                EntityName: "MJ: Artifact Types",
                OrderBy: "Name"
            },
            {
                EntityName: "MJ: Conversation Artifact Versions",
                ExtraFilter: `ConversationArtifactID IN (SELECT ID FROM [${ei.SchemaName}].[${ei.BaseView}] WHERE ConversationID='${conversationId}')`,
                OrderBy: 'ConversationArtifactID, __mj_CreatedAt'
            }
        ], contextUser);
        if (results && results.length > 0 && results.every((r) => r.Success)) {
            const types = results[1].Results.map((a) => {
                const retVal = {
                    id: a.ID,
                    name: a.Name,
                    description: a.Description,
                    contentType: a.ContentType,
                    enabled: a.IsEnabled,
                    createdAt: a.__mj_CreatedAt,
                    updatedAt: a.__mj_UpdatedAt
                };
                return retVal;
            });
            const allConvoArtifacts = results[0].Results.map((a) => {
                const rawVersions = results[2].Results;
                const thisArtifactsVersions = rawVersions.filter(rv => rv.ConversationArtifactID === a.ID);
                const versionsForThisArtifact = thisArtifactsVersions.map((v) => {
                    const versionRetVal = {
                        id: v.ID,
                        artifactId: v.ConversationArtifactID,
                        version: v.Version,
                        configuration: v.Configuration,
                        content: v.Content,
                        comments: v.Comments,
                        createdAt: v.__mj_CreatedAt,
                        updatedAt: v.__mj_UpdatedAt
                    };
                    return versionRetVal;
                });
                const artifactRetVal = {
                    id: a.ID,
                    name: a.Name,
                    description: a.Description,
                    comments: a.Comments,
                    sharingScope: a.SharingScope,
                    versions: versionsForThisArtifact,
                    conversationId: a.ConversationID,
                    artifactType: types.find((t => t.id === a.ArtifactTypeID)),
                    createdAt: a.__mj_CreatedAt,
                    updatedAt: a.__mj_UpdatedAt
                };
                return artifactRetVal;
            });
            return allConvoArtifacts;
        }
        else {
            return [];
        }
    }
    async ExecuteAskSkipRunScript({ dataSource, userPayload }, pubSub, DataContextId, ScriptText) {
        const user = UserCache.Instance.Users.find((u) => u.Email.trim().toLowerCase() === userPayload.email.trim().toLowerCase());
        if (!user)
            throw new Error(`User ${userPayload.email} not found in UserCache`);
        const dataContext = new DataContext();
        await dataContext.Load(DataContextId, dataSource, true, false, 0, user);
        const input = await this.buildSkipChatAPIRequest([], '', dataContext, 'run_existing_script', false, false, false, false, user, dataSource, false, false);
        input.scriptText = ScriptText;
        return this.handleSimpleSkipChatPostRequest(input, undefined, undefined, undefined, userPayload.userRecord, userPayload);
    }
    buildSkipAPIKeys() {
        return [
            {
                vendorDriverName: 'OpenAILLM',
                apiKey: GetAIAPIKey('OpenAILLM'),
            },
            {
                vendorDriverName: 'AnthropicLLM',
                apiKey: GetAIAPIKey('AnthropicLLM'),
            },
            {
                vendorDriverName: 'GeminiLLM',
                apiKey: GetAIAPIKey('GeminiLLM'),
            },
            {
                vendorDriverName: 'GroqLLM',
                apiKey: GetAIAPIKey('GroqLLM'),
            },
            {
                vendorDriverName: 'MistralLLM',
                apiKey: GetAIAPIKey('MistralLLM'),
            },
            {
                vendorDriverName: 'CerebrasLLM',
                apiKey: GetAIAPIKey('CerebrasLLM'),
            },
        ];
    }
    async ReattachToProcessingConversation(ConversationId, { userPayload, providers }, pubSub) {
        try {
            const md = GetReadWriteProvider(providers);
            const user = UserCache.Instance.Users.find((u) => u.Email.trim().toLowerCase() === userPayload.email.trim().toLowerCase());
            if (!user) {
                LogError(`User ${userPayload.email} not found in UserCache`);
                return null;
            }
            const convoEntity = await md.GetEntityObject('Conversations', user);
            const loadResult = await convoEntity.Load(ConversationId);
            if (!loadResult) {
                LogError(`Could not load conversation ${ConversationId} for re-attachment`);
                return null;
            }
            if (convoEntity.UserID !== user.ID) {
                LogError(`Conversation ${ConversationId} does not belong to user ${user.Email}`);
                return null;
            }
            if (convoEntity.Status === 'Processing') {
                activeStreams.addSession(ConversationId, userPayload.sessionId);
                const lastStatusMessage = activeStreams.getStatus(ConversationId) || 'Processing...';
                const startTime = activeStreams.getStartTime(ConversationId);
                const isStreamActive = activeStreams.isActive(ConversationId);
                if (isStreamActive) {
                    const statusMessage = {
                        type: 'AskSkip',
                        status: 'OK',
                        ResponsePhase: 'Processing',
                        conversationID: convoEntity.ID,
                        message: lastStatusMessage,
                    };
                    pubSub.publish(PUSH_STATUS_UPDATES_TOPIC, {
                        pushStatusUpdates: {
                            message: JSON.stringify(statusMessage),
                            sessionId: userPayload.sessionId
                        }
                    });
                    LogStatus(`Re-attached session ${userPayload.sessionId} to active stream for conversation ${ConversationId}, last status: ${lastStatusMessage}`);
                    return {
                        lastStatusMessage,
                        startTime: startTime || convoEntity.__mj_UpdatedAt
                    };
                }
                else {
                    const statusMessage = {
                        type: 'AskSkip',
                        status: 'OK',
                        ResponsePhase: 'Processing',
                        conversationID: convoEntity.ID,
                        message: 'Processing...',
                    };
                    pubSub.publish(PUSH_STATUS_UPDATES_TOPIC, {
                        pushStatusUpdates: {
                            message: JSON.stringify(statusMessage),
                            sessionId: userPayload.sessionId
                        }
                    });
                    LogStatus(`Re-attached session ${userPayload.sessionId} to conversation ${ConversationId}, but stream is inactive`);
                    return {
                        lastStatusMessage: 'Processing...',
                        startTime: convoEntity.__mj_UpdatedAt
                    };
                }
            }
            else {
                LogStatus(`Conversation ${ConversationId} is not processing (Status: ${convoEntity.Status})`);
                return null;
            }
        }
        catch (error) {
            LogError(`Error re-attaching to conversation: ${error}`);
            return null;
        }
    }
    async ExecuteAskSkipAnalysisQuery(UserQuestion, ConversationId, { dataSource, userPayload, providers }, pubSub, DataContextId, ForceEntityRefresh, StartTime) {
        const md = GetReadWriteProvider(providers);
        const user = UserCache.Instance.Users.find((u) => u.Email.trim().toLowerCase() === userPayload.email.trim().toLowerCase());
        if (!user)
            throw new Error(`User ${userPayload.email} not found in UserCache`);
        const requestStartTime = StartTime || new Date();
        const { convoEntity, dataContextEntity, convoDetailEntity, dataContext } = await this.HandleSkipChatInitialObjectLoading(dataSource, ConversationId, UserQuestion, user, userPayload, md, DataContextId);
        await this.setConversationStatus(convoEntity, 'Processing', userPayload, pubSub);
        const messages = await this.LoadConversationDetailsIntoSkipMessages(dataSource, convoEntity.ID, AskSkipResolver_1._maxHistoricalMessages);
        const conversationDetailCount = 1;
        const input = await this.buildSkipChatAPIRequest(messages, ConversationId, dataContext, 'initial_request', true, true, true, false, user, dataSource, ForceEntityRefresh === undefined ? false : ForceEntityRefresh, true);
        return this.HandleSkipChatRequest(input, UserQuestion, user, dataSource, ConversationId, userPayload, pubSub, md, convoEntity, convoDetailEntity, dataContext, dataContextEntity, conversationDetailCount, requestStartTime);
    }
    buildQueryCategoryPath(md, categoryID) {
        const cat = md.QueryCategories.find((c) => c.ID === categoryID);
        if (!cat)
            return '';
        if (!cat.ParentID)
            return cat.Name;
        const parentPath = this.buildQueryCategoryPath(md, cat.ParentID);
        return parentPath ? `${parentPath}/${cat.Name}` : cat.Name;
    }
    BuildSkipQueries(status = 'Approved') {
        const md = new Metadata();
        const approvedQueries = md.Queries.filter((q) => q.Status === status);
        return approvedQueries.map((q) => ({
            ID: q.ID,
            Name: q.Name,
            Description: q.Description,
            Category: q.Category,
            CategoryPath: this.buildQueryCategoryPath(md, q.CategoryID),
            CategoryID: q.CategoryID,
            SQL: q.SQL,
            Status: q.Status,
            QualityRank: q.QualityRank,
            EmbeddingVector: q.EmbeddingVector,
            EmbeddingModelID: q.EmbeddingModelID,
            EmbeddingModelName: q.EmbeddingModel,
            Fields: q.Fields.map((f) => ({
                ID: f.ID,
                QueryID: f.QueryID,
                Name: f.Name,
                Description: f.Description,
                Sequence: f.Sequence,
                SQLBaseType: f.SQLBaseType,
                SQLFullType: f.SQLFullType,
                SourceEntityID: f.SourceEntityID,
                SourceEntity: f.SourceEntity,
                SourceFieldName: f.SourceFieldName,
                IsComputed: f.IsComputed,
                ComputationDescription: f.ComputationDescription,
                IsSummary: f.IsSummary,
                SummaryDescription: f.SummaryDescription
            })),
            Parameters: q.Parameters.map((p) => ({
                ID: p.ID,
                QueryID: p.QueryID,
                Name: p.Name,
                Description: p.Description,
                Type: p.Type,
                IsRequired: p.IsRequired,
                DefaultValue: p.DefaultValue,
                SampleValue: p.SampleValue,
                ValidationFilters: p.ValidationFilters
            })),
            Entities: q.Entities.map((e) => ({
                ID: e.ID,
                QueryID: e.QueryID,
                EntityID: e.EntityID,
                Entity: e.Entity
            })),
            CacheEnabled: q.CacheEnabled,
            CacheMaxSize: q.CacheMaxSize,
            CacheTTLMinutes: q.CacheMaxSize,
            CacheValidationSQL: q.CacheValidationSQL
        }));
    }
    async PackEntityRows(e, dataSource) {
        try {
            if (e.RowsToPackWithSchema === 'None')
                return [];
            const fields = e.Fields.filter((f) => {
                const scopes = f.ScopeDefault?.split(',').map((s) => s.trim().toLowerCase());
                return !scopes || scopes.length === 0 || scopes.includes('all') || scopes.includes('ai');
            }).map(f => `[${f.Name}]`).join(',');
            let sql = '';
            switch (e.RowsToPackWithSchema) {
                case 'All':
                    sql = `SELECT ${fields} FROM ${e.SchemaName}.${e.BaseView}`;
                    break;
                case 'Sample':
                    switch (e.RowsToPackSampleMethod) {
                        case 'random':
                            sql = `SELECT TOP ${e.RowsToPackSampleCount} ${fields} FROM [${e.SchemaName}].[${e.BaseView}] ORDER BY newid()`;
                            break;
                        case 'top n':
                            const orderBy = e.RowsToPackSampleOrder ? ` ORDER BY [${e.RowsToPackSampleOrder}]` : '';
                            sql = `SELECT TOP ${e.RowsToPackSampleCount} ${fields} FROM [${e.SchemaName}].[${e.BaseView}]${orderBy}`;
                            break;
                        case 'bottom n':
                            const firstPrimaryKey = e.FirstPrimaryKey.Name;
                            const innerOrderBy = e.RowsToPackSampleOrder ? `[${e.RowsToPackSampleOrder}]` : `[${firstPrimaryKey}] DESC`;
                            sql = `SELECT * FROM (
                        SELECT TOP ${e.RowsToPackSampleCount} ${fields} 
                        FROM [${e.SchemaName}].[${e.BaseView}]
                        ORDER BY ${innerOrderBy}
                    ) sub
                    ORDER BY [${firstPrimaryKey}] ASC;`;
                            break;
                    }
            }
            const request = new mssql.Request(dataSource);
            const result = await request.query(sql);
            if (!result || !result.recordset) {
                return [];
            }
            else {
                return result.recordset;
            }
        }
        catch (e) {
            LogError(`AskSkipResolver::PackEntityRows: ${e}`);
            return [];
        }
    }
    async PackFieldPossibleValues(f, dataSource) {
        try {
            if (f.ValuesToPackWithSchema === 'None') {
                return [];
            }
            else if (f.ValuesToPackWithSchema === 'All') {
                return await this.GetFieldDistinctValues(f, dataSource);
            }
            else if (f.ValuesToPackWithSchema === 'Auto') {
                if (f.ValueListTypeEnum === 'List') {
                    return f.EntityFieldValues.map((v) => {
                        return { value: v.Value, displayValue: v.Value };
                    });
                }
                else if (f.ValueListTypeEnum === 'ListOrUserEntry') {
                    const values = await this.GetFieldDistinctValues(f, dataSource);
                    if (!values || values.length === 0) {
                        return f.EntityFieldValues.map((v) => {
                            return { value: v.Value, displayValue: v.Value };
                        });
                    }
                    else {
                        return [...new Set([...f.EntityFieldValues.map((v) => {
                                    return { value: v.Value, displayValue: v.Value };
                                }), ...values])];
                    }
                }
            }
            return [];
        }
        catch (e) {
            LogError(`AskSkipResolver::PackFieldPossibleValues: ${e}`);
            return [];
        }
    }
    async GetFieldDistinctValues(f, dataSource) {
        try {
            const sql = `SELECT DISTINCT ${f.Name} FROM ${f.SchemaName}.${f.BaseView}`;
            const request = new mssql.Request(dataSource);
            const result = await request.query(sql);
            if (!result || !result.recordset) {
                return [];
            }
            else {
                return result.recordset.map((r) => {
                    return {
                        value: r[f.Name],
                        displayValue: r[f.Name]
                    };
                });
            }
        }
        catch (e) {
            LogError(`AskSkipResolver::GetFieldDistinctValues: ${e}`);
            return [];
        }
    }
    static __skipEntitiesCache$ = new BehaviorSubject(null);
    static __lastRefreshTime = 0;
    static __refreshInProgress = null;
    async refreshSkipEntities(dataSource) {
        try {
            const md = new Metadata();
            console.log(`[refreshSkipEntities] Total entities in metadata: ${md.Entities.length}`);
            console.log(`[refreshSkipEntities] Config excludeSchemas: ${JSON.stringify(configInfo.askSkip?.entitiesToSend?.excludeSchemas)}`);
            console.log(`[refreshSkipEntities] Config includeEntitiesFromExcludedSchemas: ${JSON.stringify(configInfo.askSkip?.entitiesToSend?.includeEntitiesFromExcludedSchemas)}`);
            const skipSpecialIncludeEntities = (configInfo.askSkip?.entitiesToSend?.includeEntitiesFromExcludedSchemas ?? [])
                .map((e) => e.trim().toLowerCase());
            const entities = md.Entities.filter((e) => {
                if (!configInfo.askSkip.entitiesToSend.excludeSchemas.includes(e.SchemaName) ||
                    skipSpecialIncludeEntities.includes(e.Name.trim().toLowerCase())) {
                    const sd = e.ScopeDefault?.trim();
                    if (sd && sd.length > 0) {
                        const scopes = sd.split(',').map((s) => s.trim().toLowerCase()) ?? ['all'];
                        return !scopes || scopes.length === 0 || scopes.includes('all') || scopes.includes('ai') || skipSpecialIncludeEntities.includes(e.Name.trim().toLowerCase());
                    }
                    else {
                        return true;
                    }
                }
                return false;
            });
            console.log(`[refreshSkipEntities] Filtered entities count: ${entities.length}`);
            if (entities.length === 0) {
                console.warn(`[refreshSkipEntities] WARNING: No entities passed filtering! This will result in empty Skip entities list.`);
            }
            const result = await Promise.all(entities.map((e) => this.PackSingleSkipEntityInfo(e, dataSource)));
            console.log(`[refreshSkipEntities] Successfully packed ${result.length} entities for Skip`);
            AskSkipResolver_1.__lastRefreshTime = Date.now();
            return result;
        }
        catch (e) {
            LogError(`AskSkipResolver::refreshSkipEntities: ${e}`);
            return [];
        }
    }
    async BuildSkipEntities(dataSource, forceRefresh = false, refreshIntervalMinutes = 15) {
        try {
            const now = Date.now();
            const cacheExpired = (now - AskSkipResolver_1.__lastRefreshTime) > (refreshIntervalMinutes * 60 * 1000);
            const cacheIsEmpty = AskSkipResolver_1.__skipEntitiesCache$.value === null;
            console.log(`[BuildSkipEntities] forceRefresh: ${forceRefresh}, cacheExpired: ${cacheExpired}, cacheIsEmpty: ${cacheIsEmpty}`);
            if (forceRefresh || cacheExpired || cacheIsEmpty) {
                if (AskSkipResolver_1.__refreshInProgress) {
                    console.log(`[BuildSkipEntities] Refresh already in progress, waiting for it to complete...`);
                    return await AskSkipResolver_1.__refreshInProgress;
                }
                console.log(`[BuildSkipEntities] Starting new refresh operation...`);
                AskSkipResolver_1.__refreshInProgress = this.refreshSkipEntities(dataSource);
                try {
                    const newData = await AskSkipResolver_1.__refreshInProgress;
                    AskSkipResolver_1.__skipEntitiesCache$.next(newData);
                    console.log(`[BuildSkipEntities] Refresh complete, cached ${newData.length} entities`);
                    return newData;
                }
                finally {
                    AskSkipResolver_1.__refreshInProgress = null;
                }
            }
            const result = AskSkipResolver_1.__skipEntitiesCache$.value || [];
            console.log(`[BuildSkipEntities] Returning ${result.length} entities from cache`);
            return result;
        }
        catch (e) {
            LogError(`AskSkipResolver::BuildSkipEntities: ${e}`);
            return [];
        }
    }
    async PackSingleSkipEntityInfo(e, dataSource) {
        try {
            const ret = {
                id: e.ID,
                name: e.Name,
                schemaName: e.SchemaName,
                baseView: e.BaseView,
                description: e.Description,
                fields: await Promise.all(e.Fields.filter(f => {
                    const scopes = f.ScopeDefault?.split(',').map((s) => s.trim().toLowerCase());
                    return !scopes || scopes.length === 0 || scopes.includes('all') || scopes.includes('ai');
                }).map(f => {
                    return this.PackSingleSkipEntityField(f, dataSource);
                })),
                relatedEntities: e.RelatedEntities.map((r) => {
                    return this.PackSingleSkipEntityRelationship(r);
                }),
                rowsPacked: e.RowsToPackWithSchema,
                rowsSampleMethod: e.RowsToPackSampleMethod,
                rows: await this.PackEntityRows(e, dataSource)
            };
            return ret;
        }
        catch (e) {
            LogError(`AskSkipResolver::PackSingleSkipEntityInfo: ${e}`);
            return null;
        }
    }
    PackSingleSkipEntityRelationship(r) {
        try {
            return {
                entityID: r.EntityID,
                relatedEntityID: r.RelatedEntityID,
                type: r.Type,
                entityKeyField: r.EntityKeyField,
                relatedEntityJoinField: r.RelatedEntityJoinField,
                joinView: r.JoinView,
                joinEntityJoinField: r.JoinEntityJoinField,
                joinEntityInverseJoinField: r.JoinEntityInverseJoinField,
                entity: r.Entity,
                entityBaseView: r.EntityBaseView,
                relatedEntity: r.RelatedEntity,
                relatedEntityBaseView: r.RelatedEntityBaseView,
            };
        }
        catch (e) {
            LogError(`AskSkipResolver::PackSingleSkipEntityRelationship: ${e}`);
            return null;
        }
    }
    async PackSingleSkipEntityField(f, dataSource) {
        try {
            return {
                entityID: f.EntityID,
                sequence: f.Sequence,
                name: f.Name,
                displayName: f.DisplayName,
                category: f.Category,
                type: f.Type,
                description: f.Description,
                isPrimaryKey: f.IsPrimaryKey,
                allowsNull: f.AllowsNull,
                isUnique: f.IsUnique,
                length: f.Length,
                precision: f.Precision,
                scale: f.Scale,
                sqlFullType: f.SQLFullType,
                defaultValue: f.DefaultValue,
                autoIncrement: f.AutoIncrement,
                valueListType: f.ValueListType,
                extendedType: f.ExtendedType,
                defaultInView: f.DefaultInView,
                defaultColumnWidth: f.DefaultColumnWidth,
                isVirtual: f.IsVirtual,
                isNameField: f.IsNameField,
                relatedEntityID: f.RelatedEntityID,
                relatedEntityFieldName: f.RelatedEntityFieldName,
                relatedEntity: f.RelatedEntity,
                relatedEntitySchemaName: f.RelatedEntitySchemaName,
                relatedEntityBaseView: f.RelatedEntityBaseView,
                possibleValues: await this.PackFieldPossibleValues(f, dataSource),
            };
        }
        catch (e) {
            LogError(`AskSkipResolver::PackSingleSkipEntityField: ${e}`);
            return null;
        }
    }
    async HandleSkipChatInitialObjectLoading(dataSource, ConversationId, UserQuestion, user, userPayload, md, DataContextId) {
        const convoEntity = await md.GetEntityObject('Conversations', user);
        let dataContextEntity;
        if (!ConversationId || ConversationId.length === 0) {
            convoEntity.NewRecord();
            if (user) {
                convoEntity.UserID = user.ID;
                convoEntity.Name = AskSkipResolver_1._defaultNewChatName;
                convoEntity.Status = 'Available';
                dataContextEntity = await md.GetEntityObject('Data Contexts', user);
                if (!DataContextId || DataContextId.length === 0) {
                    dataContextEntity.NewRecord();
                    dataContextEntity.UserID = user.ID;
                    dataContextEntity.Name = 'Data Context for Skip Conversation ';
                    if (!(await dataContextEntity.Save())) {
                        LogError(`Creating a new data context failed`, undefined, dataContextEntity.LatestResult);
                        throw new Error(`Creating a new data context failed`);
                    }
                }
                else {
                    const dcLoadResult = await dataContextEntity.Load(DataContextId);
                    if (!dcLoadResult) {
                        throw new Error(`Loading DataContextEntity for DataContextId ${DataContextId} failed`);
                    }
                }
                convoEntity.DataContextID = dataContextEntity.ID;
                if (await convoEntity.Save()) {
                    ConversationId = convoEntity.ID;
                    if (!DataContextId || dataContextEntity.ID.length === 0) {
                        dataContextEntity.Name += ` ${ConversationId}`;
                        const dciSaveResult = await dataContextEntity.Save();
                        if (!dciSaveResult) {
                            LogError(`Error saving DataContextEntity for conversation: ${ConversationId}`, undefined, dataContextEntity.LatestResult);
                        }
                    }
                }
                else {
                    LogError(`Creating a new conversation failed`, undefined, convoEntity.LatestResult);
                    throw new Error(`Creating a new conversation failed`);
                }
            }
            else {
                throw new Error(`User ${userPayload.email} not found in UserCache`);
            }
        }
        else {
            await convoEntity.Load(ConversationId);
            dataContextEntity = await md.GetEntityObject('Data Contexts', user);
            if (DataContextId && DataContextId.length > 0 && DataContextId !== convoEntity.DataContextID) {
                if (convoEntity.DataContextID === null) {
                    convoEntity.DataContextID = DataContextId;
                    const convoEntitySaveResult = await convoEntity.Save();
                    if (!convoEntitySaveResult) {
                        LogError(`Error saving conversation entity for conversation: ${ConversationId}`, undefined, convoEntity.LatestResult);
                    }
                }
                else {
                    console.warn(`AskSkipResolver: DataContextId ${DataContextId} was passed in but it was ignored because it was different than the DataContextID in the conversation ${convoEntity.DataContextID}`);
                }
                if (convoEntity.DataContextID)
                    await dataContextEntity.Load(convoEntity.DataContextID);
            }
            else if ((!DataContextId || DataContextId.length === 0) && (!convoEntity.DataContextID || convoEntity.DataContextID.length === 0)) {
                dataContextEntity.NewRecord();
                dataContextEntity.UserID = user.ID;
                dataContextEntity.Name = 'Data Context for Skip Conversation ' + ConversationId;
                if (await dataContextEntity.Save()) {
                    DataContextId = convoEntity.DataContextID;
                    convoEntity.DataContextID = dataContextEntity.ID;
                    if (!await convoEntity.Save()) {
                        LogError(`Error saving conversation entity for conversation: ${ConversationId}`, undefined, convoEntity.LatestResult);
                    }
                }
                else
                    LogError(`Error saving DataContextEntity for conversation: ${ConversationId}`, undefined, dataContextEntity.LatestResult);
            }
            else {
                await dataContextEntity.Load(convoEntity.DataContextID);
            }
        }
        const convoDetailEntity = await md.GetEntityObject('Conversation Details', user);
        convoDetailEntity.NewRecord();
        convoDetailEntity.ConversationID = ConversationId;
        convoDetailEntity.UserID = user.ID;
        convoDetailEntity.Message = UserQuestion;
        convoDetailEntity.Role = 'User';
        convoDetailEntity.HiddenToUser = false;
        let convoDetailSaveResult = await convoDetailEntity.Save();
        if (!convoDetailSaveResult) {
            LogError(`Error saving conversation detail entity for user message: ${UserQuestion}`, undefined, convoDetailEntity.LatestResult);
        }
        const dataContext = MJGlobal.Instance.ClassFactory.CreateInstance(DataContext);
        await dataContext.Load(dataContextEntity.ID, dataSource, false, false, 0, user);
        return { dataContext, convoEntity, dataContextEntity, convoDetailEntity };
    }
    async LoadConversationDetailsIntoSkipMessages(dataSource, ConversationId, maxHistoricalMessages, roleFilter) {
        try {
            if (!ConversationId || ConversationId.length === 0) {
                throw new Error(`ConversationId is required`);
            }
            const md = new Metadata();
            const e = md.Entities.find((e) => e.Name === 'Conversation Details');
            const roleFilterClause = roleFilter ? ` AND Role = '${roleFilter}'` : '';
            const sql = `SELECT
                      ${maxHistoricalMessages ? 'TOP ' + maxHistoricalMessages : ''} *
                   FROM
                      ${e.SchemaName}.${e.BaseView}
                   WHERE
                      ConversationID = '${ConversationId}'${roleFilterClause}
                   ORDER
                      BY __mj_CreatedAt DESC`;
            const request = new mssql.Request(dataSource);
            const result = await request.query(sql);
            if (!result || !result.recordset)
                throw new Error(`Error running SQL: ${sql}`);
            else {
                const returnData = result.recordset.sort((a, b) => {
                    const aDate = new Date(a.__mj_CreatedAt);
                    const bDate = new Date(b.__mj_CreatedAt);
                    return aDate.getTime() - bDate.getTime();
                });
                return returnData.map((r) => {
                    const skipRole = this.MapDBRoleToSkipRole(r.Role);
                    let outputMessage;
                    if (skipRole === 'system') {
                        let detail;
                        try {
                            detail = JSON.parse(r.Message);
                        }
                        catch (e) {
                            detail = null;
                            outputMessage = r.Message;
                        }
                        if (detail?.responsePhase === SkipResponsePhase.AnalysisComplete) {
                            const analysisDetail = detail;
                            outputMessage = JSON.stringify({
                                responsePhase: SkipResponsePhase.AnalysisComplete,
                                techExplanation: analysisDetail.techExplanation,
                                userExplanation: analysisDetail.userExplanation,
                                executionResults: analysisDetail.executionResults,
                                tableDataColumns: analysisDetail.tableDataColumns,
                                componentOptions: analysisDetail.componentOptions,
                                artifactRequest: analysisDetail.artifactRequest
                            });
                        }
                        else if (detail?.responsePhase === SkipResponsePhase.ClarifyingQuestion) {
                            const clarifyingQuestionDetail = detail;
                            outputMessage = JSON.stringify({
                                responsePhase: SkipResponsePhase.ClarifyingQuestion,
                                clarifyingQuestion: clarifyingQuestionDetail.clarifyingQuestion,
                            });
                        }
                        else if (detail) {
                            LogError(`Unknown response phase: ${detail.responsePhase}`);
                        }
                    }
                    const m = {
                        content: skipRole === 'system' ? outputMessage : r.Message,
                        role: skipRole,
                        conversationDetailID: r.ID,
                        hiddenToUser: r.HiddenToUser,
                        userRating: r.UserRating,
                        userFeedback: r.UserFeedback,
                        reflectionInsights: r.ReflectionInsights,
                        summaryOfEarlierConveration: r.SummaryOfEarlierConversation,
                        createdAt: r.__mj_CreatedAt,
                        updatedAt: r.__mj_UpdatedAt,
                    };
                    return m;
                });
            }
        }
        catch (e) {
            LogError(e);
            throw e;
        }
    }
    MapDBRoleToSkipRole(role) {
        switch (role.trim().toLowerCase()) {
            case 'ai':
            case 'system':
            case 'assistant':
                return 'system';
            default:
                return 'user';
        }
    }
    async HandleSkipChatRequest(input, UserQuestion, user, dataSource, ConversationId, userPayload, pubSub, md, convoEntity, convoDetailEntity, dataContext, dataContextEntity, conversationDetailCount, startTime) {
        const skipConfigInfo = configInfo.askSkip;
        const chatURL = skipConfigInfo.url ? `${skipConfigInfo.url}${SKIP_API_ENDPOINTS.CHAT}` : skipConfigInfo.chatURL;
        LogStatus(`   >>> HandleSkipRequest: Sending request to Skip API: ${chatURL}`);
        if (conversationDetailCount > 10) {
            await this.setConversationStatus(convoEntity, 'Available', userPayload, pubSub);
            pubSub.publish(PUSH_STATUS_UPDATES_TOPIC, {
                message: JSON.stringify({
                    type: 'AskSkip',
                    status: 'Error',
                    conversationID: ConversationId,
                    message: 'Analysis failed to run, please try again later and if this continues, contact your support desk.',
                }),
                sessionId: userPayload.sessionId,
            });
            return {
                Success: false,
                Status: 'Error',
                Result: `Exceeded maximum attempts to answer the question ${UserQuestion}`,
                ResponsePhase: SkipResponsePhase.AnalysisComplete,
                ConversationId: ConversationId,
                UserMessageConversationDetailId: '',
                AIMessageConversationDetailId: '',
            };
        }
        let response;
        try {
            response = await sendPostRequest(chatURL, input, true, this.buildSkipPostHeaders(), (message) => {
                LogStatus(JSON.stringify(message, null, 4));
                if (message.type === 'status_update') {
                    const statusContent = message.value.messages[0].content;
                    activeStreams.updateStatus(ConversationId, statusContent, userPayload.sessionId);
                    const sessionIds = activeStreams.getSessionIds(ConversationId);
                    for (const sessionId of sessionIds) {
                        pubSub.publish(PUSH_STATUS_UPDATES_TOPIC, {
                            message: JSON.stringify({
                                type: 'AskSkip',
                                status: 'OK',
                                conversationID: ConversationId,
                                ResponsePhase: message.value.responsePhase,
                                message: statusContent,
                            }),
                            sessionId: sessionId,
                        });
                    }
                }
            });
        }
        catch (error) {
            await this.setConversationStatus(convoEntity, 'Available', userPayload, pubSub);
            LogError(`Error in HandleSkipChatRequest sendPostRequest: ${error}`);
            pubSub.publish(PUSH_STATUS_UPDATES_TOPIC, {
                message: JSON.stringify({
                    type: 'AskSkip',
                    status: 'Error',
                    conversationID: ConversationId,
                    message: 'Request failed. Please try again later and if this continues, contact your support desk.',
                }),
                sessionId: userPayload.sessionId,
            });
            throw error;
        }
        if (response && response.length > 0) {
            const apiResponse = response[response.length - 1].value;
            LogStatus(`  Skip API response: ${apiResponse.responsePhase}`);
            this.PublishApiResponseUserUpdateMessage(apiResponse, userPayload, ConversationId, pubSub);
            if (apiResponse.responsePhase === 'data_request') {
                return await this.HandleDataRequestPhase(input, apiResponse, UserQuestion, user, dataSource, ConversationId, userPayload, pubSub, convoEntity, convoDetailEntity, dataContext, dataContextEntity, conversationDetailCount, startTime);
            }
            else if (apiResponse.responsePhase === 'clarifying_question') {
                return await this.HandleClarifyingQuestionPhase(input, apiResponse, UserQuestion, user, dataSource, ConversationId, userPayload, pubSub, convoEntity, convoDetailEntity, startTime);
            }
            else if (apiResponse.responsePhase === 'analysis_complete') {
                return await this.HandleAnalysisComplete(input, apiResponse, UserQuestion, user, dataSource, ConversationId, userPayload, pubSub, convoEntity, convoDetailEntity, dataContext, dataContextEntity, startTime);
            }
            else {
                throw new Error(`Unknown Skip API response phase: ${apiResponse.responsePhase}`);
            }
        }
        else {
            await this.setConversationStatus(convoEntity, 'Available', userPayload, pubSub);
            pubSub.publish(PUSH_STATUS_UPDATES_TOPIC, {
                message: JSON.stringify({
                    type: 'AskSkip',
                    status: 'Error',
                    conversationID: ConversationId,
                    message: 'Analysis failed to run, please try again later and if this continues, contact your support desk.',
                }),
                sessionId: userPayload.sessionId,
            });
            return {
                Success: false,
                Status: 'Error',
                Result: `User Question ${UserQuestion} didn't work!`,
                ResponsePhase: SkipResponsePhase.AnalysisComplete,
                ConversationId: ConversationId,
                UserMessageConversationDetailId: '',
                AIMessageConversationDetailId: '',
            };
        }
    }
    buildSkipPostHeaders() {
        return {
            'x-api-key': configInfo.askSkip?.apiKey ?? '',
        };
    }
    async PublishApiResponseUserUpdateMessage(apiResponse, userPayload, conversationID, pubSub) {
        let sUserMessage = '';
        switch (apiResponse.responsePhase) {
            case 'data_request':
                sUserMessage = 'We need to gather some more data, I will do that next and update you soon.';
                break;
            case 'analysis_complete':
                sUserMessage = 'I have completed the analysis, the results will be available momentarily.';
                break;
            case 'clarifying_question':
                break;
        }
        pubSub.publish(PUSH_STATUS_UPDATES_TOPIC, {
            message: JSON.stringify({
                type: 'AskSkip',
                status: 'OK',
                conversationID,
                message: sUserMessage,
            }),
            sessionId: userPayload.sessionId,
        });
    }
    async HandleAnalysisComplete(apiRequest, apiResponse, UserQuestion, user, dataSource, ConversationId, userPayload, pubSub, convoEntity, convoDetailEntity, dataContext, dataContextEntity, startTime) {
        const md = new Metadata();
        if (apiRequest.callingServerAccessToken && tokenExists(apiRequest.callingServerAccessToken)) {
            deleteAccessToken(apiRequest.callingServerAccessToken);
        }
        const { AIMessageConversationDetailID } = await this.FinishConversationAndNotifyUser(apiResponse, dataContext, dataContextEntity, md, user, convoEntity, pubSub, userPayload, dataSource, startTime);
        const response = {
            Success: true,
            Status: 'OK',
            ResponsePhase: SkipResponsePhase.AnalysisComplete,
            ConversationId: ConversationId,
            UserMessageConversationDetailId: convoDetailEntity.ID,
            AIMessageConversationDetailId: AIMessageConversationDetailID,
            Result: JSON.stringify(apiResponse),
        };
        return response;
    }
    async HandleClarifyingQuestionPhase(apiRequest, apiResponse, UserQuestion, user, dataSource, ConversationId, userPayload, pubSub, convoEntity, convoDetailEntity, startTime) {
        const endTime = new Date();
        const md = new Metadata();
        const convoDetailEntityAI = await md.GetEntityObject('Conversation Details', user);
        convoDetailEntityAI.NewRecord();
        convoDetailEntityAI.ConversationID = ConversationId;
        convoDetailEntityAI.Message = JSON.stringify(apiResponse);
        convoDetailEntityAI.Role = 'AI';
        convoDetailEntityAI.HiddenToUser = false;
        convoDetailEntityAI.CompletionTime = endTime.getTime() - startTime.getTime();
        await this.setConversationStatus(convoEntity, 'Available', userPayload, pubSub);
        if (await convoDetailEntityAI.Save()) {
            return {
                Success: true,
                Status: 'OK',
                ResponsePhase: SkipResponsePhase.ClarifyingQuestion,
                ConversationId: ConversationId,
                UserMessageConversationDetailId: convoDetailEntity.ID,
                AIMessageConversationDetailId: convoDetailEntityAI.ID,
                Result: JSON.stringify(apiResponse),
            };
        }
        else {
            LogError(`Error saving conversation detail entity for AI message: ${apiResponse.clarifyingQuestion}`, undefined, convoDetailEntityAI.LatestResult);
            return {
                Success: false,
                Status: 'Error',
                ResponsePhase: SkipResponsePhase.ClarifyingQuestion,
                ConversationId: ConversationId,
                UserMessageConversationDetailId: convoDetailEntity.ID,
                AIMessageConversationDetailId: convoDetailEntityAI.ID,
                Result: JSON.stringify(apiResponse),
            };
        }
    }
    async HandleDataRequestPhase(apiRequest, apiResponse, UserQuestion, user, dataSource, ConversationId, userPayload, pubSub, convoEntity, convoDetailEntity, dataContext, dataContextEntity, conversationDetailCount, startTime) {
        try {
            if (!apiResponse.success) {
                LogError(`Data request/gathering from Skip API failed: ${apiResponse.error}`);
                return {
                    Success: false,
                    Status: `The Skip API Server data gathering phase returned a non-recoverable error. Try again later and Skip might be able to handle this request.\n${apiResponse.error}`,
                    ResponsePhase: SkipResponsePhase.DataRequest,
                    ConversationId: ConversationId,
                    UserMessageConversationDetailId: convoDetailEntity.ID,
                    AIMessageConversationDetailId: '',
                    Result: JSON.stringify(apiResponse),
                };
            }
            const _maxDataGatheringRetries = 5;
            const _dataGatheringFailureHeaderMessage = '***DATA GATHERING FAILURE***';
            const md = new Metadata();
            const executionErrors = [];
            let dataRequest = apiResponse.dataRequest;
            apiRequest.messages.push({
                content: `Skip API Requested Data as shown below
                  ${JSON.stringify(apiResponse.dataRequest)}`,
                role: 'system',
                conversationDetailID: convoDetailEntity.ID,
            });
            if (!Array.isArray(dataRequest)) {
                if (dataRequest) {
                    dataRequest = [dataRequest];
                }
                else {
                    const errorMessage = `Data request from Skip API is not an array and not a single item.`;
                    LogError(errorMessage);
                    executionErrors.push({ dataRequest: apiResponse.dataRequest, errorMessage: errorMessage });
                    dataRequest = [];
                }
            }
            for (const dr of dataRequest) {
                try {
                    const item = dataContext.AddDataContextItem();
                    switch (dr.type) {
                        case 'sql':
                            item.Type = 'sql';
                            item.SQL = dr.text;
                            item.AdditionalDescription = dr.description;
                            item.CodeName = dr.codeName;
                            if (!(await item.LoadData(dataSource, false, false, 0, user)))
                                throw new Error(`SQL data request failed: ${item.DataLoadingError}`);
                            break;
                        case 'stored_query':
                            const queryName = dr.text;
                            const query = md.Queries.find((q) => q.Name === queryName);
                            if (query) {
                                item.Type = 'query';
                                item.QueryID = query.ID;
                                item.RecordName = query.Name;
                                item.AdditionalDescription = dr.description;
                                if (!(await item.LoadData(dataSource, false, false, 0, user)))
                                    throw new Error(`SQL data request failed: ${item.DataLoadingError}`);
                            }
                            else
                                throw new Error(`Query ${queryName} not found.`);
                            break;
                        default:
                            throw new Error(`Unknown data request type: ${dr.type}`);
                            break;
                    }
                }
                catch (e) {
                    LogError(e);
                    executionErrors.push({
                        dataRequest: dr,
                        errorMessage: e && typeof e === 'object' && 'message' in e && e.message ? e.message : e.toString(),
                    });
                }
            }
            if (executionErrors.length > 0) {
                const dataGatheringFailedAttemptCount = apiRequest.messages.filter((m) => m.content.includes(_dataGatheringFailureHeaderMessage)).length + 1;
                if (dataGatheringFailedAttemptCount > _maxDataGatheringRetries) {
                    LogStatus(`Execution errors for Skip data request occured, and we have exceeded the max retries${_maxDataGatheringRetries}, sending errors back to the user.`);
                    return {
                        Success: false,
                        Status: 'Error gathering data and we have exceedded the max retries. Try again later and Skip might be able to handle this request.',
                        ResponsePhase: SkipResponsePhase.DataRequest,
                        ConversationId: ConversationId,
                        UserMessageConversationDetailId: convoDetailEntity.ID,
                        AIMessageConversationDetailId: '',
                        Result: JSON.stringify(apiResponse),
                    };
                }
                else {
                    LogStatus(`Execution errors for Skip data request occured, sending those errors back to the Skip API to get new instructions.`);
                    apiRequest.requestPhase = 'data_gathering_failure';
                    apiRequest.messages.push({
                        content: `${_dataGatheringFailureHeaderMessage} #${dataGatheringFailedAttemptCount} of ${_maxDataGatheringRetries} attempts to gather data failed. Errors:
                      ${JSON.stringify(executionErrors)}
                    `,
                        role: 'user',
                        conversationDetailID: convoDetailEntity.ID,
                    });
                }
            }
            else {
                await dataContext.SaveItems(user, false);
                apiRequest.dataContext = CopyScalarsAndArrays(dataContext);
                apiRequest.requestPhase = 'data_gathering_response';
            }
            conversationDetailCount++;
            return this.HandleSkipChatRequest(apiRequest, UserQuestion, user, dataSource, ConversationId, userPayload, pubSub, md, convoEntity, convoDetailEntity, dataContext, dataContextEntity, conversationDetailCount, startTime);
        }
        catch (e) {
            LogError(e);
            throw e;
        }
    }
    async FinishConversationAndNotifyUser(apiResponse, dataContext, dataContextEntity, md, user, convoEntity, pubSub, userPayload, dataSource, startTime) {
        const sTitle = apiResponse.title || apiResponse.reportTitle;
        const sResult = JSON.stringify(apiResponse);
        let artifactId = null;
        let artifactVersionId = null;
        if (apiResponse.artifactRequest?.action === 'new_artifact' || apiResponse.artifactRequest?.action === 'new_artifact_version') {
            artifactId = apiResponse.artifactRequest.artifactId;
            let newVersion = 0;
            if (apiResponse.artifactRequest?.action === 'new_artifact') {
                const artifactEntity = await md.GetEntityObject('MJ: Conversation Artifacts', user);
                artifactEntity.NewRecord();
                artifactEntity.ConversationID = convoEntity.ID;
                artifactEntity.Name = apiResponse.artifactRequest.name;
                artifactEntity.Description = apiResponse.artifactRequest.description;
                await AIEngine.Instance.Config(false, user);
                artifactEntity.ArtifactTypeID = AIEngine.Instance.ArtifactTypes.find((t) => t.Name === 'Report')?.ID;
                artifactEntity.SharingScope = 'None';
                if (await artifactEntity.Save()) {
                    artifactId = artifactEntity.ID;
                }
                else {
                    LogError(`Error saving artifact entity for conversation: ${convoEntity.ID}`, undefined, artifactEntity.LatestResult);
                }
                newVersion = 1;
            }
            else {
                const ei = md.EntityByName("MJ: Conversation Artifact Versions");
                const sSQL = `SELECT ISNULL(MAX(Version),0) AS MaxVersion FROM [${ei.SchemaName}].[${ei.BaseView}] WHERE ConversationArtifactID = '${artifactId}'`;
                try {
                    const request = new mssql.Request(dataSource);
                    const result = await request.query(sSQL);
                    if (result && result.recordset && result.recordset.length > 0) {
                        newVersion = result.recordset[0].MaxVersion + 1;
                    }
                    else {
                        LogError(`Error getting max version for artifact ID: ${artifactId}`, undefined, result);
                    }
                }
                catch (e) {
                    LogError(`Error getting max version for artifact ID: ${artifactId}`, undefined, e);
                }
            }
            if (artifactId && newVersion > 0) {
                const artifactVersionEntity = await md.GetEntityObject('MJ: Conversation Artifact Versions', user);
                artifactVersionEntity.NewRecord();
                artifactVersionEntity.ConversationArtifactID = artifactId;
                artifactVersionEntity.Version = newVersion;
                artifactVersionEntity.Configuration = sResult;
                if (await artifactVersionEntity.Save()) {
                    artifactVersionId = artifactVersionEntity.ID;
                }
                else {
                    LogError(`Error saving Artifact Version record`);
                }
            }
        }
        const endTime = new Date();
        const convoDetailEntityAI = await md.GetEntityObject('Conversation Details', user);
        convoDetailEntityAI.NewRecord();
        convoDetailEntityAI.ConversationID = convoEntity.ID;
        convoDetailEntityAI.Message = sResult;
        convoDetailEntityAI.Role = 'AI';
        convoDetailEntityAI.HiddenToUser = false;
        convoDetailEntityAI.CompletionTime = endTime.getTime() - startTime.getTime();
        if (artifactId && artifactId.length > 0) {
            convoDetailEntityAI.ArtifactID = artifactId;
            if (artifactVersionId && artifactVersionId.length > 0) {
                convoDetailEntityAI.ArtifactVersionID = artifactVersionId;
            }
        }
        const convoDetailSaveResult = await convoDetailEntityAI.Save();
        if (!convoDetailSaveResult) {
            LogError(`Error saving conversation detail entity for AI message: ${sResult}`, undefined, convoDetailEntityAI.LatestResult);
        }
        let needToSaveConvo = false;
        if (convoEntity.Name === AskSkipResolver_1._defaultNewChatName && sTitle && sTitle !== AskSkipResolver_1._defaultNewChatName) {
            convoEntity.Name = sTitle;
            needToSaveConvo = true;
        }
        if (convoEntity.Status === 'Processing') {
            convoEntity.Status = 'Available';
            needToSaveConvo = true;
        }
        if (needToSaveConvo) {
            const convoEntitySaveResult = await convoEntity.Save();
            if (!convoEntitySaveResult) {
                LogError(`Error saving conversation entity for AI message: ${sResult}`, undefined, convoEntity.LatestResult);
            }
        }
        const userNotification = await md.GetEntityObject('User Notifications', user);
        userNotification.NewRecord();
        userNotification.UserID = user.ID;
        userNotification.Title = 'Report Created: ' + sTitle;
        userNotification.Message = `Good news! Skip finished creating a report for you, click on this notification to jump back into the conversation.`;
        userNotification.Unread = true;
        userNotification.ResourceConfiguration = JSON.stringify({
            type: 'askskip',
            conversationId: convoEntity.ID,
        });
        const userNotificationSaveResult = await userNotification.Save();
        if (!userNotificationSaveResult) {
            LogError(`Error saving user notification entity for AI message: ${sResult}`, undefined, userNotification.LatestResult);
        }
        if (apiResponse.newDataItems) {
            apiResponse.newDataItems.forEach((skipItem) => {
                const newItem = dataContext.AddDataContextItem();
                newItem.Type = 'sql';
                newItem.SQL = skipItem.text;
                newItem.AdditionalDescription = skipItem.description;
            });
        }
        await dataContext.SaveItems(user, false);
        pubSub.publish(PUSH_STATUS_UPDATES_TOPIC, {
            message: JSON.stringify({
                type: 'UserNotifications',
                status: 'OK',
                conversationID: convoEntity.ID,
                details: {
                    action: 'create',
                    recordId: userNotification.ID,
                },
            }),
            sessionId: userPayload.sessionId,
        });
        return {
            AIMessageConversationDetailID: convoDetailEntityAI.ID,
        };
    }
    async setConversationStatus(convoEntity, status, userPayload, pubSub) {
        if (convoEntity.Status !== status) {
            convoEntity.Status = status;
            const convoSaveResult = await convoEntity.Save();
            if (!convoSaveResult) {
                LogError(`Error updating conversation status to '${status}'`, undefined, convoEntity.LatestResult);
            }
            else {
                if (status === 'Available') {
                    activeStreams.removeConversation(convoEntity.ID);
                    LogStatus(`Removed conversation ${convoEntity.ID} from active streams (status changed to Available)`);
                }
                else if (status === 'Processing') {
                    activeStreams.addSession(convoEntity.ID, userPayload.sessionId);
                    LogStatus(`Added session ${userPayload.sessionId} to active streams for conversation ${convoEntity.ID}`);
                }
                if (pubSub) {
                    const statusMessage = {
                        type: 'ConversationStatusUpdate',
                        conversationID: convoEntity.ID,
                        status: status,
                        timestamp: new Date().toISOString()
                    };
                    pubSub.publish(PUSH_STATUS_UPDATES_TOPIC, {
                        pushStatusUpdates: {
                            message: JSON.stringify(statusMessage),
                            sessionId: userPayload.sessionId
                        }
                    });
                    LogStatus(`Published conversation status update for ${convoEntity.ID}: ${status}`);
                }
            }
            return convoSaveResult;
        }
        return true;
    }
    getAgentNoteTypeIDByName(name, defaultNoteType = 'AI') {
        const noteTypeID = AIEngine.Instance.AgentNoteTypes.find(nt => nt.Name.trim().toLowerCase() === name.trim().toLowerCase())?.ID;
        if (noteTypeID) {
            return noteTypeID;
        }
        else {
            const defaultNoteTypeID = AIEngine.Instance.AgentNoteTypes.find(nt => nt.Name.trim().toLowerCase() === defaultNoteType.trim().toLowerCase())?.ID;
            return defaultNoteTypeID;
        }
    }
    async getViewData(ViewId, user) {
        const rv = new RunView();
        const result = await rv.RunView({ ViewID: ViewId, IgnoreMaxRows: true }, user);
        if (result && result.Success)
            return result.Results;
        else
            throw new Error(`Error running view ${ViewId}`);
    }
};
__decorate([
    Query(() => AskSkipResultType),
    __param(0, Arg('UserQuestion', () => String)),
    __param(1, Arg('ConversationId', () => String)),
    __param(2, Arg('EntityName', () => String)),
    __param(3, Arg('CompositeKey', () => CompositeKeyInputType)),
    __param(4, Ctx()),
    __param(5, PubSub()),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String, String, String, CompositeKeyInputType, Object, PubSubEngine]),
    __metadata("design:returntype", Promise)
], AskSkipResolver.prototype, "ExecuteAskSkipRecordChat", null);
__decorate([
    Query(() => AskSkipResultType),
    __param(0, Ctx()),
    __param(1, PubSub()),
    __param(2, Arg('DataContextId', () => String)),
    __param(3, Arg('ScriptText', () => String)),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object, PubSubEngine, String, String]),
    __metadata("design:returntype", Promise)
], AskSkipResolver.prototype, "ExecuteAskSkipRunScript", null);
__decorate([
    Query(() => ReattachConversationResponse),
    __param(0, Arg('ConversationId', () => String)),
    __param(1, Ctx()),
    __param(2, PubSub()),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String, Object, PubSubEngine]),
    __metadata("design:returntype", Promise)
], AskSkipResolver.prototype, "ReattachToProcessingConversation", null);
__decorate([
    Query(() => AskSkipResultType),
    __param(0, Arg('UserQuestion', () => String)),
    __param(1, Arg('ConversationId', () => String)),
    __param(2, Ctx()),
    __param(3, PubSub()),
    __param(4, Arg('DataContextId', () => String, { nullable: true })),
    __param(5, Arg('ForceEntityRefresh', () => Boolean, { nullable: true })),
    __param(6, Arg('StartTime', () => Date, { nullable: true })),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [String, String, Object, PubSubEngine, String, Boolean, Date]),
    __metadata("design:returntype", Promise)
], AskSkipResolver.prototype, "ExecuteAskSkipAnalysisQuery", null);
AskSkipResolver = AskSkipResolver_1 = __decorate([
    Resolver(AskSkipResultType)
], AskSkipResolver);
export { AskSkipResolver };
export default AskSkipResolver;
//# sourceMappingURL=AskSkipResolver.js.map