This commit is contained in:
Timothy Jaeryang Baek 2026-06-29 05:44:47 -05:00
parent e6d35fc4cc
commit 44b9463498

View file

@ -2693,41 +2693,49 @@ async def process_chat_payload(request, form_data, user, metadata, model):
# Otherwise, save any tools that filter inlets added for merging later.
inlet_filter_tools = None if payload_tools is not None else form_data.get('tools', None)
# Skills — extract IDs from message content (<$skillId|label> tags) so
# persisted chats work without relying on the frontend to send skill_ids.
user_skill_ids = set(form_data.pop('skill_ids', None) or [])
user_skill_ids |= extract_skill_ids_from_messages(form_data.get('messages', []))
model_skill_ids = set(model.get('info', {}).get('meta', {}).get('skillIds', []))
all_skill_ids = user_skill_ids | model_skill_ids
# Mentioned skills get full content; selected/default skills can be loaded through view_skill.
mentioned_skill_ids = extract_skill_ids_from_messages(form_data.get('messages', []))
skill_ids = (
set(form_data.pop('skill_ids', None) or [])
| set(model.get('info', {}).get('meta', {}).get('skillIds', []))
| mentioned_skill_ids
)
available_skills = []
if all_skill_ids:
view_skill_ids = []
use_builtin_tools = (
bool(metadata.get('session_id'))
and metadata.get('params', {}).get('function_calling') != 'legacy'
and (model.get('info', {}).get('meta', {}).get('capabilities') or {}).get('builtin_tools', True)
)
if skill_ids:
from open_webui.models.skills import Skills as SkillsModel
accessible_skill_ids = {s.id for s in await SkillsModel.get_skills_by_user_id(user.id, 'read')}
available_skills = []
for sid in all_skill_ids:
for sid in skill_ids:
if sid in accessible_skill_ids:
s = await SkillsModel.get_skill_by_id(sid)
if s and s.is_active:
available_skills.append(s)
skill_descriptions = ''
skill_manifest = ''
for skill in available_skills:
if skill.id in user_skill_ids:
# User-selected: inject full content
if skill.id in mentioned_skill_ids or not use_builtin_tools:
form_data['messages'] = add_or_update_system_message(
f'<skill name="{skill.name}">\n{skill.content}\n</skill>',
form_data['messages'],
append=True,
)
else:
# Model-attached: name+description only
skill_descriptions += f'<skill>\n<id>{skill.id}</id>\n<name>{skill.name}</name>\n<description>{skill.description or ""}</description>\n</skill>\n'
view_skill_ids.append(skill.id)
skill_manifest += (
f'<skill>\n<id>{skill.id}</id>\n<name>{skill.name}</name>\n'
f'<description>{skill.description or ""}</description>\n</skill>\n'
)
if skill_descriptions:
if skill_manifest:
form_data['messages'] = add_or_update_system_message(
f'<available_skills>\n{skill_descriptions}</available_skills>',
f'<available_skills>\n{skill_manifest}</available_skills>',
form_data['messages'],
append=True,
)
@ -2916,11 +2924,7 @@ async def process_chat_payload(request, form_data, user, metadata, model):
# Inject builtin tools for native function calling based on enabled features and model capability.
# Only inject when the request originates from the UI (identified by session_id).
# API callers don't expect hidden tools; they can explicitly request tools via tool_ids.
builtin_tools_enabled = (model.get('info', {}).get('meta', {}).get('capabilities') or {}).get(
'builtin_tools', True
)
has_session = bool(metadata.get('session_id'))
if has_session and metadata.get('params', {}).get('function_calling') != 'legacy' and builtin_tools_enabled:
if use_builtin_tools:
# Add file context to user messages
chat_id = metadata.get('chat_id')
form_data['messages'] = await add_file_context(form_data.get('messages', []), chat_id, user)
@ -2929,7 +2933,7 @@ async def process_chat_payload(request, form_data, user, metadata, model):
{
**extra_params,
'__event_emitter__': event_emitter,
'__skill_ids__': [s.id for s in available_skills if s.id not in user_skill_ids],
'__skill_ids__': view_skill_ids,
},
features,
model,