emma-hermes/tools
Teknium 74d0b392e7
feat(x_search): gated X (Twitter) search tool with OAuth-or-API-key auth (#26763)
* feat(x_search): gated X (Twitter) search tool with OAuth-or-API-key auth

Salvages tools/x_search_tool.py from the closed PR #10786 (originally by
@Jaaneek) and reworks its credential resolution so the tool registers
when EITHER xAI credential path is available:

* XAI_API_KEY (paid xAI API key) is set in ~/.hermes/.env or the env, OR
* The user is signed in via xAI Grok OAuth — SuperGrok subscription —
  i.e. hermes auth add xai-oauth has been run

Both paths route through xAI's built-in x_search Responses tool at
https://api.x.ai/v1/responses. When both credentials exist OAuth wins,
matching tools/xai_http.py's existing preference order (uses SuperGrok
quota instead of paid API spend).

The check_fn calls resolve_xai_http_credentials() which auto-refreshes
the OAuth access token if it's within the refresh skew window, so a
True return means the bearer is fetchable AND non-empty.

Wiring
- tools/x_search_tool.py — new tool, ~370 LOC. Schema gated by check_fn,
  bearer resolved per-call so revoked OAuth surfaces a clean tool_error
  rather than an HTTP 401.
- toolsets.py — "x_search" toolset def. NOT added to _HERMES_CORE_TOOLS;
  users opt in via hermes tools.
- hermes_cli/tools_config.py — CONFIGURABLE_TOOLSETS entry + TOOL_CATEGORIES
  block with two provider options (OAuth + API key) sharing the existing
  xai_grok post_setup hook for credential bootstrap.
- hermes_cli/config.py — DEFAULT_CONFIG["x_search"] with model /
  timeout_seconds / retries. Additive nested key; no version bump.
- tests/tools/test_x_search_tool.py — 13 tests covering HTTP shape,
  handle validation, citation extraction, 4xx/5xx/timeout handling,
  and the full credential-resolution matrix (OAuth-only, API-key-only,
  both-set, neither-set, resolver-raises, config overrides, registry
  registration).
- website/docs/guides/xai-grok-oauth.md — adds X Search to the
  direct-to-xAI tools section with off-by-default note.
- website/docs/user-guide/features/tools.md — new row in the tools table.

Off by default — users enable via `hermes tools` → 🐦 X (Twitter) Search.
Schema only appears to the model when xAI credentials are configured.

Co-authored-by: Jaaneek <Jaaneek@users.noreply.github.com>

* docs(x_search): add dedicated feature page + reference entries

- website/docs/user-guide/features/x-search.md (new) — full feature
  walkthrough: authentication, enablement, configuration, parameters,
  returned fields, example, troubleshooting, see-also links.
- website/docs/reference/tools-reference.md — new "x_search" toolset
  section with parameter docs and credential gating note.
- website/docs/reference/toolsets-reference.md — new row in the
  toolset catalog table.
- website/sidebars.ts — wires the new feature page under
  Media & Web, after web-search.

---------

Co-authored-by: Jaaneek <Jaaneek@users.noreply.github.com>
2026-05-16 00:58:27 -07:00
..
browser_providers fix(tools): wrap browser provider network calls with error handling 2026-05-15 01:53:06 -07:00
computer_use fix(async): close unscheduled coroutines in all threadsafe bridges (#26584) 2026-05-15 14:00:01 -07:00
environments fix(windows): stop spamming cwd-missing + tirith-spawn warnings on every terminal call 2026-05-15 16:25:31 -07:00
neutts_samples
__init__.py
ansi_strip.py
approval.py fix(env-flags): widen truthy-only session env checks to sibling sites 2026-05-15 12:35:07 -07:00
binary_extensions.py
browser_camofox.py
browser_camofox_state.py
browser_cdp_tool.py fix(async): close unscheduled coroutines in all threadsafe bridges (#26584) 2026-05-15 14:00:01 -07:00
browser_dialog_tool.py
browser_supervisor.py fix(async): close unscheduled coroutines in all threadsafe bridges (#26584) 2026-05-15 14:00:01 -07:00
browser_tool.py feat: wire ensure_dependency into TUI and browser tool call sites 2026-05-15 14:45:43 -07:00
budget_config.py chore: remove Atropos RL environments and tinker-atropos integration (#26106) 2026-05-15 10:36:38 +05:30
checkpoint_manager.py
clarify_gateway.py
clarify_tool.py
code_execution_tool.py
computer_use_tool.py
credential_files.py
cronjob_tools.py fix(env-flags): widen truthy-only session env checks to sibling sites 2026-05-15 12:35:07 -07:00
debug_helpers.py
delegate_tool.py fix(delegate): guard heartbeat join against unstarted thread 2026-05-15 15:09:55 -07:00
discord_tool.py
env_passthrough.py
feishu_doc_tool.py
feishu_drive_tool.py
file_operations.py fix(lsp): shift baseline diagnostics into post-edit coordinates (#25978) 2026-05-14 15:56:07 -07:00
file_state.py
file_tools.py
fuzzy_match.py
homeassistant_tool.py
image_generation_tool.py feat(image-gen): actionable setup message when no FAL backend is reachable (#26222) 2026-05-15 01:33:13 -07:00
interrupt.py
kanban_tools.py
lazy_deps.py fix(deps): pin brotlicffi so aiohttp can decode Discord's Brotli attachments 2026-05-14 22:36:46 -07:00
managed_tool_gateway.py
mcp_oauth.py
mcp_oauth_manager.py
mcp_tool.py fix(async): close unscheduled coroutines in all threadsafe bridges (#26584) 2026-05-15 14:00:01 -07:00
memory_tool.py fix(memory): eliminate TOCTOU race in Windows file lock creation 2026-05-15 15:28:18 -07:00
microsoft_graph_auth.py
microsoft_graph_client.py
mixture_of_agents_tool.py
neutts_synth.py
openrouter_client.py
osv_check.py
patch_parser.py
path_security.py
process_registry.py fix(tui): autonomous background process completion notifications (#26071) (#26327) 2026-05-15 19:31:00 +05:30
registry.py security: sanitize tool error strings before injecting into model context (#26823) 2026-05-16 00:57:39 -07:00
schema_sanitizer.py
send_message_tool.py
session_search_tool.py
skill_manager_tool.py
skill_provenance.py
skill_usage.py
skills_guard.py feat(skills-hub): add huggingface/skills as trusted default tap (#2549) 2026-05-15 01:25:33 -07:00
skills_hub.py feat(skills-hub): add huggingface/skills as trusted default tap (#2549) 2026-05-15 01:25:33 -07:00
skills_sync.py
skills_tool.py fix(env-flags): widen truthy-only session env checks to sibling sites 2026-05-15 12:35:07 -07:00
slash_confirm.py fix(async): close unscheduled coroutines in all threadsafe bridges (#26584) 2026-05-15 14:00:01 -07:00
terminal_tool.py fix(env-flags): widen truthy-only session env checks to sibling sites 2026-05-15 12:35:07 -07:00
tirith_security.py fix(windows): silence tirith-unavailable banner + skip install/spawn attempts on unsupported platforms (#26718) 2026-05-15 20:29:28 -07:00
todo_tool.py
tool_backend_helpers.py
tool_output_limits.py
tool_result_storage.py
transcription_tools.py fix(xai-http): preserve ~/.hermes/.env fallback and XAI_STT_BASE_URL precedence 2026-05-15 12:11:32 -07:00
tts_tool.py feat(xai-oauth): add xAI Grok OAuth (SuperGrok Subscription) provider 2026-05-15 12:11:32 -07:00
url_safety.py fix(url-safety): allow only http and https schemes 2026-05-15 01:52:48 -07:00
video_generation_tool.py feat(video_gen): unified video_generate tool with pluggable provider backends (#25126) 2026-05-13 16:39:41 -07:00
vision_tools.py
voice_mode.py
web_tools.py fix(tools): add return_exceptions to asyncio.gather in web_tools 2026-05-15 01:50:41 -07:00
website_policy.py
x_search_tool.py feat(x_search): gated X (Twitter) search tool with OAuth-or-API-key auth (#26763) 2026-05-16 00:58:27 -07:00
xai_http.py fix(xai-http): preserve ~/.hermes/.env fallback and XAI_STT_BASE_URL precedence 2026-05-15 12:11:32 -07:00
yuanbao_tools.py