fix(webhook): load URL-resolved profile's skills under multiplex

A `/p/<profile>/webhooks/<route>` request resolved the profile from the URL
but ran the route script, prompt render and `skills:` lookup with no
profile scope — the runner only enters `_profile_runtime_scope` later,
around `handle_message` — so routed webhooks loaded the launch (default)
profile's skills and logged "Skill not found" for the routed profile's own.

- gateway/platforms/webhook.py: add `_profile_scope(profile)` (nullcontext
  when no prefix was resolved; `_profile_runtime_scope(get_profile_dir(p))`
  otherwise, same helper the runner uses) and wrap the script / render /
  skill-injection block in it. Bare routes are unchanged.
- agent/skill_commands.py: `scan_skill_commands` scanned the import-time
  `SKILLS_DIR` (frozen to the launch home), so even a correctly scoped call
  listed default's skills; the #88023 home-keyed cache alone could not fix
  that. Use the call-time `_skills_dir()` there and at the two other
  SKILLS_DIR-relative sites in the module.
- agent/skill_utils.py: `normalize_skill_lookup_name` used the same frozen
  root, so a routed profile's absolute skill_dir was rejected by
  `skill_view` ("must be a relative path within the skills directory").
  Resolve against `_skills_dir()` — the root `skill_view` itself enforces.

Fixes #67277

Co-authored-by: Juani Lezcano <tky.juani@gmail.com>
Co-authored-by: webtecnica <75556242+webtecnica@users.noreply.github.com>
This commit is contained in:
Teknium
2026-09-02 03:40:53 -07:00
parent cd7811a7a7
commit dc7e1b7ab9
5 changed files with 188 additions and 65 deletions
+7 -4
View File
@@ -996,12 +996,15 @@ def normalize_skill_lookup_name(identifier: str) -> str:
# Look the primary skills root up on tools.skills_tool at CALL time
# (not via get_skills_dir()): callers and tests patch
# ``tools.skills_tool.SKILLS_DIR`` and skill_view() itself resolves
# against that module attribute, so normalization must agree with the
# exact root skill_view() will enforce. Import deferred to avoid a
# module cycle (tools.skills_tool imports agent.skill_utils).
# against ``_skills_dir()`` — which honors that patch and otherwise
# follows the live profile-scoped HERMES_HOME (the import-time
# SKILLS_DIR is frozen to the launch home, #67277) — so normalization
# must agree with the exact root skill_view() will enforce. Import
# deferred to avoid a module cycle (tools.skills_tool imports
# agent.skill_utils).
try:
from tools import skills_tool as _skills_tool
primary_root = Path(_skills_tool.SKILLS_DIR)
primary_root = _skills_tool._skills_dir()
except Exception:
primary_root = get_skills_dir()