BrowserUse_and_ComputerUse_.../gateway/platforms
Teknium dd60bcbfb7
feat: OpenAI-compatible API server + WhatsApp configurable reply prefix (#1756)
* feat: OpenAI-compatible API server platform adapter

Salvaged from PR #956, updated for current main.

Adds an HTTP API server as a gateway platform adapter that exposes
hermes-agent via the OpenAI Chat Completions and Responses APIs.
Any OpenAI-compatible frontend (Open WebUI, LobeChat, LibreChat,
AnythingLLM, NextChat, ChatBox, etc.) can connect by pointing at
http://localhost:8642/v1.

Endpoints:
- POST /v1/chat/completions  — stateless Chat Completions API
- POST /v1/responses         — stateful Responses API with chaining
- GET  /v1/responses/{id}    — retrieve stored response
- DELETE /v1/responses/{id}  — delete stored response
- GET  /v1/models            — list hermes-agent as available model
- GET  /health               — health check

Features:
- Real SSE streaming via stream_delta_callback (uses main's streaming)
- In-memory LRU response store for Responses API conversation chaining
- Named conversations via 'conversation' parameter
- Bearer token auth (optional, via API_SERVER_KEY)
- CORS support for browser-based frontends
- System prompt layering (frontend system messages on top of core)
- Real token usage tracking in responses

Integration points:
- Platform.API_SERVER in gateway/config.py
- _create_adapter() branch in gateway/run.py
- API_SERVER_* env vars in hermes_cli/config.py
- Env var overrides in gateway/config.py _apply_env_overrides()

Changes vs original PR #956:
- Removed streaming infrastructure (already on main via stream_consumer.py)
- Removed Telegram reply_to_mode (separate feature, not included)
- Updated _resolve_model() -> _resolve_gateway_model()
- Updated stream_callback -> stream_delta_callback
- Updated connect()/disconnect() to use _mark_connected()/_mark_disconnected()
- Adapted to current Platform enum (includes MATTERMOST, MATRIX, DINGTALK)

Tests: 72 new tests, all passing
Docs: API server guide, Open WebUI integration guide, env var reference

* feat(whatsapp): make reply prefix configurable via config.yaml

Reworked from PR #1764 (ifrederico) to use config.yaml instead of .env.

The WhatsApp bridge prepends a header to every outgoing message.
This was hardcoded to '⚕ *Hermes Agent*'. Users can now customize
or disable it via config.yaml:

  whatsapp:
    reply_prefix: ''                     # disable header
    reply_prefix: '🤖 *My Bot*\n───\n'  # custom prefix

How it works:
- load_gateway_config() reads whatsapp.reply_prefix from config.yaml
  and stores it in PlatformConfig.extra['reply_prefix']
- WhatsAppAdapter reads it from config.extra at init
- When spawning bridge.js, the adapter passes it as
  WHATSAPP_REPLY_PREFIX in the subprocess environment
- bridge.js handles undefined (default), empty (no header),
  or custom values with \\n escape support
- Self-chat echo suppression uses the configured prefix

Also fixes _config_version: was 9 but ENV_VARS_BY_VERSION had a
key 10 (TAVILY_API_KEY), so existing users at v9 would never be
prompted for Tavily. Bumped to 10 to close the gap. Added a
regression test to prevent this from happening again.

Credit: ifrederico (PR #1764) for the bridge.js implementation
and the config version gap discovery.

---------

Co-authored-by: Test <test@test.com>
2026-03-17 10:44:37 -07:00
..
__init__.py Enhance CLI with multi-platform messaging integration and configuration management 2026-02-02 19:01:51 -08:00
ADDING_A_PLATFORM.md docs: finish cron terminology cleanup 2026-03-14 19:20:58 -07:00
api_server.py feat: OpenAI-compatible API server + WhatsApp configurable reply prefix (#1756) 2026-03-17 10:44:37 -07:00
base.py feat(gateway): inject reply-to message context for out-of-session replies (#1594) 2026-03-17 02:31:27 -07:00
dingtalk.py fix(dingtalk): requirements check passes with only one credential set 2026-03-17 03:50:45 -07:00
discord.py Merge pull request #1661 from NousResearch/fix/discord-thread-persistence 2026-03-17 02:27:09 -07:00
email.py fix: email send_typing metadata + ☤ Hermes staff symbol (#1431, #1420) 2026-03-17 02:37:40 -07:00
homeassistant.py fix: Home Assistant event filtering now closed by default (#1169) 2026-03-13 07:40:38 -07:00
matrix.py fix(gateway): SMS persistent HTTP session + Matrix MIME media types 2026-03-17 04:35:14 -07:00
mattermost.py fix(gateway): Matrix and Mattermost never report as connected 2026-03-17 04:01:02 -07:00
signal.py fix(signal): align send() signature with base class (content, reply_to, metadata) 2026-03-10 15:18:26 -07:00
slack.py refactor: centralize slash command registry (#1603) 2026-03-16 23:21:03 -07:00
sms.py fix(gateway): SMS persistent HTTP session + Matrix MIME media types 2026-03-17 04:35:14 -07:00
telegram.py fix(telegram): aggregate split text messages before dispatching (#1674) 2026-03-17 02:49:57 -07:00
whatsapp.py feat: OpenAI-compatible API server + WhatsApp configurable reply prefix (#1756) 2026-03-17 10:44:37 -07:00