refactor(tools): group H layout compaction (AST-neutral bracket hugging)

This commit is contained in:
Teknium
2026-09-02 22:42:44 -07:00
parent 8b33fd46be
commit cffc1df516
6 changed files with 60 additions and 162 deletions

View File

@@ -20,11 +20,7 @@ import stat
from pathlib import Path
from typing import IO
__all__ = [
"ensure_spill_dir",
"open_exclusive",
"write_text_exclusive",
]
__all__ = ["ensure_spill_dir", "open_exclusive", "write_text_exclusive"]
# O_NOFOLLOW is POSIX-only; on Windows O_EXCL alone already refuses every
# pre-existing path.
@@ -51,8 +47,7 @@ def open_exclusive(
private: bool = True,
overwrite: bool = False,
encoding: str = "utf-8",
errors: str = "strict",
) -> IO[str]:
errors: str = "strict") -> IO[str]:
"""Open ``path`` for writing via exclusive create; never follows a link.
``overwrite=True`` first unlinks an existing path (``lstat``-checked, so only
the link itself is removed and directories are refused), then creates
@@ -83,8 +78,7 @@ def write_text_exclusive(
private: bool = True,
overwrite: bool = False,
encoding: str = "utf-8",
errors: str = "strict",
) -> None:
errors: str = "strict") -> None:
"""``Path.write_text`` equivalent that refuses to follow symlinks."""
with open_exclusive(
path, private=private, overwrite=overwrite, encoding=encoding, errors=errors

View File

@@ -36,10 +36,7 @@ def managed_nous_tools_enabled(*, force_fresh: bool = False) -> bool:
def nous_tool_gateway_unavailable_message(
capability: str = "the Nous Tool Gateway",
*,
force_fresh: bool = False,
) -> str:
capability: str = "the Nous Tool Gateway", *, force_fresh: bool = False) -> str:
"""Return account-aware guidance for an unavailable Nous Tool Gateway path."""
try:
from hermes_cli.nous_account import (
@@ -55,8 +52,7 @@ def nous_tool_gateway_unavailable_message(
pass
return (
f"{capability} is unavailable. Run `hermes model` to refresh your "
"Nous Portal login and billing status."
)
"Nous Portal login and billing status.")
def normalize_browser_cloud_provider(value: object | None) -> str:
@@ -81,9 +77,7 @@ def has_direct_modal_credentials() -> bool:
except (PermissionError, OSError):
modal_file_exists = False
return bool(
(os.getenv("MODAL_TOKEN_ID") and os.getenv("MODAL_TOKEN_SECRET"))
or modal_file_exists
)
(os.getenv("MODAL_TOKEN_ID") and os.getenv("MODAL_TOKEN_SECRET")) or modal_file_exists)
def resolve_modal_backend_state(
@@ -91,8 +85,7 @@ def resolve_modal_backend_state(
*,
has_direct: bool,
managed_ready: bool,
managed_enabled: bool | None = None,
) -> Dict[str, Any]:
managed_enabled: bool | None = None) -> Dict[str, Any]:
"""Resolve direct vs managed Modal backend: ``direct``/``managed`` are
exclusive; ``auto`` prefers managed when available, else direct."""
requested_mode = coerce_modal_mode(modal_mode)
@@ -111,8 +104,7 @@ def resolve_modal_backend_state(
"has_direct": has_direct,
"managed_ready": managed_ready,
"managed_mode_blocked": requested_mode == "managed" and not managed_enabled,
"selected_backend": selected_backend,
}
"selected_backend": selected_backend}
def _scoped_credential(name: str) -> str:
@@ -138,11 +130,7 @@ def _dotenv_value(env_var: str) -> str:
def resolve_provider_secret(
env_var: str,
provider_id: str,
config_value: str = "",
env_getter=None,
) -> str:
env_var: str, provider_id: str, config_value: str = "", env_getter=None) -> str:
"""Resolve a voice-provider API key (single owner for STT/TTS lookup).
Order: explicit ``config_value`` -> profile secret scope / env -> ``.env``
@@ -194,8 +182,7 @@ def resolve_openai_audio_api_key() -> str:
a raw ``os.environ`` read could bill another profile's account under multiplex."""
return (
resolve_provider_secret("VOICE_TOOLS_OPENAI_KEY", "")
or resolve_provider_secret("OPENAI_API_KEY", "openai-api")
)
or resolve_provider_secret("OPENAI_API_KEY", "openai-api"))
def prefers_gateway(config_section: str) -> bool:
@@ -215,16 +202,11 @@ def prefers_gateway(config_section: str) -> bool:
NOUS_MANAGED_PROVIDER = "nous"
# Per-capability keys that also count as "this category has been configured".
_EXTRA_SELECTION_KEYS = {
"web": ("search_backend", "extract_backend"),
}
_EXTRA_SELECTION_KEYS = {"web": ("search_backend", "extract_backend")}
# Key(s) carrying the category's provider selection. ``browser.backend`` is the
# DRIVER choice (browser-use CLI vs built-in), not the cloud provider — excluded.
_SELECTION_NAME_KEYS = {
"browser": ("cloud_provider",),
"web": ("backend",),
}
_SELECTION_NAME_KEYS = {"browser": ("cloud_provider",), "web": ("backend",)}
_DEFAULT_NAME_KEYS = ("provider", "backend", "cloud_provider")
@@ -298,8 +280,7 @@ def selection_error(section: str, selection_name: str, failure: str) -> str:
failure = removed_backend_note(section, selection_name) or failure
return (
f"{section} is configured to use {selection_name} (set via hermes "
f"tools), but {failure}. Run 'hermes tools' to change it."
)
f"tools), but {failure}. Run 'hermes tools' to change it.")
def fal_key_is_configured() -> bool:

View File

@@ -19,11 +19,7 @@ import shlex
import threading
import time
from tools.budget_config import (
DEFAULT_PREVIEW_SIZE_CHARS,
BudgetConfig,
DEFAULT_BUDGET,
)
from tools.budget_config import DEFAULT_PREVIEW_SIZE_CHARS, BudgetConfig, DEFAULT_BUDGET
logger = logging.getLogger(__name__)
PERSISTED_OUTPUT_TAG = "<persisted-output>"
@@ -187,11 +183,7 @@ def _write_to_sandbox(content: str, remote_path: str, env) -> bool:
def _build_persisted_message(
preview: str,
has_more: bool,
original_size: int,
file_path: str,
) -> str:
preview: str, has_more: bool, original_size: int, file_path: str) -> str:
"""Build the <persisted-output> replacement block."""
size_kb = original_size / 1024
size_str = f"{size_kb / 1024:.1f} MB" if size_kb >= 1024 else f"{size_kb:.1f} KB"
@@ -205,8 +197,7 @@ def _build_persisted_message(
"remote API; the full result is already on disk.\n\n"
f"Preview (first {len(preview)} chars):\n"
+ preview + ("\n..." if has_more else "")
+ f"\n{PERSISTED_OUTPUT_CLOSING_TAG}"
)
+ f"\n{PERSISTED_OUTPUT_CLOSING_TAG}")
_PERSISTED_PATH_RE = re.compile(r"^Full output saved to: (.+)$", re.MULTILINE)
@@ -228,8 +219,7 @@ def maybe_persist_tool_result(
tool_use_id: str,
env=None,
config: BudgetConfig = DEFAULT_BUDGET,
threshold: int | float | None = None,
) -> str:
threshold: int | float | None = None) -> str:
"""Layer 2: persist an oversized result, return preview + path.
``threshold`` overrides ``config.resolve_threshold(tool_name)``. Falls back
to inline truncation when no write location succeeds."""
@@ -243,8 +233,7 @@ def maybe_persist_tool_result(
def _persisted(path: str, host_suffix: str = "") -> str:
logger.info(
"Persisted large tool result: %s (%s, %d chars -> %s%s)",
tool_name, tool_use_id, len(content), path, host_suffix,
)
tool_name, tool_use_id, len(content), path, host_suffix)
return _build_persisted_message(preview, has_more, len(content), path)
# Always persist host-side first: cache/spillover is the single canonical home.
@@ -269,20 +258,15 @@ def maybe_persist_tool_result(
logger.info(
"Inline-truncating large tool result: %s (%d chars, no sandbox write)",
tool_name, len(content),
)
tool_name, len(content))
return (
f"{preview}\n\n"
f"[Truncated: tool response was {len(content):,} chars. "
f"Full output could not be saved to sandbox.]"
)
f"Full output could not be saved to sandbox.]")
def enforce_turn_budget(
tool_messages: list[dict],
env=None,
config: BudgetConfig = DEFAULT_BUDGET,
) -> list[dict]:
tool_messages: list[dict], env=None, config: BudgetConfig = DEFAULT_BUDGET) -> list[dict]:
"""Layer 3: persist the largest non-persisted results first until the turn's
aggregate is under budget. Mutates the list in-place and returns it."""
candidates = []
@@ -303,8 +287,7 @@ def enforce_turn_budget(
tool_use_id = tool_messages[idx].get("tool_call_id", f"budget_{idx}")
replacement = maybe_persist_tool_result(
content=content, tool_name=_BUDGET_TOOL_NAME, tool_use_id=tool_use_id,
env=env, config=config, threshold=0,
)
env=env, config=config, threshold=0)
if replacement != content:
total_size += len(replacement) - size
tool_messages[idx]["content"] = replacement

View File

@@ -22,25 +22,12 @@ from typing import Any, Dict, Iterable, List, Optional, Tuple
from tools.registry import tool_error
from tools.tool_search_names import ( # noqa: F401 — re-exported public names
BRIDGE_TOOL_NAMES,
TOOL_CALL_NAME,
TOOL_DESCRIBE_NAME,
TOOL_SEARCH_NAME,
BRIDGE_TOOL_NAMES, TOOL_CALL_NAME, TOOL_DESCRIBE_NAME, TOOL_SEARCH_NAME,
)
from tools.tool_search_catalog import ( # noqa: F401 — re-exported public/test names
CHARS_PER_TOKEN,
CatalogEntry,
_corpus_stats,
_entry_search_text,
_fn,
_listing_group_label,
_registry_entry,
_short_desc,
_stem,
_tokenize,
build_catalog,
build_catalog_listing_with_form,
search_catalog,
CHARS_PER_TOKEN, CatalogEntry, _corpus_stats, _entry_search_text, _fn,
_listing_group_label, _registry_entry, _short_desc, _stem, _tokenize,
build_catalog, build_catalog_listing_with_form, search_catalog,
)
from tools.tool_search_validation import validate_deferred_call_args # noqa: F401
@@ -94,9 +81,7 @@ class ToolSearchConfig:
# A list replaces the curated default wholesale; anything else = curated.
defer_tools=(
frozenset(str(n).strip() for n in defer_raw if str(n).strip())
if isinstance(defer_raw, (list, tuple, set)) else None
),
)
if isinstance(defer_raw, (list, tuple, set)) else None))
_TRI_STATE_ALIASES = {"true": "on", "1": "on", "yes": "on", "false": "off", "0": "off", "no": "off"}
@@ -202,8 +187,7 @@ def _tool_def_names(tool_defs: Iterable[Dict[str, Any]]) -> Iterable[str]:
def classify_tools(
tool_defs: List[Dict[str, Any]],
defer_tools: Optional[frozenset] = None,
) -> Tuple[List[Dict[str, Any]], List[Dict[str, Any]]]:
defer_tools: Optional[frozenset] = None) -> Tuple[List[Dict[str, Any]], List[Dict[str, Any]]]:
"""Split a tool-defs list into (visible, deferrable). Bridge tools are
dropped (they are re-added after classification)."""
visible: List[Dict[str, Any]] = []
@@ -236,8 +220,7 @@ def estimate_tokens_from_schemas(tool_defs: Iterable[Dict[str, Any]]) -> int:
def should_activate(
config: ToolSearchConfig,
deferrable_tokens: int,
context_length: Optional[int],
) -> bool:
context_length: Optional[int]) -> bool:
"""``"off"`` never activates; ``"on"``/``"auto"`` activate whenever any
deferrable tool exists. ``"auto"`` is an alias of ``"on"`` reserved for a
future budget-gated mode — do not distinguish them without that design.
@@ -280,8 +263,7 @@ def _search_description(deferred_count: int, listing: Optional[str], listing_for
"tool's description. Follow with "
f"`{TOOL_DESCRIBE_NAME}` to load full parameter schemas, "
f"then `{TOOL_CALL_NAME}` to invoke. Tools listed at the top of this "
"system prompt are already available and do not need to be searched."
)
"system prompt are already available and do not need to be searched.")
if not listing:
return desc
if listing_form == "groups":
@@ -290,28 +272,24 @@ def _search_description(deferred_count: int, listing: Optional[str], listing_for
"through this bridge. For any request in these domains, search "
"here FIRST — do not claim the capability is unavailable and do "
"not substitute a generic tool (terminal/browser) without "
"searching.\n\n" + listing
)
"searching.\n\n" + listing)
desc += (
"\n\nEvery deferred capability is listed below. If a tool name "
"appears here, do NOT claim it is unavailable — load it with "
f"`{TOOL_DESCRIBE_NAME}` (skip `{TOOL_SEARCH_NAME}` when you "
"already see the exact name)."
)
"already see the exact name).")
if listing_form == "mixed":
desc += (
" For servers marked 'names not listed', the tools exist "
f"too — find them with `{TOOL_SEARCH_NAME}` before "
"concluding anything is missing."
)
"concluding anything is missing.")
return desc + "\n\n" + listing
def bridge_tool_schemas(
deferred_count: int,
listing: Optional[str] = None,
listing_form: str = "",
) -> List[Dict[str, Any]]:
listing_form: str = "") -> List[Dict[str, Any]]:
"""Bridge tool schemas injected in place of deferred tools. Kept short —
every byte is paid on every turn. ``listing`` is embedded in the tool_search
description; ``listing_form`` picks the framing (per-tool forms say "skip
@@ -384,8 +362,7 @@ def assemble_tool_defs(
tool_defs: List[Dict[str, Any]],
*,
context_length: Optional[int] = None,
config: Optional[ToolSearchConfig] = None,
) -> AssemblyResult:
config: Optional[ToolSearchConfig] = None) -> AssemblyResult:
"""Return the tool-defs list the model should actually see: passthrough
when inactive, otherwise deferrable tools replaced by the three bridge
tools. Idempotent — bridge tools already present are stripped first."""
@@ -403,8 +380,7 @@ def assemble_tool_defs(
tool_defs=incoming, activated=False, deferred_count=len(deferrable),
deferred_tokens=deferrable_tokens,
threshold_tokens=int((context_length or 0) * (config.threshold_pct / 100.0)),
tier=0,
)
tier=0)
listing, listing_form = None, "none"
listing_budget = listing_token_budget(config, context_length)
@@ -416,13 +392,11 @@ def assemble_tool_defs(
logger.info(
"tool_search activated (tier %d): %d core/visible tools kept, %d deferred "
"(~%d tokens), listing %s (budget ~%d tokens)",
tier, len(visible), len(deferrable), deferrable_tokens, listing_form, listing_budget,
)
tier, len(visible), len(deferrable), deferrable_tokens, listing_form, listing_budget)
return AssemblyResult(
tool_defs=visible + bridge, activated=True, deferred_count=len(deferrable),
deferred_tokens=deferrable_tokens, threshold_tokens=listing_budget,
tier=tier, listing_form=listing_form,
)
tier=tier, listing_form=listing_form)
def is_bridge_tool(name: str) -> bool:
@@ -443,8 +417,7 @@ def _shared_tool_record(entry: CatalogEntry) -> Dict[str, Any]:
"source": entry.source,
"source_name": entry.source_name,
"description": (entry.description or "")[:400], # cap chatty MCP descriptions
"required": [r[:64] for r in required if isinstance(r, str)][:32],
}
"required": [r[:64] for r in required if isinstance(r, str)][:32]}
def _available_source_summary(catalog: List[CatalogEntry]) -> List[Dict[str, Any]]:
@@ -519,8 +492,7 @@ def dispatch_tool_search(args: Dict[str, Any],
"This query returned no lexical matches, but the sources above "
"are connected and their tools remain available. Retry "
"tool_search with the service name plus a concrete action or "
"object before concluding the capability is unavailable."
)
"object before concluding the capability is unavailable.")
results.append(group)
return json.dumps({
"queries": queries,
@@ -560,16 +532,13 @@ def dispatch_tool_describe(args: Dict[str, Any],
if fn is not None:
tools[name] = {
"description": fn.get("description", ""),
"parameters": fn.get("parameters", {}),
}
"parameters": fn.get("parameters", {})}
elif _registry_entry(name) is not None and not is_deferrable_tool_name(
name, load_config_readonly().effective_defer_tools
):
name, load_config_readonly().effective_defer_tools):
# Registered but bridge/core/GUI-surface: a real name, wrong door.
errors[name] = (
f"'{name}' is not a deferrable tool. If you see it in the tools list "
"already, call it directly; otherwise check the spelling against tool_search."
)
"already, call it directly; otherwise check the spelling against tool_search.")
else:
not_found.append(name)
@@ -590,8 +559,7 @@ def scoped_deferrable_names(tool_defs: List[Dict[str, Any]]) -> frozenset[str]:
defer_tools = load_config_readonly().effective_defer_tools
return frozenset(
name for name in _tool_def_names(tool_defs)
if name and is_deferrable_tool_name(name, defer_tools)
)
if name and is_deferrable_tool_name(name, defer_tools))
def resolve_underlying_call(args: Dict[str, Any]) -> Tuple[Optional[str], Dict[str, Any], Optional[str]]:
@@ -616,34 +584,16 @@ def resolve_underlying_call(args: Dict[str, Any]) -> Tuple[Optional[str], Dict[s
if not is_deferrable_tool_name(name, load_config_readonly().effective_defer_tools):
return None, {}, (
f"'{name}' is not a deferrable tool. If it appears in the model-facing tools "
"list already, call it directly instead of via tool_call."
)
"list already, call it directly instead of via tool_call.")
return name, raw_args, None
__all__ = [
"TOOL_SEARCH_NAME",
"TOOL_DESCRIBE_NAME",
"TOOL_CALL_NAME",
"BRIDGE_TOOL_NAMES",
"ToolSearchConfig",
"CatalogEntry",
"AssemblyResult",
"load_config",
"is_deferrable_tool_name",
"classify_tools",
"estimate_tokens_from_schemas",
"should_activate",
"build_catalog",
"build_catalog_listing_with_form",
"listing_token_budget",
"search_catalog",
"bridge_tool_schemas",
"assemble_tool_defs",
"is_bridge_tool",
"dispatch_tool_search",
"dispatch_tool_describe",
"resolve_underlying_call",
"scoped_deferrable_names",
"validate_deferred_call_args",
"TOOL_SEARCH_NAME", "TOOL_DESCRIBE_NAME", "TOOL_CALL_NAME", "BRIDGE_TOOL_NAMES",
"ToolSearchConfig", "CatalogEntry", "AssemblyResult", "load_config",
"is_deferrable_tool_name", "classify_tools", "estimate_tokens_from_schemas",
"should_activate", "build_catalog", "build_catalog_listing_with_form", "listing_token_budget",
"search_catalog", "bridge_tool_schemas", "assemble_tool_defs", "is_bridge_tool",
"dispatch_tool_search", "dispatch_tool_describe", "resolve_underlying_call",
"scoped_deferrable_names", "validate_deferred_call_args",
]

View File

@@ -122,8 +122,7 @@ def build_catalog(tool_defs: List[Dict[str, Any]]) -> List[CatalogEntry]:
schema=td,
source=source,
source_name=source_name,
_tokens=_tokenize(_entry_search_text(td, source_label)),
))
_tokens=_tokenize(_entry_search_text(td, source_label))))
return catalog
@@ -167,8 +166,7 @@ def search_catalog(
query: str,
limit: int = 5,
*,
corpus_stats: Optional[_CorpusStats] = None,
) -> List[CatalogEntry]:
corpus_stats: Optional[_CorpusStats] = None) -> List[CatalogEntry]:
"""Top-``limit`` catalog entries for ``query`` by BM25 (exact name match
ranks first). Falls back to a name-substring match only when NO query
token appears in any document (e.g. "hub" vs ``github_*``); the IDF
@@ -226,10 +224,7 @@ def _listing_group_label(source_name: str) -> str:
def build_catalog_listing_with_form(
deferrable: List[Dict[str, Any]],
*,
max_tokens: int = 4000,
) -> Tuple[Optional[str], str]:
deferrable: List[Dict[str, Any]], *, max_tokens: int = 4000) -> Tuple[Optional[str], str]:
"""Render the skills-style deferred-catalog manifest: ``- name: short desc``
lines grouped under a heading per source (MCP server / plugin toolset).

View File

@@ -25,8 +25,7 @@ def _schema_for_local_validation(node: Any) -> Any:
# Literal keywords hold instance data, not schemas: copy byte-for-byte.
normalized = {
key: copy.deepcopy(value) if key in _SCHEMA_LITERAL_KEYS else _schema_for_local_validation(value)
for key, value in node.items() if key != "nullable"
}
for key, value in node.items() if key != "nullable"}
if node.get("nullable") is not True:
return normalized
schema_type = normalized.get("type")
@@ -56,8 +55,7 @@ def _schema_has_external_ref(node: Any) -> bool:
return any(
_schema_has_external_ref(value)
for key, value in node.items()
if key not in _SCHEMA_LITERAL_KEYS
)
if key not in _SCHEMA_LITERAL_KEYS)
def _validation_path(error: Any) -> str:
@@ -76,8 +74,7 @@ def _validation_path(error: Any) -> str:
def _validation_error(message: str, *, path: str, constraint: str, parameters: Any) -> str:
return tool_error(
message, path=path, constraint=constraint, parameters=parameters,
hint="Retry tool_call with 'arguments' matching the parameters schema above.",
)
hint="Retry tool_call with 'arguments' matching the parameters schema above.")
def validate_deferred_call_args(name: str, args: Dict[str, Any]) -> Optional[str]:
@@ -106,8 +103,7 @@ def validate_deferred_call_args(name: str, args: Dict[str, Any]) -> Optional[str
return _validation_error(
f"tool_call to '{name}' is missing required argument(s): "
f"{', '.join(missing)}. The tool was NOT invoked.",
path="arguments", constraint="required", parameters=params,
)
path="arguments", constraint="required", parameters=params)
validation_schema = _schema_for_local_validation(params)
if _schema_has_external_ref(validation_schema):
@@ -143,8 +139,7 @@ def validate_deferred_call_args(name: str, args: Dict[str, Any]) -> Optional[str
return _validation_error(
f"tool_call to '{name}' failed argument validation at {path} "
f"({constraint}): {detail}. The tool was NOT invoked.",
path=path, constraint=constraint, parameters=params,
)
path=path, constraint=constraint, parameters=params)
except Exception: # pragma: no cover — never block dispatch on validator bugs
logger.debug("validate_deferred_call_args failed for %s", name, exc_info=True)
return None