hermes-agent/tools
ethernet 2d71e2f1e4 perf(tools): text prefilter before AST parse in tool discovery
`_module_registers_tools()` reads each `tools/*.py` file and fully
AST-parses it to check for a top-level `registry.register()` call.
90 files are scanned on every process start — but only 32 actually
register tools.

Add a cheap text prefilter: after reading the file (which we need to
do anyway for AST), check that both `"registry"` and `"register"`
appear in the source before calling `ast.parse`. A file with a
top-level `registry.register()` call must contain both strings, so
this is a perfect superset — zero false negatives. 50 of 90 files
skip the AST parse entirely.

The `source=` parameter is not threaded through `discover_builtin_tools`;
the prefilter lives entirely inside `_module_registers_tools`, keeping
the public API unchanged.

Benchmark (median of 10 runs, scanning 90 files):

  before (read + ast.parse all):  305.9ms
  after  (text prefilter + ast):   187.8ms
  speedup: 1.6x  (118ms saved)

Identical module set: 32 modules, same names, same order.
2026-07-13 18:14:15 -04:00
..
computer_use
…
environments fix(windows): survive broken Git Bash login shells 2026-07-13 16:14:18 -04:00
neutts_samples
…
__init__.py
…
ansi_strip.py
…
approval.py fix(approval): scope smart deny owner overrides to one operation 2026-07-13 04:31:55 -07:00
async_delegation.py fix(delegation): harden durable completion delivery 2026-07-13 07:28:21 -07:00
binary_extensions.py
…
blueprints.py
…
browser_camofox.py
…
browser_camofox_state.py
…
browser_cdp_tool.py
…
browser_dialog_tool.py
…
browser_supervisor.py
…
browser_tool.py
…
budget_config.py
…
checkpoint_manager.py
…
clarify_gateway.py
…
clarify_tool.py
…
close_terminal_tool.py
…
code_execution_tool.py
…
computer_use_tool.py
…
credential_files.py
…
cronjob_tools.py fix(cron): stop the ticker from stalling forever on a wedged jobs lock (#60703) (#60855) 2026-07-08 05:13:18 -07:00
daemon_pool.py
…
debug_helpers.py
…
delegate_tool.py fix(runtime): preserve resolved fork metadata 2026-07-10 18:50:28 +05:30
discord_tool.py fix(discord): bound REST response reads 2026-07-07 02:40:04 -07:00
env_passthrough.py
…
env_probe.py
…
fal_common.py
…
feishu_doc_tool.py
…
feishu_drive_tool.py
…
file_operations.py fix(windows): bash-safe snapshot paths after #63113 2026-07-13 01:59:58 -04:00
file_state.py
…
file_tools.py fix(tools): resolve MSYS paths in file tools on Windows 2026-07-10 01:54:51 -05:00
fuzzy_match.py
…
homeassistant_tool.py
…
hook_output_spill.py
…
image_generation_tool.py fix(deepinfra): harden multimodal provider routing 2026-07-14 02:59:39 +05:30
image_source.py
…
interrupt.py
…
kanban_tools.py fix(kanban): harden durable artifact handoff 2026-07-12 23:09:41 -07:00
lazy_deps.py fix(feishu): ship Channel signaling SDK support 2026-07-09 20:31:49 -07:00
managed_tool_gateway.py
…
mcp_oauth.py
…
mcp_oauth_manager.py
…
mcp_stdio_watchdog.py fix(mcp): guard POSIX-only kill primitives in stdio watchdog for the Windows footgun linter 2026-07-07 15:16:00 -07:00
mcp_tool.py Handle minimal MCP server fakes 2026-07-07 15:16:00 -07:00
memory_tool.py fix: default memory null target to memory store (#46356) 2026-07-07 02:10:43 -07:00
microsoft_graph_auth.py
…
microsoft_graph_client.py
…
neutts_synth.py
…
openrouter_client.py
…
osv_check.py
…
patch_parser.py fix(patch): ignore inert context-only hunks (#63678) 2026-07-13 02:42:18 -07:00
path_security.py
…
process_registry.py feat(delegation): persist background completions 2026-07-13 07:28:21 -07:00
project_tools.py
…
read_extract.py
…
read_terminal_tool.py
…
registry.py perf(tools): text prefilter before AST parse in tool discovery 2026-07-13 18:14:15 -04:00
schema_sanitizer.py fix(schema): preserve multi-type arrays as anyOf instead of dropping branches 2026-07-07 02:52:17 -07:00
send_message_tool.py feat(gateway): attach MEDIA: caption to the media bubble on standalone sends 2026-07-09 15:38:32 +05:30
session_search_tool.py
…
skill_manager_tool.py fix(skills): widen call-time skills-dir resolution to skill_manager_tool 2026-07-07 05:14:00 -07:00
skill_provenance.py
…
skill_usage.py
…
skills_ast_audit.py
…
skills_guard.py fix(skills): bind bundles to exact files and origins 2026-07-12 02:59:27 -07:00
skills_hub.py fix(skills): bind bundles to exact files and origins 2026-07-12 02:59:27 -07:00
skills_sync.py
…
skills_tool.py fix: return per-call copies from the skill-discovery cache 2026-07-09 15:38:14 +05:30
slash_confirm.py
…
terminal_tool.py fix(approval): scope smart deny owner overrides to one operation 2026-07-13 04:31:55 -07:00
thread_context.py
…
threat_patterns.py
…
tirith_security.py
…
todo_tool.py
…
tool_backend_helpers.py
…
tool_output_limits.py
…
tool_result_storage.py
…
tool_search.py
…
transcription_tools.py fix(deepinfra): harden multimodal provider routing 2026-07-14 02:59:39 +05:30
tts_tool.py fix(deepinfra): align refresh and TTS availability 2026-07-14 02:59:39 +05:30
url_safety.py fix: repair URL authority whitespace before web fetches (#46363) 2026-07-07 02:39:36 -07:00
video_generation_tool.py feat(providers): Support DeepInfra as an LLM provider 2026-07-14 02:59:39 +05:30
vision_tools.py
…
voice_mode.py
…
web_tools.py fix(web): handle short extract provider results 2026-07-10 19:14:06 +05:30
website_policy.py
…
write_approval.py
…
x_search_tool.py
…
xai_http.py
…
xai_video_tools.py
…
yuanbao_tools.py
…