- Updated the DingTalk card template to enable streaming mode and multi-update configuration.
- Removed the obsolete delete_card method from DingTalkClient to streamline card management.
- Enhanced DingTalkAdapter to manage active turn cards and accumulated streaming text, ensuring a seamless user experience during human input prompts.
- Modified the create_message_card method to utilize existing active cards for resumed workflows, preventing duplication.
- Improved the _paint_form_on_card method to update existing cards with human input prompts and buttons dynamically.
- Updated the dingtalk_human_input_card.json template to reflect the new streaming capabilities and configuration options.
- Add a new module `card_callback.py` to handle card action button clicks from DingTalk.
- Introduce `DingTalkCardActionHandler` to process card action callbacks and extract parameters.
- Update `DingTalkAdapter` to manage card state and handle form input through a single card template.
- Add configuration for `human_input_card_template_id` in `dingtalk.yaml` to specify the template for human input.
- Create a new card template `dingtalk_human_input_card.json` for rendering human input prompts and buttons.
- Added module-level storage for pending forms to manage state across sessions.
- Introduced functions to set, get, and clear pending forms with expiration handling.
- Enhanced DifyServiceAPIRunner to support resuming paused workflows via form actions.
- Implemented logic to yield human input requests and display appropriate messages.
- Updated workflow submission methods to handle paused states and resume actions.
- Ensured proper merging of pending form actions with user inputs for seamless interaction.
* feat(qrcode-login): enhance WeChat login flow with expiration handling and improved session management
* feat(qrcode-login): replace RefreshCw icon with RotateCw for loading state
* feat(qrcode-login): adjust session expiration handling and improve error status management
The /api/v1/system/debug/exec endpoint passes user-supplied HTTP body
directly to Python exec(), enabling arbitrary code execution for any
authenticated user when debug_mode is enabled. This is a critical
security risk (CWE-94): a single misconfiguration or compromised JWT
grants full server-side code execution.
Remove the endpoint entirely. The /debug/plugin/action endpoint (which
does not use exec()) is left intact as it serves a different, scoped
purpose.
Co-authored-by: Junyan Chin <rockchinq@gmail.com>
Unify JSON card message parsing across mini-program, music, and article/video
types. Extract app, preview, title, and url fields using the standard QQ JSON
card structure (meta.detail_1 / music / news) instead of app-name hardcoding.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Add support for parsing OneBot JSON message segments (QQ mini-program,
Bilibili share cards, etc.) in the target2yiri converter. Parses the
card metadata and converts it to plain text to avoid silently dropping
these message types.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* feat: add one-click app creation for Feishu with QR code support
* feat: implement WeChat QR code login functionality and update related configurations
* feat: add qrcode dependency for QR code generation support
* feat: enhance QR code login UI and add internationalization support for new labels
* feat: new ui back
* feat: add DingTalk one-click app creation and QR code login support
* feat: add WeComBot one-click creation support and enhance QR code login functionality
* feat: Update the robot creation function and bind the most recently updated pipeline
Add business-agnostic validation for knowledge base creation:
- Backend: dynamically validate required fields from plugin's creation_schema
and retrieval_schema, with support for show_if conditional fields
- Frontend: expose validation function from DynamicFormComponent and
validate before KBForm submission
- Add i18n translations for validation error messages
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* add conversation expire config
* add user query text to card
* fix(pipeline): move session limit to AI config
* test(pipeline): cover AI session limit config
* refactor(pipeline): merge session expire-time into AI runner stage
Move the session validity duration field out of the standalone
session-limit stage into the runner stage so it actually renders in the
AI tab (the tab only shows the runner stage and the stage matching the
selected runner — any other stage is filtered out). Read path, default
config, metadata description, and tests updated accordingly.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(pipeline): expire conversations from last update time
* fix(n8n): sync generated conversation id into payload
---------
Co-authored-by: RockChinQ <rockchinq@gmail.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
File messages from platforms like Telegram carry base64 data with an
empty url. The unconditional from_file_url(me.url) call passed an empty
string downstream, causing httpx to fail with "Request URL is missing
an 'http://' or 'https://' protocol" when uploading to Dify.
Mirror the existing Voice handling pattern: check base64 first, fall
back to url. Applied in both the main message chain and the Quote path.
Closes#2079
Co-authored-by: Junyan Qin <rockchinq@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add _safe_resolve() helper that uses os.path.realpath() to canonicalize
the joined path and verifies it stays within LOCAL_STORAGE_PATH.
All six public methods (save, load, exists, delete, size,
delete_dir_recursive) now validate the key before performing any I/O.
This prevents absolute-path injection (e.g. key="/etc/passwd") and
relative traversal (e.g. key="../../etc/passwd") from escaping the
storage root directory.
CWE-22
* 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>
The Space API defaults to page_size=20, but the model catalog has grown
beyond 20 entries (currently 26), causing models to be silently dropped
during sync.
Migration 0003 failed when rerank_models table already exists from create_all().
Add table existence check to prevent duplicate creation error in CI environments with cached database.