mirror of
https://github.com/open-webui/open-webui.git
synced 2026-09-12 23:02:35 +00:00
refac
This commit is contained in:
parent
2a44c9d384
commit
0edd731c74
5 changed files with 32 additions and 12 deletions
|
|
@ -2240,7 +2240,7 @@ def sanitize_tool_pairs(messages: list[dict]) -> list[dict]:
|
|||
return sanitized
|
||||
|
||||
|
||||
# Ids are validated as [a-z0-9_-]+ on create; matching that keeps ordinary "<$..." text intact.
|
||||
# Match candidate mentions using the same ID characters allowed on skill creation.
|
||||
SKILL_MENTION_RE = re.compile(r'<(?:\$([a-z0-9_-]+)(?:\|[^>]*)?|/([a-z0-9_-]+)\|[^>]*)>')
|
||||
|
||||
|
||||
|
|
@ -2263,25 +2263,27 @@ def extract_skill_ids_from_messages(messages: list[dict]) -> set[str]:
|
|||
return ids
|
||||
|
||||
|
||||
SKILL_MENTION_STRIP_RE = re.compile(r'<(?:\$[a-z0-9_-]+(?:\|([^>]*))?|/[a-z0-9_-]+\|([^>]*))>')
|
||||
SKILL_MENTION_STRIP_RE = re.compile(r'<(?:\$([a-z0-9_-]+)(?:\|([^>]*))?|/([a-z0-9_-]+)\|([^>]*))>')
|
||||
|
||||
|
||||
def strip_skill_mentions(messages: list[dict]) -> None:
|
||||
"""Replace <$skillId|label> and </skillId|label> mention tags with the label in-place."""
|
||||
def strip_skill_mentions(messages: list[dict], skill_ids: set[str]) -> None:
|
||||
"""Replace mentions of resolved skills with their label, preserving all other text."""
|
||||
|
||||
def label(match):
|
||||
return match.group(1) or match.group(2) or ''
|
||||
if (match.group(1) or match.group(3)) not in skill_ids:
|
||||
return match.group(0)
|
||||
return match.group(2) or match.group(4) or ''
|
||||
|
||||
for message in messages:
|
||||
content = message.get('content')
|
||||
if isinstance(content, str) and SKILL_MENTION_STRIP_RE.search(content):
|
||||
message['content'] = SKILL_MENTION_STRIP_RE.sub(label, content).strip()
|
||||
message['content'] = SKILL_MENTION_STRIP_RE.sub(label, content)
|
||||
elif isinstance(content, list):
|
||||
for part in content:
|
||||
if isinstance(part, dict) and part.get('type') == 'text':
|
||||
text = part.get('text', '')
|
||||
if SKILL_MENTION_STRIP_RE.search(text):
|
||||
part['text'] = SKILL_MENTION_STRIP_RE.sub(label, text).strip()
|
||||
part['text'] = SKILL_MENTION_STRIP_RE.sub(label, text)
|
||||
|
||||
|
||||
async def connect_mcp_server(
|
||||
|
|
@ -2776,8 +2778,8 @@ async def process_chat_payload(request, form_data, user, metadata, model):
|
|||
append=True,
|
||||
)
|
||||
|
||||
# Strip <$skillId|label> mention tags so the model doesn't see raw markup.
|
||||
strip_skill_mentions(form_data.get('messages', []))
|
||||
# Strip only resolved skill mentions; ordinary text such as Perl's <$fh> stays intact.
|
||||
strip_skill_mentions(form_data.get('messages', []), {s.id for s in available_skills})
|
||||
|
||||
prompt = get_last_user_message(form_data['messages'])
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
const i18n = getContext('i18n');
|
||||
|
||||
import { WEBUI_BASE_URL } from '$lib/constants';
|
||||
import { skills } from '$lib/stores';
|
||||
import { copyToClipboard, safeLinkUrl, unescapeHtml } from '$lib/utils';
|
||||
|
||||
import Image from '$lib/components/common/Image.svelte';
|
||||
|
|
@ -128,7 +129,11 @@
|
|||
}}
|
||||
></iframe>
|
||||
{:else if token.type === 'mention'}
|
||||
<MentionToken {token} />
|
||||
{#if token.triggerChar === '$' && !$skills?.some((skill) => skill.id === token.id && skill.is_active)}
|
||||
{token.raw}
|
||||
{:else}
|
||||
<MentionToken {token} />
|
||||
{/if}
|
||||
{:else if token.type === 'footnote'}
|
||||
{@html DOMPurify.sanitize(
|
||||
`<sup class="footnote-ref footnote-ref-text">${token.escapedText}</sup>`
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
import { marked } from 'marked';
|
||||
import DOMPurify from 'dompurify';
|
||||
import equal from 'fast-deep-equal';
|
||||
import { skills } from '$lib/stores';
|
||||
|
||||
marked.use({
|
||||
breaks: true,
|
||||
|
|
@ -522,9 +523,15 @@
|
|||
// Now replace the escaped mention patterns back into real spans
|
||||
const withMentions = escaped.replace(
|
||||
/<([@#$])([^|&\s]+)(?:\|([^&]*?))?>|<\/([\w.\-:/]+)\|([^&]*?)>/g,
|
||||
(_, ch, id, label, slashSkillId, slashSkillLabel) => {
|
||||
(match, ch, id, label, slashSkillId, slashSkillLabel) => {
|
||||
const mentionChar = ch || '$';
|
||||
const mentionId = id || slashSkillId;
|
||||
if (
|
||||
mentionChar === '$' &&
|
||||
!$skills?.some((skill) => skill.id === mentionId && skill.is_active)
|
||||
) {
|
||||
return match;
|
||||
}
|
||||
const display = (label || slashSkillLabel)?.length
|
||||
? label || slashSkillLabel
|
||||
: mentionId;
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ export const models: Writable<Model[]> = writable([]);
|
|||
|
||||
export const knowledge: Writable<null | Document[]> = writable(null);
|
||||
export const tools = writable(null);
|
||||
export const skills = writable(null);
|
||||
export const skills: Writable<null | any[]> = writable(null);
|
||||
export const functions = writable(null);
|
||||
|
||||
export type WorkspaceSection = 'models' | 'knowledge' | 'prompts' | 'skills' | 'tools';
|
||||
|
|
|
|||
|
|
@ -1,4 +1,7 @@
|
|||
// mention-extension.ts
|
||||
import { get } from 'svelte/store';
|
||||
import { skills } from '$lib/stores';
|
||||
|
||||
type MentionOptions = {
|
||||
triggerChar?: string; // default "@"
|
||||
className?: string; // default "mention"
|
||||
|
|
@ -20,6 +23,9 @@ function mentionStart(src: string) {
|
|||
|
||||
function mentionRenderer(token: any, options: MentionOptions = {}) {
|
||||
const trigger = options.triggerChar ?? '@';
|
||||
if (trigger === '$' && !get(skills)?.some((skill) => skill.id === token.id && skill.is_active)) {
|
||||
return escapeHtml(token.raw);
|
||||
}
|
||||
const cls = options.className ?? 'mention';
|
||||
const extra = options.extraAttrs ?? {};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue