This commit is contained in:
Timothy Jaeryang Baek
2026-07-15 15:06:08 -04:00
parent 396ee62226
commit 3fcb7b2d64
3 changed files with 20 additions and 16 deletions
+11 -7
View File
@@ -2074,7 +2074,7 @@ def sanitize_tool_pairs(messages: list[dict]) -> list[dict]:
return sanitized
SKILL_MENTION_RE = re.compile(r'<\$([^|>]+)(?:\|[^>]*)?>')
SKILL_MENTION_RE = re.compile(r'<(?:\$([^|>]+)(?:\|[^>]*)?|/([^|>]+)\|[^>]*)>')
def _get_text_parts(message: dict) -> list[str]:
@@ -2088,27 +2088,31 @@ def _get_text_parts(message: dict) -> list[str]:
def extract_skill_ids_from_messages(messages: list[dict]) -> set[str]:
"""Extract skill IDs from <$skillId|label> mention tags in messages."""
"""Extract skill IDs from <$skillId|label> and </skillId|label> mention tags."""
ids: set[str] = set()
for message in messages:
for text in _get_text_parts(message):
ids.update(m.group(1) for m in SKILL_MENTION_RE.finditer(text))
ids.update(m.group(1) or m.group(2) for m in SKILL_MENTION_RE.finditer(text))
return ids
def strip_skill_mentions(messages: list[dict]) -> None:
"""Replace <$skillId|label> mention tags with the label in message content in-place."""
strip_re = re.compile(r'<\$[^|>]+(?:\|([^>]*))?>')
"""Replace <$skillId|label> and </skillId|label> mention tags with the label in-place."""
strip_re = re.compile(r'<(?:\$[^|>]+(?:\|([^>]*))?|/[^|>]+\|([^>]*))>')
def label(match):
return match.group(1) or match.group(2) or ''
for message in messages:
content = message.get('content')
if isinstance(content, str) and strip_re.search(content):
message['content'] = strip_re.sub(r'\1', content).strip()
message['content'] = strip_re.sub(label, content).strip()
elif isinstance(content, list):
for part in content:
if isinstance(part, dict) and part.get('type') == 'text':
text = part.get('text', '')
if strip_re.search(text):
part['text'] = strip_re.sub(r'\1', text).strip()
part['text'] = strip_re.sub(label, text).strip()
async def connect_mcp_server(
@@ -691,8 +691,7 @@
</div>
<div
class="shrink-0 flex w-full min-w-0 flex-1 pr-1 self-center {(model?.is_active ??
true)
class="flex min-w-0 flex-1 pr-1 self-center {(model?.is_active ?? true)
? ''
: 'text-gray-500'}"
>
@@ -704,13 +703,13 @@
? `${model?.ollama?.digest} **(${model?.ollama?.modified_at})**`
: model.id
)}
className=" w-fit"
className="min-w-0 flex-1"
placement="top-start"
>
<div
class="text-[13px] leading-4 font-normal line-clamp-1 flex items-center gap-1.5"
class="flex min-w-0 items-center gap-1.5 text-[13px] font-normal leading-4"
>
{model.name}
<span class="min-w-0 truncate">{model.name}</span>
<span
class="shrink-0 text-[11px] font-normal leading-4 {modelAccessClass(
@@ -723,7 +722,7 @@
</Tooltip>
</div>
</button>
<div class="flex flex-row gap-0.5 items-center self-center">
<div class="flex shrink-0 flex-row gap-0.5 items-center self-center">
{#if shiftKey}
<Tooltip content={model?.meta?.hidden ? $i18n.t('Show') : $i18n.t('Hide')}>
<button
@@ -106,15 +106,16 @@
}
});
// Convert TipTap mention spans -> <@id>
// Convert TipTap mention spans -> serialized mention tags.
turndownService.addRule('mentions', {
filter: (node) => node.nodeName === 'SPAN' && node.getAttribute('data-type') === 'mention',
replacement: (_content, node: HTMLElement) => {
const id = node.getAttribute('data-id') || '';
// TipTap stores the trigger char in data-mention-suggestion-char (usually "@")
const ch = node.getAttribute('data-mention-suggestion-char') || '@';
// Emit <@id> style, e.g. <@llama3.2:latest>
return `<${ch}${id}>`;
// Skills are always serialized as <$id|label>, even when selected from "/".
const mentionChar = id.includes('|') ? '$' : ch;
return `<${mentionChar}${id}>`;
}
});