mirror of
https://github.com/hansjone/oclaw.git
synced 2026-10-11 12:10:45 +08:00
Bust executor prompt cache on workspace SKILL.md layout changes
Add workspace_skills_layout_signature (hash of paths + mtimes + sizes) and fold it into get_executor_prompt_static and manager prebuild cache keys. Add tests for signature drift and cache invalidation. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
c33ca303a2
commit
939a734e76
4 changed files with 112 additions and 0 deletions
|
|
@ -1,5 +1,6 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
|
|
@ -170,6 +171,38 @@ def discover_public_workspace_skill_names(skills_root: str | Path | None = None)
|
|||
return out
|
||||
|
||||
|
||||
def workspace_skills_layout_signature(skills_root: str | Path | None = None) -> str:
|
||||
"""Short hex signature that changes when any ``SKILL.md`` under the skills root moves or changes on disk.
|
||||
|
||||
Used to bust executor/manager prompt caches after install/uninstall/edit of workspace skills without
|
||||
touching SQLite settings.
|
||||
"""
|
||||
base = Path(skills_root).resolve() if skills_root else default_skills_root()
|
||||
if not base.exists() or not base.is_dir():
|
||||
return "0"
|
||||
h = hashlib.sha256()
|
||||
h.update(str(base).encode("utf-8", errors="ignore"))
|
||||
h.update(b"\n")
|
||||
try:
|
||||
for skill_md in sorted(base.rglob("SKILL.md"), key=lambda p: str(p).lower()):
|
||||
if not skill_md.is_file():
|
||||
continue
|
||||
try:
|
||||
st = skill_md.stat()
|
||||
rel = skill_md.relative_to(base).as_posix().lower()
|
||||
h.update(rel.encode("utf-8", errors="ignore"))
|
||||
h.update(str(int(st.st_mtime_ns)).encode("ascii", errors="ignore"))
|
||||
h.update(b":")
|
||||
h.update(str(int(st.st_size)).encode("ascii", errors="ignore"))
|
||||
h.update(b"\n")
|
||||
except OSError:
|
||||
h.update(str(skill_md.resolve()).encode("utf-8", errors="ignore"))
|
||||
h.update(b"\n?")
|
||||
except OSError:
|
||||
return "0:err"
|
||||
return h.hexdigest()[:24]
|
||||
|
||||
|
||||
def _tool_origin(tool: "ToolSpec") -> str:
|
||||
nm = str(getattr(tool, "name", "") or "")
|
||||
if nm.startswith("mcp__"):
|
||||
|
|
@ -344,6 +377,7 @@ __all__ = [
|
|||
"build_skill_registry",
|
||||
"default_skills_root",
|
||||
"discover_workspace_skill_manifests",
|
||||
"workspace_skills_layout_signature",
|
||||
"load_skill_manifest",
|
||||
"materialize_skills_from_tool_specs",
|
||||
"skill_runtime_diagnostics",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue