-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathregistry.py
More file actions
87 lines (71 loc) · 3.46 KB
/
Copy pathregistry.py
File metadata and controls
87 lines (71 loc) · 3.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
from __future__ import annotations
from .defs.agents import TOOLS_SECTION as _AGENTS
from .defs.browser_web import TOOLS_SECTION as _BROWSER_WEB
from .defs.channel_process_loops import TOOLS_SECTION as _CHANNEL_PROCESS_LOOPS
from .defs.integrations_email import TOOLS_SECTION as _INTEGRATIONS_EMAIL
from .defs.media_scheduling import TOOLS_SECTION as _MEDIA_SCHEDULING
from .defs.memory_skills import TOOLS_SECTION as _MEMORY_SKILLS
from .defs.output_delivery import TOOLS_SECTION as _OUTPUT_DELIVERY
from .defs.system_files import TOOLS_SECTION as _SYSTEM_FILES
from .defs.tasks_knowledge import TOOLS_SECTION as _TASKS_KNOWLEDGE
# RFC-004 P1: TOOLS is the exact-order concatenation of the section
# slices in src/tools/defs/. ORDER IS BEHAVIOR (prompt catalog) — the
# characterization contract (test_tool_parity) pins the full order, and
# sections are positional slices, never semantic regroupings.
TOOLS: list[dict] = [
*_SYSTEM_FILES,
*_MEDIA_SCHEDULING,
*_MEMORY_SKILLS,
*_TASKS_KNOWLEDGE,
*_BROWSER_WEB,
*_CHANNEL_PROCESS_LOOPS,
*_AGENTS,
*_INTEGRATIONS_EMAIL,
*_OUTPUT_DELIVERY,
]
TOOL_MAP: dict[str, dict] = {t["name"]: t for t in TOOLS}
# RFC-004 P7 startup assertion (plan advisory #5): duplicate names in the
# section slices would collapse silently in TOOL_MAP — fail at import
# instead. (The exact count/order is pinned by the characterization
# contract, where changing it is a reviewed edit rather than a prod crash.)
assert len(TOOL_MAP) == len(TOOLS), "duplicate tool name across defs/ sections"
# NOTE: the old MUTATING_TOOLS / READ_ONLY_TOOLS frozensets were removed — they
# were imported only by a schema test and NOT consulted by any runtime
# authorization path (the governor uses risk_classifier; mutation detection uses
# post_validation.detect_mutation). Keeping them was an approval-bypass trap: a
# reviewer moving a tool between the sets would think they'd changed
# authorization while nothing actually changed.
# Cache for get_tool_definitions — avoids rebuilding dicts on every message.
_tool_defs_cache: list[dict] | None = None
def get_tool_definitions(command_shell: str | None = None) -> list[dict]:
"""Return tool definitions.
Each description is decorated with an affordance footer (cost / risk /
latency / preconditions) so the LLM can price a call before making it.
Results are cached. Call invalidate_tool_defs_cache()
if TOOLS list is modified at runtime (e.g. by tests).
Explicit command_shell decorates fresh local facts; None is the stable,
host-independent documentation catalog. ToolCatalog applies live facts.
"""
from .affordances import decorate_description
global _tool_defs_cache
if _tool_defs_cache is None:
_tool_defs_cache = [
{
"name": t["name"],
"description": decorate_description(t["name"], t["description"]),
"input_schema": t["input_schema"],
**({"is_core": True} if t.get("is_core") else {}),
}
for t in TOOLS
]
if command_shell is None:
return _tool_defs_cache
from .command_shell import apply_shell_contracts
return apply_shell_contracts(_tool_defs_cache, command_shell)
def invalidate_tool_defs_cache() -> None:
"""Clear the tool definitions cache.
Call after modifying TOOLS at runtime (e.g. in tests) or after
config changes that affect tool availability.
"""
global _tool_defs_cache
_tool_defs_cache = None