Feat: bot message routing (#2100)

* 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>
This commit is contained in:
Typer_Body
2026-04-03 23:56:58 +08:00
committed by GitHub
parent 875227a2fe
commit 77a0de5ef0
19 changed files with 1149 additions and 25 deletions

View File

@@ -307,6 +307,39 @@ const enUS = {
routingConnection: 'Routing & Connection',
routingConnectionDescription:
'Bind the pipeline that processes messages for this bot',
routingRules: 'Conditional Routing Rules',
routingRulesDescription:
'Rules are evaluated in order; first match routes to its pipeline. Fallback to the default pipeline above if none match.',
addRoutingRule: 'Add Rule',
ruleTypeLauncherType: 'Session Type',
ruleTypeLauncherId: 'Session ID',
ruleTypeMessageContent: 'Message Content',
operatorEq: 'Equals',
operatorNeq: 'Not Equals',
operatorContains: 'Contains',
operatorNotContains: 'Not Contains',
operatorStartsWith: 'Starts With',
operatorRegex: 'Regex',
operatorHas: 'Has',
operatorNotHas: 'Does not have',
ruleTypeMessageHasElement: 'Message Element',
ruleValueElementPlaceholder: 'Select element type',
elementImage: 'Image',
elementVoice: 'Voice',
elementFile: 'File',
elementForward: 'Forward',
elementFace: 'Emoji',
elementAt: '@Mention',
elementAtAll: '@All',
elementQuote: 'Quote',
ruleValuePlaceholder: 'Match value',
ruleValueLauncherIdPlaceholder: 'Group or user ID',
ruleValueMessagePlaceholder: 'Message text',
ruleValuePrefixPlaceholder: 'e.g. !draw',
ruleValueRegexpPlaceholder: 'e.g. ^/help',
pipelineDiscard: 'Discard Message',
sessionTypePerson: 'Private Chat',
sessionTypeGroup: 'Group Chat',
adapterConfigDescription: 'Configure the selected platform adapter',
dangerZone: 'Danger Zone',
dangerZoneDescription: 'Irreversible and destructive actions',
@@ -355,6 +388,9 @@ const enUS = {
refresh: 'Refresh',
active: 'Active',
inactive: 'Inactive',
discarded: 'Discarded',
userMessage: 'User',
botMessage: 'Assistant',
},
},
plugins: {