import { createApp, ref } from 'vue' import { createStore } from 'vuex' import axios from "axios"; import App from './App.vue' import router from './router' import './assets/tailwind.css' const app = createApp(App) console.log("Loaded main.js") function copyObject(obj) { const copy = {}; for (const key in obj) { if (obj.hasOwnProperty(key)) { copy[key] = obj[key]; } } return copy; } // Create a new store instance. export const store = createStore({ state () { return { personality_editor:null, showPersonalityEditor: false, selectedPersonality:null, currentPersonConfig: { ai_name: '', ai_author: '', ai_category: '', ai_language: '', ai_description: '', ai_conditionning: '', ai_disclaimer: '', ai_icon: null, }, // count: 0, yesNoDialog:null, universalForm:null, toast:null, messageBox:null, api_get_req:null, startSpeechRecognition:null, ready:false, loading_infos: "", loading_progress: 0, version : "unknown", settingsChanged:false, isConnected: false, // Add the isConnected property isModelOk: false, isGenerating: false, config:null, mountedPers:null, mountedPersArr:[], mountedExtensions:[], bindingsZoo:[], modelsArr:[], selectedModel:null, personalities:[], diskUsage:null, ramUsage:null, vramUsage:null, modelsZoo:[], installedModels:[], currentModel:null, extensionsZoo:[], databases:[], } }, mutations: { setIsReady(state, ready) { state.ready = ready; }, setIsConnected(state, isConnected) { state.isConnected = isConnected; }, setIsModelOk(state, isModelOk) { state.isModelOk = isModelOk; }, setIsGenerating(state, isGenerating) { state.isGenerating = isGenerating; }, setConfig(state, config) { state.config = config; }, setPersonalities(state, personalities) { state.personalities = personalities; }, setMountedPers(state, mountedPers) { state.mountedPers = mountedPers; }, setMountedPersArr(state, mountedPersArr) { state.mountedPersArr = mountedPersArr; }, setMountedExtensions(state, mountedExtensions) { state.mountedExtensions = mountedExtensions; }, setbindingsZoo(state, bindingsZoo) { state.bindingsZoo = bindingsZoo; }, setModelsArr(state, modelsArr) { state.modelsArr = modelsArr; }, setselectedModel(state, selectedModel) { state.selectedModel = selectedModel; }, setDiskUsage(state, diskUsage) { state.diskUsage = diskUsage; }, setRamUsage(state, ramUsage) { state.ramUsage = ramUsage; }, setVramUsage(state, vramUsage) { state.vramUsage = vramUsage; }, setModelsZoo(state, modelsZoo) { state.modelsZoo = modelsZoo; }, setCurrentModel(state, currentModel) { state.currentModel = currentModel; }, setExtensionsZoo(state, extensionsZoo) { state.extensionsZoo = extensionsZoo; }, setDatabases(state, databases) { state.databases = databases; }, // increment (state) { // state.count++ // } }, getters: { getIsConnected(state) { return state.isConnected }, getIsModelOk(state) { return state.isModelOk; }, getIsGenerating(state) { return state.isGenerating }, getConfig(state) { return state.config }, getPersonalities(state) { return state.personalities; }, getMountedPersArr(state) { return state.mountedPersArr; }, getmmountedExtensions(state) { return state.mountedExtensions; }, getMountedPers(state) { return state.mountedPers; }, getbindingsZoo(state) { return state.bindingsZoo; }, getModelsArr(state) { return state.modelsArr; }, getDiskUsage(state) { return state.diskUsage; }, getRamUsage(state) { return state.ramUsage; }, getVramUsage(state) { return state.vramUsage; }, getDatabasesList(state){ return state.databases; }, getModelsZoo(state) { return state.modelsZoo; }, getCurrentModel(state) { return state.currentModel; }, getExtensionsZoo(state) { return state.extensionsZoo; }, }, actions: { async getVersion(){ try{ let res = await axios.get('/get_lollms_webui_version', {}); if (res) { this.state.version = res.data.version } } catch{ console.log("Coudln't get version") } }, async refreshConfig({ commit }) { console.log("Fetching configuration"); try { const configFile = await api_get_req('get_config') if(configFile.active_personality_id<0){ configFile.active_personality_id=0; } let personality_path_infos = configFile.personalities[configFile.active_personality_id].split("/") //let personality_path_infos = await this.api_get_req("get_current_personality_path_infos") configFile.personality_category = personality_path_infos[0] configFile.personality_folder = personality_path_infos[1] if (configFile.extensions.length>0){ configFile.extension_category = configFile.extensions[-1] } else{ configFile.extension_category = "ai_sensors" } console.log("Recovered config") console.log(configFile) console.log("Committing config"); console.log(configFile) console.log(this.state.config) commit('setConfig', configFile); } catch (error) { console.log(error.message, 'refreshConfig'); // Handle error } }, async refreshDatabase({ commit }) { let databases = await api_get_req("list_databases") console.log("databases:",databases) commit('setDatabases', databases); }, async refreshPersonalitiesZoo({ commit }) { let personalities = [] const catdictionary = await api_get_req("get_all_personalities") const catkeys = Object.keys(catdictionary); // returns categories console.log("Personalities recovered:"+this.state.config.personalities) for (let j = 0; j < catkeys.length; j++) { const catkey = catkeys[j]; const personalitiesArray = catdictionary[catkey]; const modPersArr = personalitiesArray.map((item) => { let isMounted = false; for(const personality of this.state.config.personalities){ if(personality.includes(catkey + '/' + item.folder)){ isMounted = true; if(personality.includes(":")){ const parts = personality.split(':'); item.language = parts[1]; } else{ item.language = null } } } // if (isMounted) { // console.log(item) // } let newItem = {} newItem = item newItem.category = catkey // add new props to items newItem.full_path = catkey + '/' + item.folder // add new props to items newItem.isMounted = isMounted // add new props to items return newItem }) if (personalities.length == 0) { personalities = modPersArr } else { personalities = personalities.concat(modPersArr) } } personalities.sort((a, b) => a.name.localeCompare(b.name)) commit('setPersonalities', personalities); console.log("Done loading personalities") }, refreshMountedPersonalities({ commit }) { if(this.state.config.active_personality_id<0){ this.state.config.active_personality_id=0; } let mountedPersArr = [] // console.log('perrs listo',this.state.personalities) const indicesToRemove = []; for (let i = 0; i < this.state.config.personalities.length; i++) { const full_path_item = this.state.config.personalities[i] const parts = full_path_item.split(':') const index = this.state.personalities.findIndex(item => item.full_path == full_path_item || item.full_path == parts[0]) if(index>=0){ let pers = copyObject(this.state.personalities[index]) if(parts.length>1){ pers.language = parts[1] } // console.log(`Personality : ${JSON.stringify(pers)}`) if (pers) { mountedPersArr.push(pers) } else { mountedPersArr.push(this.state.personalities[this.state.personalities.findIndex(item => item.full_path == "generic/lollms")]) } } else{ indicesToRemove.push(i) console.log("Couldn't load personality : ",full_path_item) } } // Remove the broken personalities using the collected indices for (let i = indicesToRemove.length - 1; i >= 0; i--) { console.log("Removing personality : ",this.state.config.personalities[indicesToRemove[i]]) this.state.config.personalities.splice(indicesToRemove[i], 1); if(this.state.config.active_personality_id>indicesToRemove[i]){ this.state.config.active_personality_id -= 1; } } commit('setMountedPersArr', mountedPersArr); this.state.mountedPers = this.state.personalities[this.state.personalities.findIndex(item => item.full_path == this.state.config.personalities[this.state.config.active_personality_id] || item.full_path+':'+item.language ==this.state.config.personalities[this.state.config.active_personality_id])] // console.log(`${this.state.config.personalities[this.state.config.active_personality_id]}`) // console.log(`Mounted personality: ${this.state.mountedPers}`) }, async refreshBindings({ commit }) { let bindingsZoo = await api_get_req("list_bindings") commit('setbindingsZoo',bindingsZoo) }, async refreshModelsZoo({ commit }) { console.log("Fetching models") const response = await axios.get('/get_available_models'); commit('setModelsZoo',response.data.filter(model => model.variants && model.variants.length>0)) }, async refreshModelStatus({ commit }) { let modelstatus = await api_get_req("get_model_status"); commit('setIsModelOk',modelstatus["status"]) }, async refreshModels({ commit }) { console.log("Fetching models") let modelsArr = await api_get_req("list_models"); console.log(`Found ${modelsArr}`) let selectedModel = await api_get_req('get_active_model'); console.log("Selected model ", selectedModel); if(selectedModel!=undefined){ commit('setselectedModel',selectedModel["model"]) } commit('setModelsArr',modelsArr) console.log("setModelsArr",modelsArr) this.state.modelsZoo.map((item)=>{ item.isInstalled=modelsArr.includes(item.name) }) this.state.installedModels = this.state.modelsZoo.filter(item=> item.isInstalled) const index = this.state.modelsZoo.findIndex(item=>item.name == this.state.config.model_name) if (index!=-1){ commit('setCurrentModel',this.state.modelsZoo[index]) } }, async refreshExtensionsZoo({ commit }) { let extensions = [] let catdictionary = await api_get_req("list_extensions") const catkeys = Object.keys(catdictionary); // returns categories console.log("Extensions recovered:"+catdictionary) for (let j = 0; j < catkeys.length; j++) { const catkey = catkeys[j]; const extensionsArray = catdictionary[catkey]; const modExtArr = extensionsArray.map((item) => { let isMounted = false; for(const extension of this.state.config.extensions){ if(extension.includes(catkey + '/' + item.folder)){ isMounted = true; } } // if (isMounted) { // console.log(item) // } let newItem = {} newItem = item newItem.category = catkey // add new props to items newItem.full_path = catkey + '/' + item.folder // add new props to items newItem.isMounted = isMounted // add new props to items return newItem }) if (extensions.length == 0) { extensions = modExtArr } else { extensions = extensions.concat(modExtArr) } } extensions.sort((a, b) => a.name.localeCompare(b.name)) //commit('setActiveExtensions', this.state.config.extensions); console.log("Done loading extensions") commit('setExtensionsZoo',extensions) }, refreshmountedExtensions({ commit }) { console.log("Mounting extensions") let mountedExtensions = [] // console.log('perrs listo',this.state.personalities) const indicesToRemove = []; for (let i = 0; i < this.state.config.extensions.length; i++) { const full_path_item = this.state.config.extensions[i] const index = this.state.extensionsZoo.findIndex(item => item.full_path == full_path_item) if(index>=0){ let ext = copyObject(this.state.config.extensions[index]) if (ext) { mountedExtensions.push(ext) } } else{ indicesToRemove.push(i) console.log("Couldn't load extension : ",full_path_item) } } // Remove the broken extensions using the collected indices for (let i = indicesToRemove.length - 1; i >= 0; i--) { console.log("Removing extensions : ",this.state.config.extensions[indicesToRemove[i]]) this.state.config.extensions.splice(indicesToRemove[i], 1); } commit('setMountedExtensions', mountedExtensions); }, async refreshDiskUsage({ commit }) { this.state.diskUsage = await api_get_req("disk_usage") }, async refreshRamUsage({ commit }) { this.state.ramUsage = await api_get_req("ram_usage") }, async refreshVramUsage({ commit }) { const resp = await api_get_req("vram_usage") const gpuArr = [] if (resp.nb_gpus > 0) { // Get keys const keys = Object.keys(resp) // for each gpu for (let i = 0; i < resp.nb_gpus; i++) { const total_vram = resp[`gpu_${i}_total_vram`]; const used_vram = resp[`gpu_${i}_used_vram`]; const model = resp[`gpu_${i}_model`]; const percentage = (used_vram / total_vram) * 100 const available_space = total_vram - used_vram gpuArr.push({ total_vram: total_vram, used_vram: used_vram, gpu_index: i, gpu_model: model, percentage: percentage.toFixed(2), available_space: available_space }); } const result = { "nb_gpus": resp.nb_gpus, "gpus": gpuArr } console.log('gpu usage: ',result) this.state.vramUsage = result } else{ const result = { "nb_gpus": 0, "gpus": [] } console.log('gpu usage: ',result) this.state.vramUsage = result } }, } }) async function api_get_req(endpoint) { try { const res = await axios.get('/' + endpoint); if (res) { return res.data; } } catch (error) { console.log(error.message, 'api_get_req'); throw error; } } async function refreshHardwareUsage(store) { await store.dispatch('refreshDiskUsage'); await store.dispatch('refreshRamUsage'); await store.dispatch('refreshVramUsage'); } let actionsExecuted = false; app.mixin({ async created() { if (!actionsExecuted) { this.$store.state.api_get_req = api_get_req actionsExecuted = true; console.log("Calling") try{ this.$store.state.loading_infos = "Loading Configuration" this.$store.state.loading_progress = 10 await this.$store.dispatch('refreshConfig'); console.log("Config ready") } catch (ex){ console.log("Error cought:", ex) } try{ this.$store.state.loading_infos = "Loading Database" this.$store.state.loading_progress = 20 await this.$store.dispatch('refreshDatabase'); } catch (ex){ console.log("Error cought:", ex) } try{ this.$store.state.loading_infos = "Getting version" this.$store.state.loading_progress = 30 await this.$store.dispatch('getVersion'); } catch (ex){ console.log("Error cought:", ex) } try{ this.$store.state.loading_infos = "Getting Bindings list" this.$store.state.loading_progress = 40 await this.$store.dispatch('refreshBindings'); } catch (ex){ console.log("Error cought:", ex) } try{ this.$store.state.loading_infos = "Getting Hardware usage" await refreshHardwareUsage(this.$store); } catch (ex){ console.log("Error cought:", ex) } try{ this.$store.state.loading_infos = "Getting extensions zoo" this.$store.state.loading_progress = 50 await this.$store.dispatch('refreshExtensionsZoo'); } catch (ex){ console.log("Error cought:", ex) } try{ this.$store.state.loading_infos = "Getting mounted extensions" this.$store.state.loading_progress = 60 await this.$store.dispatch('refreshmountedExtensions'); } catch (ex){ console.log("Error cought:", ex) } try{ this.$store.state.loading_infos = "Getting personalities zoo" this.$store.state.loading_progress = 70 await this.$store.dispatch('refreshPersonalitiesZoo') } catch (ex){ console.log("Error cought:", ex) } try{ this.$store.state.loading_infos = "Getting mounted personalities" this.$store.state.loading_progress = 80 await this.$store.dispatch('refreshMountedPersonalities'); } catch (ex){ console.log("Error cought:", ex) } try{ this.$store.state.loading_infos = "Getting models zoo" this.$store.state.loading_progress = 90 await this.$store.dispatch('refreshModelsZoo'); } catch (ex){ console.log("Error cought:", ex) } try{ this.$store.state.loading_infos = "Getting active models" this.$store.state.loading_progress = 100 await this.$store.dispatch('refreshModels'); await this.$store.dispatch('refreshModelStatus'); } catch (ex){ console.log("Error cought:", ex) } this.$store.state.ready = true; } }, beforeMount() { } }) function logObjectProperties(obj) { if (typeof obj !== 'object' || obj === null) { console.log('Invalid object'); return; } let logString = "Object parameters and values:\n"; for (const key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key) && typeof obj[key] !== 'function') { logString += `${key}: ${obj[key]}\n`; } } console.log(logString); } function flattenObject(obj, parentKey = "") { let result = []; for (const key in obj) { if (obj.hasOwnProperty(key)) { const newKey = parentKey ? `${parentKey}/${key}` : key; if (typeof obj[key] === "object") { const nestedFields = flattenObject(obj[key], newKey); result = result.concat(nestedFields); } else { result.push(newKey); } } } return result; } app.use(router) app.use(store) app.mount('#app') export{logObjectProperties, copyObject, flattenObject, refreshHardwareUsage}