* feat: add web_page_bot adapter and embed widget
- Implemented a new `web_page_bot` adapter for embedding chat widgets on websites.
- Created a new YAML configuration file for `web_page_bot` with necessary metadata and execution details.
- Developed the `WebPageBotAdapter` class to handle message events and manage listeners.
- Added a JavaScript widget for embedding the chat interface, including styles and functionality for user interaction.
- Updated WebSocket handling to support the new bot adapter and manage connections.
- Enhanced the bot form to include pipeline UUID and adapter configuration in the system context.
- Introduced a new dynamic form item type for embed code in the form entity.
* feat(embed): add feedback submission and image upload functionality to embed widget
* feat(embed): add reset session endpoint for embed widget and improve WebSocket image handling
* feat(widget): remove typing indicator display logic from message handling
* fix(embed): security hardening for embed widget
- Add UUID format validation for pipeline_uuid parameters
- Add Cloudflare Turnstile integration for bot protection (optional)
- Add HMAC-signed session tokens for /messages, /reset, /feedback endpoints
- Sanitize error responses (remove internal exception details)
- Sanitize base_url before JS injection
- Fix XSS in markdown link rendering (only allow http/https protocols)
- Fix XSS in image URL extraction (only allow http/https/data protocols)
- Escape widget title in embed code snippet (HTML entity encoding)
- Remove class-level mutable default in WebPageBotAdapter
- Remove duplicate config line and console.log in widget.js
- Add turnstile_site_key and turnstile_secret_key config fields
* style: fix prettier formatting for chained replace calls
* fix(embed): declare listeners as Pydantic field in WebPageBotAdapter
The base class is a Pydantic BaseModel, so listeners must be declared
as a field (with default_factory) rather than assigned in __init__.
Also keep the __init__ to convert positional args to keyword args for
Pydantic compatibility with botmgr's calling convention.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor(embed): use bot_uuid instead of pipeline_uuid in all embed URLs
Replace pipeline_uuid with bot_uuid in all user-facing embed widget
URLs so internal pipeline identifiers are never exposed. The server
resolves bot_uuid to the owning web_page_bot, validates it is enabled
and has a pipeline bound, then routes internally using pipeline_uuid.
Add a dedicated WebSocket endpoint at /api/v1/embed/<bot_uuid>/ws/connect
instead of reusing the pipeline debug path. Wire WebPageBotAdapter to
proxy reply_message calls through the WebSocket adapter so dashboard
shows the correct adapter name while replies are still delivered.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs(embed): improve Turnstile config field descriptions
Add guidance on where to obtain the keys (Cloudflare dashboard) and
clarify that leaving them empty disables the feature.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat(embed): add multi-language support for embed widget
Add a language selector to the web_page_bot config with 8 locales
(en, zh-Hans, zh-Hant, ja, es, ru, th, vi). The backend injects the
locale into widget.js which uses a built-in i18n dictionary for all
user-facing strings (welcome message, placeholder, aria labels, error
messages, powered-by footer).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(embed): use correct select option format for language selector
Options must use name/label (i18n object) format, not value/label
(plain string), to match the dynamic form renderer.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* style(embed): adjust footer padding and link to langbot.app
Increase footer padding for more breathing room from the bottom edge.
Change powered-by link from GitHub repo to langbot.app.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(embed): ignore Enter key during IME composition
Check e.isComposing before treating Enter as send, so confirming
an IME candidate (e.g. Chinese/Japanese input) does not also fire
the message.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(embed): center bubble icon and fill entire circle
Make .lb-chat-icon span fill the full bubble area so the logo image
covers the circle completely without exposing the blue background.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat(embed): add bubble icon presets selector
Add 6 bubble icon options (LangBot logo, chat bubble, robot, headset,
sparkle, message) configurable in the bot settings. Icons are inline
SVGs in widget.js, selected via a config field injected by the backend.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: RockChinQ <rockchinq@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat(monitoring): link feedback to LangBot message ID and add feedback export
- Add pipeline→adapter notification hook so monitoring message ID is
passed back to WecomBotAdapter after creation
- Store stream_id→monitoring_message_id mapping with 10-min TTL cleanup
- Replace feedback record stream_id with LangBot monitoring message ID
so feedback can be linked to actual message records
- Rename streamId label to "Related Query ID" in all 7 i18n locales
- Remove non-functional message ID jump button from FeedbackList
- Add feedback export option to ExportDropdown (backend already implemented)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat(monitoring): add combined refresh handler for monitoring and feedback data
* fix(wecombot): improve stream ID mapping and error logging in WecomBotAdapter
* feat(lark): add monitoring message ID mapping for feedback correlation
* feat(lark): rename monitoring message ID mappings for clarity and consistency
feat(feedback): add button to view conversation for feedback items
* feat(bot-session-monitor): add feedback handling for bot messages with visual indicators
* feat(bot-session-monitor): enhance feedback display with hover content for like/dislike indicators
* fix(dingtalk): use voice recognition text instead of raw audio binary
When DingTalk sends a voice message to the bot, the callback JSON contains
a 'recognition' field with the speech-to-text result (powered by Qwen).
Previously, LangBot only extracted the 'downloadCode' to download the raw
audio binary and passed it as 'file_base64' to LLM APIs, which caused
400 errors since most models don't support this content type.
This patch:
- Extracts the 'recognition' field from DingTalk audio message content
- Uses it as plain text input to the LLM instead of raw audio
- Falls back to audio binary only when no recognition text is available
- Fixes duplicate text issue for audio messages with recognition
Fixes voice messages returning 'Request failed' on all LLM models.
* fix: add filereader for dingtalk,lark (#2122)
* fix: add filereader for dingtalk
* feat: add lark
* feat: update uv.lock
* chore: update version to 4.9.6 in pyproject.toml, __init__.py, and uv.lock
* fix: update langbot-plugin version to 0.3.8
* fix: update langbot-plugin version to 0.3.8
* fix(wecombot): extend StreamSession TTL for feedback sessions to prevent context data loss
StreamSessionManager.cleanup() removes sessions after 60s TTL, but feedback
events (like → cancel → dislike) can arrive later. When the session expires
before the dislike event, all context fields (session_id, user_id, message_id,
stream_id) are lost because get_session_by_feedback_id() returns None.
Fix: Sessions with registered feedback_ids now use a 10-minute TTL, aligned
with the adapter's _stream_to_monitoring_msg TTL in wecombot.py.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: 6mvp6 <13727783693@163.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: fdc310 <2213070223@qq.com>
Co-authored-by: haiyangbg <zhouhaiyangaa@gmail.com>
Co-authored-by: Guanchao Wang <wangcham233@gmail.com>
Co-authored-by: Rock Chin <1010553892@qq.com>
When DingTalk sends a voice message to the bot, the callback JSON contains
a 'recognition' field with the speech-to-text result (powered by Qwen).
Previously, LangBot only extracted the 'downloadCode' to download the raw
audio binary and passed it as 'file_base64' to LLM APIs, which caused
400 errors since most models don't support this content type.
This patch:
- Extracts the 'recognition' field from DingTalk audio message content
- Uses it as plain text input to the LLM instead of raw audio
- Falls back to audio binary only when no recognition text is available
- Fixes duplicate text issue for audio messages with recognition
Fixes voice messages returning 'Request failed' on all LLM models.
* fix(monitoring): fix WeChat Work feedback recording bugs
- Fix feedback events silently dropped when stream session expires:
dispatch feedback handlers regardless of session availability
- Fix IntegrityError on repeated feedback (like→dislike) for same
message: implement UPSERT logic in record_feedback()
- Fix cancel feedback (type=3) not removing records: add delete logic
- Fix inaccurate_reasons validation error: convert int reason codes
to strings before creating FeedbackEvent (Pydantic expects List[str])
- Fix feedback timestamps 8 hours off in frontend: use parseUTCTimestamp
instead of new Date() for UTC timestamp parsing
- Fix StreamSessionManager.cleanup missing _feedback_index cleanup
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(monitoring): apply ruff format to wecom feedback files
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: 6mvp6 <13727783693@163.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: pipeline routing rules - add routed_by_rule bypass and diagnostic logging
- Add routing rules editor (RoutingRulesEditor component)
- Add routed_by_rule bypass logic in response rules
- Add diagnostic logging for pipeline routing
- Database migration for bot pipeline routing rules
- Extract RoutingRulesEditor component from BotForm
- Revert log levels to debug
* feat: add message_has_element routing rule type
Support routing by message element type (Image, Voice, File, Forward,
Face, At, AtAll, Quote) with eq/neq operators.
* test: add unit tests for pipeline routing rules
20 tests covering _match_operator (eq/neq/contains/not_contains/
starts_with/regex/invalid) and resolve_pipeline_uuid (launcher_type/
launcher_id/message_content/message_has_element/first-match-wins/
skip-invalid/default-operator).
* fix(web): add missing 'message_has_element' to routing rule type validation
The Zod schema and TypeScript type for PipelineRoutingRule.type were
missing the 'message_has_element' variant, causing silent form validation
failure when saving routing rules with this type.
* feat: add pipeline discard functionality and localization support
* feat(web): improve drag-and-drop with DragOverlay, add discard monitoring and pipeline icons
- Add DragOverlay for smooth cursor-following drag in routing rules editor
- Remove transition to eliminate redundant swap animation on drop
- Record discarded messages in monitoring system via _record_discarded_message
- Display pipeline name (Workflow icon) and runner name (Play icon) on session monitor messages
- Show discard badge on discarded messages in session monitor
- Add i18n translations for discarded/userMessage/botMessage
* fix: ensure discarded messages appear in session monitor and improve icons
- Create/update monitoring session for discarded messages so they show in
the bot session monitor (was only inserting message rows, not sessions)
- Use human-readable 'Discarded' as pipeline_name instead of '__discard__'
- Change runner icon from Play to Bot for better AI Agent semantics
* fix: merge discarded messages into same session and remove session-level pipeline name
- Use LauncherTypes enum for session_id in discarded messages to match
the format used by monitoring_helper (fixes duplicate sessions)
- Don't overwrite session pipeline info on discard — a session can have
messages from multiple pipelines
- Remove pipeline_name from session list and chat header since it's
now shown per-message and a session is no longer single-pipeline
* fix(web): only show save button on config tab in bot detail page
* fix(web): scroll to bottom after messages render in session monitor
---------
Co-authored-by: RockChinQ <rockchinq@gmail.com>
Adds 'system.disabled_adapters' config option (list of adapter names).
Disabled adapters are excluded from both the adapter registry and API
responses, preventing users from creating bots with those adapters.
Example config:
system:
disabled_adapters:
- aiocqhttp
- dingtalk
* feat(wecom): add user feedback support for WeChat Work AI Bot
This commit implements user feedback functionality (like/dislike) for
WeChat Work AI Bot conversations, including:
Backend changes:
- Add feedback_id and stream_id fields to WecomBotEvent
- Implement feedback event handling in WecomBotClient (api.py)
- Add StreamSessionManager._feedback_index for feedback_id lookup
- Add on_feedback decorator for custom feedback handlers
- Create MonitoringFeedback entity for database persistence
- Add dbm025 migration for monitoring_feedback table
- Implement FeedbackMonitor helper class
- Update all platform adapters with ap parameter support
- Update botmgr to pass bot_info for monitoring context
Frontend changes:
- Add FeedbackCard and FeedbackList components
- Add useFeedbackData hook for feedback data fetching
- Add feedback tab to monitoring page
- Add feedback types and interfaces
- Add i18n translations (zh-Hans, en-US)
Other changes:
- Update Dockerfile with Chinese mirror for faster builds
- Update docker-compose.yaml with network configuration
- Update .gitignore for docker data and backup files
Note: Known issues that need future improvement:
- feedback_type=3 (cancel) is recorded but not properly handled
- Duplicate feedback records are not deduplicated
* chore: remove unnecessary migration for new table will be created automatically
* chore: ruff format
* chore: prettier
* feat: add feedback handling support across multiple platform adapters
* fix(web): remove unused imports and variables in monitoring module
---------
Co-authored-by: 6mvp6 <13727783693@163.com>
Co-authored-by: Junyan Qin <rockchinq@gmail.com>
- Add zh_Hant (Traditional Chinese) to all 17 adapter YAML metadata and config fields
- Add ja_JP translations to global adapters (Telegram, Discord, Slack, Lark, LINE)
- Fix buggy zh_Hant in line.yaml and slack.yaml (contained simplified Chinese)
- Add zh_Hant field to backend I18nString model
- Add adapter category grouping with locale-aware ordering
- Add webhook Cloud CTA for community edition users
- Fix wizard progress not clearing on skip/complete
* fix(web): auto-redirect to wizard on first visit and change sidebar icons to blue
* refactor(wizard): use backend metadata table instead of localStorage for wizard completion state
- Add wizard_completed field to system info API (read from metadata table)
- Add POST /api/v1/system/wizard/completed endpoint to mark wizard done
- Frontend home layout checks systemInfo.wizard_completed for auto-redirect
- Wizard calls markWizardCompleted API on skip/finish
- Ensures consistent behavior across all browsers on the same instance
* fix(wizard): update systemInfo in memory before navigation to prevent redirect loop
* fix(monitoring): prevent horizontal overflow and unify empty state styles
* fix(wizard): use Object.assign for systemInfo and await wizard completion API
- Replace systemInfo reassignment with Object.assign in all 3 locations
to preserve object identity across module imports
- Await markWizardCompleted() POST in wizard skip/finish handlers
instead of fire-and-forget to ensure backend persistence
- Always re-fetch systemInfo in home layout to get latest
wizard_completed state from backend
* fix(wizard): prevent redirect loop by blocking navigation on failed status save
- Refactor wizard_completed (boolean) to wizard_status (string: none/skipped/completed)
- Remove ALL localStorage usage from wizard page (form state persistence)
- Replace AlertDialogAction with Button so skip dialog stays open during POST
- Add loading spinners for skip and complete actions
- If POST fails, show error toast and keep dialog/button active for retry
- If POST succeeds, update in-memory state and navigate
* fix(wizard): fix row[0].value bug causing GET /info to always return wizard_status=none
conn.execute(select(Entity)) returns Row with raw column values, not ORM
entities. row[0] is the key column (a string), so row[0].value raises
AttributeError which was silently swallowed by except-pass, making the
GET endpoint always return wizard_status=none regardless of DB state.
* fix(wizard): replace AlertDialog with Dialog for skip confirmation to remove slide animation
* chore: optimize toast in wizard
* fix(wizard): set default token value for Telegram adapter and initialize adapter config in wizard
* feat(web): move webhook URL to dynamic form system, add market category filter, fix layout overflow
- Add 'webhook-url' dynamic form field type rendered as read-only input
with copy button, defined in adapter YAML specs instead of hardcoded
in BotForm. Supports show_if conditions for optional-webhook adapters.
- Remove hardcoded webhook display logic from BotForm.tsx, pass webhook
URLs via systemContext to DynamicFormComponent.
- Fetch webhook URLs after bot creation in wizard and pass to Step 1.
- Support ?category= query param on /home/market page for filtering by
component type (mirrors langbot-space behavior).
- Link 'install knowledge engine' hint to /home/market?category=KnowledgeEngine.
- Fix SidebarInset missing min-w-0 causing content overflow when sidebar
is expanded.
- Add vertical divider between plugin detail config and readme panels.
- Fix infinite re-render loop in DynamicFormComponent by memoizing
editableItems array.
* fix: lint
* fix(web): change systemInfo to const to satisfy prefer-const lint rule
* fix: update adapter descriptions for clarity and usage requirements
* feat: add wexin openclaw adapter
* feat: The new feature will store the token and other configurations after login.
* fix: wexin qc to base64 and in log image print
* feat: add image to base64
* feat: add update file and image and voice
* Fixed the issue where the at bot did not remove the at symbol, resulting in some commands not being activated in group chats. Also, adjusted the logic in the on_message section.
* fix:reply_message del bot_name
The Telegram adapter only handles TEXT, COMMAND, PHOTO, and VOICE
messages. Document files (docx, pdf, etc.) sent by users are silently
dropped because:
1. MessageHandler filters lack filters.Document.ALL
2. target2yiri() has no message.document branch
3. yiri2target() has no platform_message.File branch
4. send_message() has no 'document' component handler
Changes:
- Add filters.Document.ALL to the MessageHandler filter set
- Add message.document parsing in target2yiri() → platform_message.File
- Add platform_message.File handling in yiri2target() → document component
- Add 'document' type handling in send_message() via bot.send_document()
This allows Telegram document messages to flow through the existing
PreProcessor and Dify file upload pipeline, consistent with how other
adapters (Lark, KOOK, Discord, WeCom) already handle files.
Closes#2065
* feat: Implement WebSocket long connection client for WeChat Work AI Bot
- Added WecomBotWsClient to handle WebSocket connections for receiving messages and sending replies.
- Introduced a new migration (dbm022) to add 'enable-webhook' field to existing wecombot adapter configs, ensuring backward compatibility.
- Updated WecomBotAdapter to support both WebSocket and webhook modes based on the new configuration.
- Enhanced YAML configuration for WecomBot to include 'enable-webhook' and 'Secret' fields, adjusting requirements accordingly.
- Incremented database version to 22 to reflect schema changes.
* fix:db enable-webhook is false
* fix:add logic
* fix:Removed an unnecessary configuration check
* fix: migration
* fix: update migration
* fix:migration
* fix(database): Update database version requirement to 20
- Increase required_database_version from 19 to 20
- Add documentation on database schema version check
* feat(lark): Added support for message references and topic message grouping
- Implemented the function to extract reference message IDs from messages, supporting parent message identification
- Added a method to construct event messages from SDK message items
- Implemented the function to asynchronously obtain reference messages and convert them into message chains
- Integrated reference message injection logic into the message processing flow
- Added a mechanism to filter source components while retaining reference content
- Implemented a method to obtain the starter ID with topic awareness
- Provided session isolation support for topic range in group thread messages
- Supported stable maintenance of conversation context in group thread discussions
- Handled cases where topic messages cannot reliably detect reference targets
* feat(lark): Implement a duplicate prevention mechanism for Feishu topic message references
- Add class-level cache to store processed topic IDs and timestamps
- Implement a timed cleanup mechanism to remove expired topic records
- Add cache size limit to prevent memory from growing indefinitely
- Return the parent message ID and mark it as processed when the first reply is made to a topic
- Return None in subsequent replies to the same topic to avoid duplicate references
- Implement automatic cache trimming to ensure stable performance
- Add get_user_info() to WecomClient to fetch user name via /user/get API
- Update WecomEventConverter.target2yiri to accept bot param and fetch real user name
- Update register_listener call to pass self.bot for user name lookup
- URL-encode userid parameter for safety
Co-authored-by: RockChinQ <45992437+RockChinQ@users.noreply.github.com>
- Include websocket_proxy_bot in get_bot_by_uuid lookup so plugins can
find it by uuid
- Rewrite send_message to broadcast directly via ws_connection_manager
using the correct pipeline_uuid instead of misusing target_id
- Save messages to session history with unique IDs so they persist
across page reloads and don't overwrite each other
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>