import { download, getSystemConfig, login, logout, oauth, runPixel, runPixelAsync, upload, uploadApp, uploadEngine, uploadInsight, } from "../../api"; import { Env } from "../../env"; import type { MCPToolResponse, Script } from "../../types"; import { UnauthorizedError } from "../../utility"; interface InsightStoreInterface { /** insightId of the app */ insightId: string; /** Track if the insight is loaded */ isInitialized: boolean; /** Track if the user is authorized */ isAuthorized: boolean; /** Track if the insight is ready for user input */ isReady: boolean; /** Error if in the error state */ error: Error | null; /** System Information */ system: { /** Config information */ config: { logins: Record; /** * List of available providers (logins) that are available */ availableProviders: { provider: string; name: string; isOauth: boolean; }[]; /** * Theme of the app */ theme: { [key: string]: unknown; THEME_MAP?: string; THEME_NAME?: string; ID?: string; IS_ACTIVE?: boolean; }; /** * System Date */ systemDate: string; [key: string]: unknown; }; } | null; /** User meta data */ meta: Record; /** Options assocaited with the insight */ options: { /** Id of an app if associated with the insight */ appId: string; /** Python code associated with the insight */ python: Script | null; /** Whether to disable connecting the insight to a room */ disableRoom: boolean; }; } export class InsightStore { private _store: InsightStoreInterface = { insightId: "new", isInitialized: false, isAuthorized: false, isReady: false, error: null, system: null, meta: {}, options: { appId: "", python: null, disableRoom: false, }, }; /** Getters */ /** * Insight Id */ get insightId() { return this._store.insightId; } /** * If the insight is initialied */ get isInitialized() { return this._store.isInitialized; } /** * If the user is authorized */ get isAuthorized() { return this._store.isAuthorized; } /** * Track if the insight is ready for user input */ get isReady() { return this._store.isReady; } /** * Error if the status is set to "ERROR" */ get error() { return this._store.error; } /** * System information */ get system() { return this._store.system; } /** * Update user meta with a model selection * @param modelName - The model name (e.g., "text-generation-model", "code-generation-model") * @param modelId - The model ID to set */ updateUserDefaultModel(modelName: string, modelId: string): void { this._store.meta = { ...this._store.meta, [modelName]: modelId, }; } /** * Get the default Text Generation model ID (UUID) from user meta */ get defaultTextGenerationModel(): string { const meta = this._store.meta; if (meta && typeof meta === "object") { const tg = meta["text-generation-model"]; if (tg) { return typeof tg === "string" ? tg : ""; } } return ""; } /** * Get the default Code Generation model ID (UUID) from user meta */ get defaultCodeGenerationModel(): string { const meta = this._store.meta; if (meta && typeof meta === "object") { const tg = meta["code-generation-model"]; if (tg) { return typeof tg === "string" ? tg : ""; } } return ""; } /** * Set the user meta with a full meta record * @param meta - full meta record to store */ setUserDefaultModel(meta: Record): void { this._store.meta = { ...meta }; } /** Methods */ /** * Initialize the insight * * options - options to initialize with */ initialize = async (options?: { /** * App to load into the insight */ app?: string | false; /** * Python file to load into an insight */ python?: | { type: "file"; path: string; alias: string; } | { type: "script"; script: string; alias: string; } | false; /** * Whether to disable connecting the insight to a room * Defaults to false */ disableRoom?: boolean; /** * Connect this insight to an existing insight ID */ insightId?: string; }): Promise<{ tool: (typeof Env)["TOOL"] | null; }> => { // reset it this._store.isInitialized = false; this._store.isAuthorized = false; this._store.isReady = false; const merged: NonNullable = { app: options?.app || "", python: options && typeof options.python !== "undefined" ? options.python : false, disableRoom: options?.disableRoom || false, insightId: options?.insightId || "", }; // set the insight this._store.insightId = ""; if (merged.insightId) { this._store.insightId = merged.insightId; } // save the initial appId this._store.options.appId = ""; if (merged.app) { this._store.options.appId = merged.app; } // save the python this._store.options.python = null; if (merged.python) { if (merged.python.type === "file") { this._store.options.python = await this.loadScript( merged.python, ); } else if (merged.python.type === "script") { this._store.options.python = { script: merged.python.script, alias: merged.python.alias, }; } } // save the disable room option this._store.options.disableRoom = merged.disableRoom || false; // load the environment from the document (production) try { if (typeof document !== "undefined") { const env = JSON.parse( document.getElementById("semoss-env")?.textContent || "", ) as { APP: string; MODULE: string; }; // update the enviornment variables with the module if (env) { Env.update({ APP: env.APP, MODULE: env.MODULE, }); } } } catch (_e) { // noop } try { // reset the id based on the Environment if set if (Env.APP) { this._store.options.appId = Env.APP; } // validate that the module is available if (!Env.MODULE) { throw new Error("module is required"); } // get the system information await this.setupSystem(); // break if no system if (!this._store.isInitialized) { throw new Error("Error loading system"); } // if security is not enabled or the user is logged in, load the app if ( (this._store.system && Object.keys(this._store.system.config.logins).length > 0) || (Env.ACCESS_KEY && Env.SECRET_KEY) ) { // track that the user is authorized this._store.isAuthorized = true; // setup the insight await this.setupInsight(); // return the tool (if set) return { tool: Env.TOOL, }; } else { // track that the user is unauthorized this._store.isAuthorized = false; } } catch (error) { // log it console.warn(error); // store the error this._store.error = error as Error; } return null; }; /** * Destroy the insight */ destroy = async () => { try { // destroy the insight await this.destroyInsight(); // destroy the system this.destroySystem(); } catch (error) { // log it console.warn(error); // store the error this._store.error = error as Error; } finally { // reset it this._store.isInitialized = false; this._store.isAuthorized = false; this._store.isReady = false; } }; /** Helpers */ /** * Initialize the system wide information */ private setupSystem = async (): Promise => { // reset it this._store.isInitialized = false; // get the response const data = await getSystemConfig(); let system: InsightStoreInterface["system"] = null; if (data) { // create the system system = { config: { logins: {}, availableProviders: [], theme: { playground: {}, }, systemDate: "", }, }; // save the other config data for (const key in data) { system.config[key] = data[key]; } } this._store.system = system; if (this._store.system) { this._store.isInitialized = true; } else { this._store.isInitialized = false; } }; /** * Initialize the system wide information */ private destroySystem = () => { // clear the system this._store.system = null; }; /** * Setup the insight after login */ private setupInsight = async (): Promise => { // set as not ready this._store.isReady = false; // load the app reactors (if they exist) let pixel = ""; if (this._store.options.appId) { pixel += `SetContext("${this._store.options.appId}");`; } // load the python code int if (this._store.options.python?.script) { // validate the alias let alias = this._store.options.python.alias; if (!alias) { alias = "smss"; console.warn(`Alias not found. Loading python as ${alias}`); } pixel += ` WriteObjectToFile(value="${this._store.options.python.script}", filePath = "temp.py"); LoadPyFromFile(alias="${alias}", filePath="temp.py"); `; } // default if there is no command to preload if (!pixel) { pixel = "META | init"; } // create the new insight const { insightId, errors } = await runPixel<[Record]>( pixel, this._store.insightId, ); // log errors if it exists if (errors.length) { throw new Error(errors[0]); } // set the insight ID this._store.insightId = insightId; // point the insight space toward the room if (Env?.TOOL?.roomId && !this._store.options.disableRoom) { await runPixel<[boolean]>( `SetRoomForInsight(roomId=${JSON.stringify(Env.TOOL.roomId)});`, insightId, ); } // set as ready this._store.isReady = true; }; /** * Destroy the insight */ private destroyInsight = async (): Promise => { if (!this._store.insightId) { return; } const { errors } = await runPixel<[Record]>( `DropInsight()`, this._store.insightId, ); // log errors if it exists if (errors.length) { throw new Error(errors[0]); } // set the insight ID this._store.insightId = ""; }; /** * Process and error in action * @param error - error to process */ private processActionError = (error: Error) => { // ignore 302 errors if (error instanceof UnauthorizedError) { this._store.isAuthorized = false; return; } // propagate it forward throw error; }; /** * Load an external script */ private loadScript = async (config: { path: string; alias: string; }): Promise