feat: show estimated tool token context in hermes tools checklist (#3805)
* feat: show estimated tool token context in hermes tools checklist Adds a live token estimate indicator to the bottom of the interactive tool configuration checklist (hermes tools / hermes setup). As users toggle toolsets on/off, the total estimated context cost updates in real time. Implementation: - tools/registry.py: Add get_schema() for check_fn-free schema access - hermes_cli/curses_ui.py: Add optional status_fn callback to curses_checklist — renders at bottom-right of terminal, stays fixed while items scroll - hermes_cli/tools_config.py: Add _estimate_tool_tokens() using tiktoken (cl100k_base, already installed) to count tokens in the JSON-serialised OpenAI-format tool schemas. Results are cached per-process. The status function deduplicates overlapping tools (e.g. browser includes web_search) for accurate totals. - 12 new tests covering estimation, caching, graceful degradation when tiktoken is unavailable, status_fn wiring, deduplication, and the numbered fallback display * fix: use effective toolsets (includes plugins) for token estimation index mapping The status_fn closure built ts_keys from CONFIGURABLE_TOOLSETS but the checklist uses _get_effective_configurable_toolsets() which appends plugin toolsets. With plugins present, the indices would mismatch, causing IndexError when selecting a plugin toolset.
This commit is contained in:
@@ -149,6 +149,15 @@ class ToolRegistry:
|
||||
"""Return sorted list of all registered tool names."""
|
||||
return sorted(self._tools.keys())
|
||||
|
||||
def get_schema(self, name: str) -> Optional[dict]:
|
||||
"""Return a tool's raw schema dict, bypassing check_fn filtering.
|
||||
|
||||
Useful for token estimation and introspection where availability
|
||||
doesn't matter — only the schema content does.
|
||||
"""
|
||||
entry = self._tools.get(name)
|
||||
return entry.schema if entry else None
|
||||
|
||||
def get_toolset_for_tool(self, name: str) -> Optional[str]:
|
||||
"""Return the toolset a tool belongs to, or None."""
|
||||
entry = self._tools.get(name)
|
||||
|
||||
Reference in New Issue
Block a user