enhanced ui

This commit is contained in:
Saifeddine ALOUI 2025-02-22 01:40:23 +01:00
parent 20b61f333f
commit e2311fc691
11 changed files with 161 additions and 147 deletions

View File

@ -593,8 +593,8 @@ async def open_custom_function_calls_folder(request: ClientAuthentication):
class PersonalityFolderRequest(BaseModel):
client_id: str = Field(...)
personality_folder: str = Field(...)
category: str = Field(...)
name: str = Field(...)
@router.post("/open_personality_folder")
async def open_personality_folder(request: PersonalityFolderRequest):
@ -605,7 +605,12 @@ async def open_personality_folder(request: PersonalityFolderRequest):
:return: A JSON response with the status of the operation.
"""
client = check_access(lollmsElfServer, request.client_id)
personality_folder = sanitize_path(request.personality_folder)
request.name = sanitize_path(request.name)
request.category = sanitize_path(request.category)
if request.category == "custom_personalities":
folder = lollmsElfServer.lollms_paths.custom_personalities_path/request.name
else:
folder = lollmsElfServer.lollms_paths.personalities_zoo_path/request.category/request.name
if lollmsElfServer.config.headless_server_mode:
return {

@ -1 +1 @@
Subproject commit 1d40e4d4f3fabc55042c783f4b5bc867c66d3b52
Subproject commit 062418120e213607696853298128c719eb5eb2d6

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

4
web/dist/index.html vendored
View File

@ -6,8 +6,8 @@
<script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>LoLLMS WebUI</title>
<script type="module" crossorigin src="/assets/index-B_QZR9zU.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-Dx2EU4qT.css">
<script type="module" crossorigin src="/assets/index-D1iX16Nx.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-B3U3p_X4.css">
</head>
<body>
<div id="app"></div>

View File

@ -74,6 +74,7 @@
<div class="relative flex-grow">
<textarea
id="chat"
:disabled="loading"
v-model="message"
@paste="handlePaste"
@keydown.enter.exact="submitOnEnter($event)"
@ -163,6 +164,7 @@
ref="databasesList"
/>
<PersonalitiesCommands
v-if="$store.state.config.mounted_function_calls.length>0"
icon="feather:zap"
:help="'Function calls (WIP)'"
:commandsList="functionCalls"

View File

@ -1,15 +1,14 @@
<template>
<div class="app-card flex flex-col h-full"
:class="selected_computed ? 'border-primary-light' : 'border-transparent', mounted ? 'bg-blue-200 dark:bg-blue-700' : ''"
:class="mounted ? 'border-primary-light' : 'border-transparent'"
:title="!function_call.installed ? 'Not installed' : ''">
<div class="flex-grow">
<div class="flex items-center mb-4">
<img :src="getImgUrl()" @error="defaultImg($event)" alt="function_call Icon"
class="w-16 h-16 rounded-full border border-gray-300 mr-4 cursor-pointer"
@click="toggleSelected"
@mouseover="showThumbnail" @mousemove="updateThumbnailPosition" @mouseleave="hideThumbnail" />
<div>
<h3 class="font-bold text-xl text-gray-800 cursor-pointer" @click="toggleSelected">{{ function_call.name }}</h3>
<h3 class="font-bold text-xl text-gray-800 cursor-pointer">{{ function_call.name }}</h3>
<p class="text-sm text-gray-600">Author: {{ function_call.author }}</p>
<p class="text-sm text-gray-600">Version: {{ function_call.version }}</p>
<p class="text-sm text-gray-600">Category: {{ function_call.category }}</p>
@ -36,12 +35,13 @@
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11.049 2.927c.3-.921 1.603-.921 1.902 0l1.519 4.674a1 1 0 00.95.69h4.915c.969 0 1.371 1.24.588 1.81l-3.976 2.888a1 1 0 00-.363 1.118l1.518 4.674c.3.922-.755 1.688-1.538 1.118l-3.976-2.888a1 1 0 00-1.176 0l-3.976 2.888c-.783.57-1.838-.197-1.538-1.118l1.518-4.674a1 1 0 00-.363-1.118l-3.976-2.888c-.784-.57-.38-1.81.588-1.81h4.914a1 1 0 00.951-.69l1.519-4.674z" />
</svg>
</button>
<button v-if="mounted" @click="toggleSelected" class="text-blue-500 hover:text-blue-600 transition duration-300 ease-in-out" title="Select">
<i data-feather="check" class="h-6 w-6"></i>
</button>
<button @click="showFolder" class="text-purple-500 hover:text-purple-600 transition duration-300 ease-in-out" title="Show Folder">
<i data-feather="folder" class="h-6 w-6"></i>
</button>
<!-- Added Settings Button -->
<button v-if="mounted" @click="show_settings" class="text-green-500 hover:text-green-600 transition duration-300 ease-in-out" title="Settings">
<i data-feather="settings" class="h-6 w-6"></i>
</button>
<InteractiveMenu :commands="commandsList" :force_position="2" title="Menu" class="text-gray-500 hover:text-gray-600 transition duration-300 ease-in-out">
</InteractiveMenu>
</div>
@ -79,10 +79,8 @@ export default {
props: {
function_call: {},
select_language: Boolean,
selected: Boolean,
full_path: String,
onOpenFolder:Function,
onSelected: Function,
onMount: Function,
onUnMount: Function,
onRemount: Function,
@ -121,9 +119,6 @@ export default {
}
return main_menu
},
selected_computed(){
return this.selected
}
},
mounted() {
this.mounted = this.function_call.mounted
@ -165,12 +160,7 @@ export default {
toggleCopyLink() {
this.onCopyfunction_callName(this)
//navigator.clipboard.writeText(this.path)
},
toggleSelected() {
if(this.mounted){
this.onSelected(this)
}
},
},
edit(){
this.onEdit(this)
},
@ -199,11 +189,6 @@ export default {
}
},
watch: {
selected() {
nextTick(() => {
feather.replace()
})
}
}
};
</script>

View File

@ -79,64 +79,85 @@
CodeBlock,
ThinkingBlock,
},
setup(props) {
setup(props) {// Helper function to find the next tag
function findNextTag(state, startLine) {
for (let i = startLine; i < state.lineMax; i++) {
let line = state.src.slice(state.bMarks[i], state.eMarks[i]).trim();
if (line === '<thinking>' || line === '<think>' || line === '</thinking>' || line === '</think>') {
return { line: i, tag: line };
}
}
return null;
}
// Custom rule for thinking blocks
const thinkingRule = (state, startLine, endLine, silent) => {
let start = state.bMarks[startLine] + state.tShift[startLine];
let max = state.eMarks[startLine];
let line = state.src.slice(start, max).trim();
let line = state.src.slice(start, max);
let startTag, endTag;
// Check for both tag formats
if (line.trim().startsWith('<thinking>')) {
startTag = '<thinking>';
endTag = '</thinking>';
} else if (line.trim().startsWith('<think>')) {
startTag = '<think>';
endTag = '</think>';
} else {
return false;
}
let currentLine = startLine + 1;
let content = [];
let found = false;
// Search for closing tag
while (currentLine < endLine) {
let currentLineContent = state.src.slice(
state.bMarks[currentLine],
state.eMarks[currentLine]
);
if (currentLineContent.trim() === endTag) {
found = true;
break;
if (line === '<thinking>' || line === '<think>') {
// Explicit start
let startTag = line;
let endTag = startTag.replace('<', '</');
let content = [];
let found = false;
let currentLine = startLine + 1;
while (currentLine < endLine) {
let currentLineContent = state.src.slice(state.bMarks[currentLine], state.eMarks[currentLine]).trim();
if (currentLineContent === endTag) {
found = true;
break;
}
content.push(currentLineContent);
currentLine++;
}
if (silent) return true;
// Create tokens
let token = state.push('thinking_open', 'div', 1);
token.markup = startTag;
token.block = true;
token.is_done = found;
token.implicit = false;
token = state.push('thinking_content', '', 0);
token.content = content.join('\n');
token.is_done = found;
token = state.push('thinking_close', 'div', -1);
token.markup = endTag;
token.block = true;
token.is_done = found;
state.line = found ? currentLine + 1 : currentLine;
return true;
} else {
// Check for implicit start
let nextTag = findNextTag(state, startLine);
if (nextTag && (nextTag.tag === '</thinking>' || nextTag.tag === '</think>')) {
let endTag = nextTag.tag;
let startTag = endTag === '</thinking>' ? '<thinking>' : '<think>';
let content = [];
for (let i = startLine; i < nextTag.line; i++) {
content.push(state.src.slice(state.bMarks[i], state.eMarks[i]));
}
if (silent) return true;
// Create tokens with implicit start
let token = state.push('thinking_open', 'div', 1);
token.markup = startTag;
token.block = true;
token.is_done = true;
token.implicit = true;
token = state.push('thinking_content', '', 0);
token.content = content.join('\n');
token.is_done = true;
token = state.push('thinking_close', 'div', -1);
token.markup = endTag;
token.block = true;
token.is_done = true;
state.line = nextTag.line + 1;
return true;
} else {
return false;
}
content.push(currentLineContent);
currentLine++;
}
if (silent) return true;
// Create tokens
let token = state.push('thinking_open', 'div', 1);
token.markup = startTag;
token.block = true;
token.is_done = found;
token = state.push('thinking_content', '', 0);
token.content = content.join('\n');
token.is_done = found;
token = state.push('thinking_close', 'div', -1);
token.markup = endTag;
token.block = true;
token.is_done = found;
state.line = found ? currentLine + 1 : currentLine;
return true;
};

View File

@ -5120,7 +5120,7 @@ export default {
if (response.data.status) {
await this.$store.dispatch('refreshConfig');
this.$store.state.messageBox.showMessage('Function mounted successfully', true);
entry.mounted = false;
entry.mounted = true;
} else {
this.$store.state.messageBox.showMessage('Failed to mount function', false);
}
@ -5141,9 +5141,9 @@ export default {
});
if (response.data.status) {
await this.$store.dispatch('refreshConfig');
this.$store.state.toast.showToast('Function mounted successfully!', 4, true)
this.$store.state.toast.showToast('Function unmounted successfully!', 4, true)
this.$store.state.messageBox.showMessage('Function unmounted successfully', true);
entry.mounted = true
entry.mounted = false
} else {
this.$store.state.toast.showToast('Failed to unmount function', 4, false)
this.$store.state.messageBox.showMessage('Failed to unmount function', false);
@ -6456,7 +6456,7 @@ export default {
await axios.post("/copy_to_custom_personas",{client_id:this.$store.state.client_id, category: pers.personality.category, name: pers.personality.name})
},
async handleOpenFolder(pers){
await axios.post("/open_personality_folder",{client_id:this.$store.state.client_id, personality_folder: pers.personality.category/pers.personality.folder})
await axios.post("/open_personality_folder",{client_id:this.$store.state.client_id, category: pers.personality.category, name: pers.personality.name})
},
onCancelInstall() {

@ -1 +1 @@
Subproject commit 9894cb53fcd8f39a0481dab11c7fef5f9e033802
Subproject commit aa1925283b05eb577973d84a824cbdbe7a34363d

@ -1 +1 @@
Subproject commit 27100d3decb92d237ee8290aacfccb70a30736f2
Subproject commit 9c7262d0f41efc34979e386c81b9db1eff4daff6