feat(zulip): add Zulip channel plugin#22308
feat(zulip): add Zulip channel plugin#22308emadomedher wants to merge 24 commits intoopenclaw:mainfrom
Conversation
Adds support for Whisper STT (https://github.com/openai/whisper), OpenAI's open-source speech recognition model. Features: - Self-hosted Whisper support (whisper-asr-webservice, faster-whisper, etc.) - OpenAI-compatible API endpoint - Automatic language detection or explicit language hints - Multiple model sizes (tiny, base, small, medium, large, large-v2, large-v3) - Works with cloud OpenAI Whisper or local instances Configuration example: ```yaml tools: media: audio: enabled: true models: - provider: whisper baseUrl: http://localhost:8200/v1 model: whisper-1 language: en ``` Default baseUrl: http://localhost:8200/v1 Default model: whisper-1
Adds support for Chatterbox TTS (https://github.com/resemble-ai/chatterbox), a state-of-the-art open-source text-to-speech system that runs locally. Features: - OpenAI-compatible API endpoint support - Voice cloning via voice library - Multilingual support (23+ languages) - Configurable parameters: exaggeration, CFG weight, speed - Supports Chatterbox, Chatterbox-Turbo, and Chatterbox-Multilingual models Configuration example: ```yaml messages: tts: provider: chatterbox chatterbox: enabled: true baseUrl: http://localhost:4123 voice: default model: chatterbox-turbo ``` Closes #XXX
Adds support for Piper TTS (https://github.com/rhasspy/piper), a fast, local, and privacy-focused neural text-to-speech system. Features: - OpenAI-compatible API endpoint support - High-quality neural voices (60+ languages) - Lightweight and fast inference - Runs completely offline/local - Configurable voice parameters (speed, noise, etc.) Configuration example: ```yaml messages: tts: provider: piper piper: enabled: true baseUrl: http://localhost:8101 voice: en_US-lessac-high lengthScale: 1.0 ```
@vector-im/matrix-bot-sdk returns {data: Buffer, contentType: string}
instead of raw Buffer. Extract the data property and preserve contentType.
- Full voice conversation loop (audio reception, STT, agent response, TTS, playback) - Proactive speaking via HTTP endpoint (POST /mumble/speak) - Voice parameter support for different TTS voices - Sender allowlist for multi-bot environments - High-quality audio (128kbps Opus, 10ms frames, 'audio' mode) - Timeout-based silence detection (500ms) - Comprehensive README with configuration examples Technical details: - Uses @tf2pickup-org/mumble-client (fork with full audio support) - Whisper STT integration (OpenAI-compatible API) - Kokoro TTS integration (67 voices, blending support) - @discordjs/opus for native Opus encoding - Linear interpolation resampling (24kHz → 48kHz) Tested with Mumble v1.5.857, Node.js v24
Resolved conflicts: - extensions/matrix/src/matrix/monitor/media.ts: accepted upstream's cleaner response handling - src/media-understanding/providers/index.ts: merged both whisperProvider and zaiProvider
- Renamed skyline-mcp → mcp-client for generic MCP support
- Supports multiple simultaneous MCP server connections
- Compatible with any MCP server (filesystem, GitHub, Postgres, Slack, Skyline, etc.)
- Per-server tool prefixes to avoid naming conflicts
- Auto-reconnection support
- Updated plugin API for OpenClaw v2026.2.9 compatibility
- Changed handler → execute method
- Added toolCallId parameter
- Fixed return format (content + details)
Tested with Skyline MCP server (31 tools loaded successfully).
Example config:
{
"servers": {
"skyline": { "command": "skyline-mcp", ... },
"filesystem": { "command": "mcp-server-filesystem", ... }
}
}
This enables OpenClaw to connect to the entire MCP ecosystem.
Major Features: - Multi-server support with error isolation - Auto ext_ prefix prevents native tool collisions - Pre-flight command validation (no uncaught exceptions) - Health monitoring with auto-recovery (60s intervals) - Rate limiting (concurrent + per-minute) - Metrics & observability (/mcp-metrics command) - Protocol completeness (resources, prompts) - Hot reload capability (/mcp-reload command) - Comprehensive test suite (13 test cases) P0 Features (Critical): ✅ Auto ext_ prefix for collision prevention ✅ MCP-to-MCP collision detection ✅ Pre-flight command check ✅ Error isolation (one bad server != crash) ✅ Tool discovery (/mcp command) ✅ Graceful degradation P1 Features (Should Have): ✅ Expanded config validation ✅ Health monitoring & auto-restart ✅ Resource cleanup (no zombie processes) ✅ Basic test coverage P2 Features (Nice to Have): ✅ Rate limiting (maxConcurrent, maxPerMinute) ✅ Metrics endpoint (/mcp-metrics) ✅ Resources & Prompts support ✅ Hot reload (/mcp-reload) Testing: - Crash-tested with invalid configurations - Verified error isolation (3/4 servers working) - Confirmed zombie process cleanup - Production deployment verified (51 tools loaded) Documentation: - Comprehensive README (666 lines) - Implementation summary with lessons learned - Troubleshooting guide - Configuration examples Files: - index.ts (995 lines) - index.test.ts (219 lines, 13 tests) - README.md (updated) - IMPLEMENTATION-SUMMARY.md (new) Status: Production Ready ✅
feat: Production-ready MCP client plugin
- Add duckduckgo as 4th search provider (no API key required)
- Uses official ddgs CLI (pip install ddgs)
- Supports Tor proxy with 'tor' convenience alias
- Add region, safesearch, and timelimit configuration options
- Maintain same caching and output format as other providers
- Auto-detects ddgs CLI in common installation paths
Configuration example:
tools:
web:
search:
provider: duckduckgo
duckduckgo:
proxy: tor
region: wt-wt
safesearch: moderate
Benefits:
- Zero-cost search option (vs Brave $5-15/month)
- Privacy-first with built-in Tor integration
- No API key registration required
- Same UX as existing providers
Technical details:
- Searches: ~/.local/bin/ddgs, ~/.openclaw/.venv/bin/ddgs, system paths
- Calls ddgs CLI with JSON output (-o flag)
- Maps ddgs output format to OpenClaw format
- Adds duckduckgo config schema validation
Use proper TypeScript types instead of 'as any' casts.
Keep both DuckDuckGo integration and upstream Grok improvements
Changes: - extensions/mumble/package.json: @tf2pickup-org/mumble-client ^0.12.5 - Updated pnpm-lock.yaml This makes the fork buildable without requiring a local mumble-client-fork directory.
Adds first-party support for Zulip, the open-source threaded team chat. Features: - Real-time message polling via Zulip event queue API - Stream and DM support with topics - Media upload and attachments - Multiple account configuration - DM/group allowlist policies - @-mention requirement in streams - Full config schema with environment variable support Follows the same patterns as mattermost extension.
| runtime.system.enqueueSystemEvent(`${inboundLabel}: ${preview}`, { | ||
| sessionKey, | ||
| contextKey: `zulip:message:${chatId}:${message.id}`, | ||
| }); |
There was a problem hiding this comment.
Check that security policies (dmPolicy, groupPolicy, requireMention) are being enforced. The message is routed via enqueueSystemEvent without explicitly passing sender ID or checking policies. Mattermost's monitor explicitly checks resolveRequireMention and filters before routing (extensions/mattermost/src/mattermost/monitor.ts:550-573). Verify the routing system automatically applies channel security configs based on the sessionKey.
Prompt To Fix With AI
This is a comment left during a code review.
Path: extensions/zulip/src/zulip/monitor.ts
Line: 171-174
Comment:
Check that security policies (dmPolicy, groupPolicy, requireMention) are being enforced. The message is routed via `enqueueSystemEvent` without explicitly passing sender ID or checking policies. Mattermost's monitor explicitly checks `resolveRequireMention` and filters before routing (`extensions/mattermost/src/mattermost/monitor.ts:550-573`). Verify the routing system automatically applies channel security configs based on the sessionKey.
How can I resolve this? If you propose a fix, please make it concise.| "type": "git", | ||
| "url": "https://github.com/myka/openclaw-zulip.git" | ||
| } |
There was a problem hiding this comment.
Repository URL points to myka/openclaw-zulip but this PR is being submitted to openclaw/openclaw. Update to match the actual repository or remove if this will be published as part of the main openclaw repo.
Prompt To Fix With AI
This is a comment left during a code review.
Path: extensions/zulip/package.json
Line: 56-58
Comment:
Repository URL points to `myka/openclaw-zulip` but this PR is being submitted to `openclaw/openclaw`. Update to match the actual repository or remove if this will be published as part of the main openclaw repo.
How can I resolve this? If you propose a fix, please make it concise.| const fetchImpl = params.fetchImpl ?? fetch; | ||
|
|
||
| // Zulip uses HTTP Basic Auth with email:api_key | ||
| const authHeader = `Basic ${Buffer.from(`${email}:${apiKey}`).toString("base64")}`; |
There was a problem hiding this comment.
Using Buffer in client code assumes Node.js environment. Consider using btoa() or a platform-agnostic base64 encoding approach for better compatibility, or document that this plugin requires Node.js runtime.
Prompt To Fix With AI
This is a comment left during a code review.
Path: extensions/zulip/src/zulip/client.ts
Line: 110
Comment:
Using `Buffer` in client code assumes Node.js environment. Consider using `btoa()` or a platform-agnostic base64 encoding approach for better compatibility, or document that this plugin requires Node.js runtime.
How can I resolve this? If you propose a fix, please make it concise.|
This pull request has been automatically marked as stale due to inactivity. |
|
Please make this as a third-party plugin that you maintain yourself in your own repo. Docs: https://docs.openclaw.ai/plugin. Feel free to open a PR after to add it to our community plugins page: https://docs.openclaw.ai/plugins/community |
Summary
Adds first-party support for Zulip, the open-source threaded team chat.
Features
Configuration
{ "channels": { "zulip": { "enabled": true, "baseUrl": "https://your-org.zulipchat.com", "email": "[email protected]", "apiKey": "your-api-key", "requireMention": true, "dmPolicy": "pairing" } } }Implementation
Follows the same patterns as the Mattermost extension:
Testing
Tested with self-hosted Zulip instance with 9 agent accounts.
Happy to make any changes needed!
Greptile Summary
Adds first-party Zulip channel plugin following the established Mattermost extension patterns. The implementation provides real-time message polling via Zulip's event queue API, stream and DM support with topics, media uploads, and multiple account configuration.
Key Changes:
extensions/zulip/with complete TypeScript implementationNote on PR Scope:
This PR includes unrelated upstream changes (MCP client extension, Mumble extension, DuckDuckGo search provider, TTS providers, and other core changes). These are from upstream syncs (
be214626and earlier commits) merged into the author's feature branch. The actual Zulip implementation is isolated to commit4a4c8b9ewhich only touchesextensions/zulip/files.Areas for verification:
monitor.ts:171-174usesenqueueSystemEventbut doesn't explicitly pass sender IDs or check security policies (dmPolicy, groupPolicy, requireMention) before routing. The README claims these policies are supported, but the monitor implementation doesn't show where mention detection or allowlist filtering occurs. This differs from Mattermost's approach which explicitly checks mentions and policies before routing (seeextensions/mattermost/src/mattermost/monitor.ts:550-573).Confidence Score: 3/5
extensions/zulip/src/zulip/monitor.tsfor security policy enforcement verificationLast reviewed commit: 4a4c8b9