Commit Graph
103 Commits
Author SHA1 Message Date
Chin Rockandmultica-agent b7992e4ea6 fix(ci): align HTTP attachment test with explicit file export
Co-authored-by: multica-agent <[email protected]>
2026-10-19 19:02:21 +00:00
41b55952ff fix(runner): avoid duplicate inline image payloads (#2631)
* fix(runner): avoid duplicate inline image payloads

* fix(runner): preserve attachments and complete HTTP agent delivery

Co-authored-by: multica-agent <[email protected]>

---------

Co-authored-by: Qingsong Li <[email protected]>
Co-authored-by: Chin Rock <[email protected]>
Co-authored-by: multica-agent <[email protected]>
2026-10-20 02:14:36 +08:00
RockChinQ 5a6ddbff6f Merge pull request #2656 from fluo-rite/fix/telegram-mention-entities
fix(telegram): respect entity boundaries when parsing bot mentions
2026-10-19 17:51:31 +08:00
RockChinQandmultica-agent 52e8042f51 fix(telegram): match mention usernames case-insensitively
Co-authored-by: multica-agent <[email protected]>
2026-10-19 17:33:51 +08:00
Haoxuan Jiang 841b4df09d fix(lark): preserve incoming rich-text code blocks (#2626) 2026-10-19 16:26:16 +08:00
Hyu 868f89a383 merge: integrate master into lark webhook signature fix 2026-10-19 01:53:46 +08:00
Hyu 757f8b7a35 fix(lark): authenticate plaintext webhooks and explain credentials 2026-10-19 01:48:29 +08:00
huanghuoguoguo 710d3edb71 Merge pull request #2694 from langbot-app/test/quality-discord-increment-oracles-20261017
test(discord): assert attachment and guild delivery targets
2026-10-17 20:12:28 +08:00
huanghuoguoguo 6ea7fb9fc8 test(discord): assert attachment and guild delivery targets 2026-10-17 16:07:00 +08:00
huanghuoguoguo c03f33d855 test(runtime): verify sandbox and platform contracts 2026-10-17 15:57:15 +08:00
RockChinQ c05aac538f fix(discord): complete streaming media and event delivery 2026-10-17 15:11:29 +08:00
RockChinQ 68a3f64cef test(core): update bot fixtures for platform policy checks 2026-10-15 05:31:04 +00:00
RockChinQ 625ee67113 fix(ci): align workspace fixtures and constrain mobile tours 2026-10-15 05:31:04 +00:00
RockChinQ b8d292c94d fix(websocket): recover debug connections and resolve backend URLs consistently 2026-10-15 05:31:04 +00:00
RockChinQ 528faf7851 test(cloud): include adapter names in runtime tenancy fixtures 2026-10-15 05:31:04 +00:00
Hyu e29fd27f02 feat(i18n): localize backend messages by workspace language 2026-10-15 05:31:04 +00:00
fluo-rite 607a94f324 fix(telegram): respect entity boundaries when parsing bot mentions 2026-10-13 02:29:07 -04:00
RockChinQandHyu ec021c3c41 fix(onebot): validate WebSocket protocol with independent mock peer (#2653)
* feat(onebot): support main-port reverse and forward WebSocket connections

* fix(onebot): keep protocol metadata out of business events

* test(onebot): validate WS events and APIs against independent protocol peer

---------

Co-authored-by: Hyu <[email protected]>
2026-10-12 13:59:25 +08:00
Hyu 11ed8a2306 feat(onebot): support main-port WebSocket transports and filter protocol events 2026-10-12 13:36:26 +08:00
RockChinQ 0b5b4cca59 fix(telegram): resolve real-client event and media delivery regressions 2026-10-11 10:14:11 +08:00
Hyu f0acbd7048 test: isolate Lark message converter mocks between cases 2026-10-11 01:18:16 +08:00
Hyu 33ea03701a test: update adapter and monitoring regression fixtures 2026-10-11 01:10:40 +08:00
Hyu 8fa5df6c77 feat(slack): support standard events and interactive callbacks 2026-10-11 00:17:27 +08:00
Hyu 7d4e13509b fix(slack): transfer message attachments through file APIs 2026-10-11 00:17:19 +08:00
Hyu 4a700ac0f3 feat(slack): add guided app setup and Socket Mode support 2026-10-10 23:37:30 +08:00
Hyu 5c8275e564 feat(weixin): show typing indicator during message processing 2026-10-10 22:50:51 +08:00
Hyu 405f1ac2e7 feat: refine Feishu streaming cards and add linked footer branding 2026-10-10 22:35:35 +08:00
Hyu d2ec53ec91 feat(dingtalk): support group subscriptions and card interaction events 2026-10-10 21:29:49 +08:00
Hyu 4f43da0fb3 fix(wecombot): improve event routing and sandbox attachment delivery 2026-10-10 18:41:57 +08:00
Hyu a2b7f6b7bb fix: stabilize native streaming and improve bot controls 2026-10-10 18:02:42 +08:00
Hyu 4b370f0a92 fix(telemetry): skip unrouted events and preserve matched deliveries 2026-10-08 13:33:57 +08:00
Hyu 4482e8d876 feat(telemetry)!: upload one record per execution node and one closure per chain
Core no longer assembles a whole trace locally. Every workflow node is uploaded
the moment it completes as its own `execution_node` record, and each execution
closes with exactly one `execution_chain` record; all records of one execution
carry the same `event_id`, so Space groups them back into a single chain.

- every execution starts at an inbound event: event-less Pipeline lanes and
  WebUI/API debug runs synthesize their virtual inbound event at the boundary
  and are marked debug=true, so a Runner is never a trace origin
- sampling is decided once per event from a stable hash of the event id (the
  previous `int(id[:8], 16)` raised on every `platform:`-prefixed id and so
  dropped every successful inbound-event chain) and is reported on each record
  as sample{mode,denominator}; the default mode is now `all`
- the local trace buffer, the 120s TTL, the per-process trace cap and the shared
  open-node mirror are gone, which also removes the truncated-chain upload and
  the re-buffered-closed-trace leak they caused
- a broken chain is always uploaded, and its reason falls back to the first
  failed node so the chain explains itself
- flush keeps records until the sender accepts them and counts what it drops;
  telemetry health replaces the unused send-task queue
- heartbeat reports bound Agent / plugin-processor / event-binding counts
- bound Pipeline and Agent resources (plugins, MCP servers, knowledge bases,
  tools with their Host source, skills, models and the Runner schema selectors
  that picked them) are reported on the chain record
- failure text is bounded and redacted instead of passing exception text through
- the dead per-query feature counters and their call sites are removed

Wire contract: schema 2 (`execution_node` / `execution_chain`).
2026-10-07 09:41:41 +08:00
carfeii 7b7f1d20f4 fix(lark): verify webhook event-subscription signature before dispatch
The Lark/Feishu webhook handler (both the current lark-omni adapter and
the legacy lark adapter) parsed and dispatched inbound HTTP callback
events without checking Lark's own X-Lark-Signature header, and the
Encrypt Key config field used to decrypt payloads is optional and empty
by default. Any caller who reached a bot's webhook URL could inject
fabricated message/card-action events with an attacker-chosen sender,
chat, and content.

Add signature verification matching Lark's documented
event-security-verification scheme (sha256 of timestamp + nonce +
encrypt_key + body, compared to X-Lark-Signature) to both
implementations, rejecting any callback that lacks a valid signature or
whose bot has no Encrypt Key configured. Adds regression tests covering
the rejection paths and updates the two existing webhook tests to
present a valid signature.
2026-10-05 22:00:54 +08:00
Hyu 41820cd1a5 test(platform): follow the batched execution trace pipeline
The execution trace rewrite batches records and uploads them from
ExecutionCounters.flush(), replaced the per-trace direct send, dropped the
window counters, made the execution id the record identity and records the
inbound event stage after the routing stage. The ingress tests still asserted
the old mechanism, so they failed on every Python version.

Assert what the pipeline now emits instead: flush the buffered records and read
them back, require the trace registry to be empty afterwards, assert the
deterministic execution id, expect the route stage before the inbound stage,
and give the dispatch stubs the execution_id parameter the ingress passes.
2026-10-01 19:55:44 +08:00
Hyu 0efc1fb1cc feat(telemetry): trace one inbound event end to end
Execution telemetry already reported window counters. This adds one bounded,
content-free chain per inbound platform event, so a single event can be
followed from its source platform through routing and processing to the
platform API calls it caused.

- telemetry/trace.py: ContextVar trace identity with route and run scopes, and
  a 32-stage bound per chain.
- telemetry/execution.py: keeps at most 64 chains for 120s, decides sampling
  from the observed outcome, and sends one payload per chain keyed by
  query_id = trace_id, so Space fetches a chain by primary identity. Window
  counters are unchanged and remain the source of coverage statistics.
- botmgr / pipelinemgr / orchestrator: bind the trace at the ingress boundary,
  scope routing identity per dispatch, and attach the run identity, so nested
  lanes (event -> route -> pipeline/runner -> platform API) reuse one chain. A
  run reached without an ingress (WebUI debug, service API) owns its own chain.
- space.execution_trace selects off | failures | sampled | all (default
  sampled: failures, WebUI debug runs and every N-th success).

Chains carry only code-defined identifiers (adapter and runner types, route
identity as type:uuid, run id); never message content, tool arguments or
platform user identifiers.
2026-10-01 02:12:44 +08:00
RockChinQ 9b589a8f08 merge: integrate 4.11 into master 2026-09-24 02:01:00 +08:00
Martin 874eb6600c fix(wecombot): stop empty bubbles and premature stream close on blank final chunks (#2561)
* fix(pipeline): stop emitting empty final assistant messages

An empty final streaming chunk was appended as an empty message chain when no sandbox outbox attachment was present, so platforms received an empty reply. Only append the chain when attachments were actually collected, and gate the "Call ..." tool notice behind output.misc.track-function-calls so it no longer becomes the final chunk of a stream.

* fix(wecombot): do not close stream on a blank final snapshot

A blank final snapshot closed the WeCom stream with an empty bubble and pushed the real answer into a separate reply_text message. Skip blank final snapshots and keep the session open so the following non-blank chunk can finalize it. Covered by new regression tests.
2026-09-23 18:28:11 +08:00
RockChinQ 184037a427 feat(bots): bind plugin processor configurations independently 2026-09-15 00:28:13 +08:00
RockChinQ f24a7c9bb2 feat(runner): unify plugin execution across agents and event processors 2026-09-10 18:04:38 +08:00
RockChinQ 8903a40c41 fix(runtime): preserve explicit replies and report bot configuration errors 2026-09-10 17:21:22 +08:00
RockChinQ d1c79a35e8 fix(4.11): align omni adapters and EventProcessor marketplace support 2026-09-10 15:06:57 +08:00
RockChinQ 237fa6545d feat(processors): add explicitly bound plugin event processors 2026-09-08 00:43:35 +08:00
QuasarRyan d6443b10bc feat(platform): add Mattermost platform adapter (#2515) 2026-09-07 22:46:47 +08:00
Hyu a4d36aa2db feat(agent): add event-aware tool permissions 2026-09-04 15:37:41 +08:00
Amir Fathi d942bfe19a fix(wecom): read media_id instead of media in send_message() (#2447)
WecomMessageConverter.yiri2target() always emits {'media_id': ...} for
image/voice/file parts (never 'media'), matching the correct usage
already in reply_message(). send_message(), the entry point plugins
use via PluginToRuntimeAction.SEND_MESSAGE, instead read
content['media'], which is never set, so any image/voice/file part
raises KeyError and aborts the send.

Refs #1687

Signed-off-by: Amir Fathi <[email protected]>
2026-09-04 13:02:40 +08:00
mintya 5ca30133a3 fix(lark): stop duplicating final reply text in streaming card (#2490)
* fix(lark): stop duplicating final reply text in streaming card

* fix(lark): stop duplicating final reply text in streaming card
2026-09-01 21:24:54 +08:00
Hyuanddadachann 8cf0015502 fix(dingtalk): restore card auto layout (#2491)
Co-authored-by: dadachann <[email protected]>
2026-09-01 17:56:02 +08:00
Hyu fde04e64f6 Merge remote-tracking branch 'origin/master' into dev/4.11.x
# Conflicts:
#	src/langbot/pkg/api/http/controller/groups/pipelines/pipelines.py
#	src/langbot/pkg/api/http/service/bot.py
#	src/langbot/pkg/provider/runners/localagent.py
#	src/langbot/templates/metadata/pipeline/ai.yaml
#	tests/unit_tests/api/service/test_bot_service.py
#	tests/unit_tests/provider/runners/test_difysvapi_runner.py
#	tests/unit_tests/utils/test_safe_regex.py
#	web/src/app/infra/entities/adapter-categories.ts
#	web/src/app/wizard/page.tsx
#	web/src/i18n/locales/en-US.ts
#	web/src/i18n/locales/ja-JP.ts
#	web/src/i18n/locales/zh-Hans.ts
#	web/tests/e2e/plugin-page-auth.spec.ts
2026-08-31 17:17:47 +08:00
NeosandHyu e69a80f5e9 Windows 兼容性修复 + Dify API 适配 + 企微 WS 加载优化 (#2470)
* fix: Windows fsync requires write access to file descriptor

- _fsync_file: os.O_RDONLY -> os.O_RDWR (Windows _commit() requires write access)
- _fsync_directory: tolerate OSError on fsync and os.open (chmod 0o700 blocks access on Windows)

* fix: Dify SSE empty data lines and upload response format mismatch

- Skip malformed/flushed SSE data lines (JSONDecodeError)
- Accept HTTP 200 besides 201 for file upload response
- Unwrap data wrapper in upload response (resp.get('data', resp))

* feat: WeCom WS mode sends empty initial stream frame for loading spinner

Send an empty reply_stream frame immediately after stream session
creation so the WeCom client shows its built-in loading indicator
while the pipeline processes the message (e.g. RAG retrieval).

* fix(compat): harden Windows, Dify, and WeCom changes

* fix(migration): clean interrupted SQLite temp files

---------

Co-authored-by: Hyu <[email protected]>
2026-08-29 22:34:10 +08:00
leonoxo 855ae2bdba fix(line): map LINE mentions to At elements so the at-bot rule works (#2478)
The LINE adapter passed text through as a single Plain component,
ignoring the mention payload (mentions[].index/length/isSelf) that the
Line Messaging API includes in the webhook. As a result:

- At(target=bot_account_id) never appeared in the message chain, so the
  'at-bot' group respond rule silently dropped every @bot mention.
- The bot only replied when the message happened to match the prefix
  rule (e.g. starting with 'ai').

Now LINEMessageConverter reads message.message.mention and builds the
chain per mention position:

- Bot mention (isSelf) -> At(target=bot_account_id) so AtBotRule matches
  the same way as other adapters (dingtalk/lark etc.).
- Other mentions -> At(target=<line user id>, display=<mention text>).
  At.__str__ already prepends '@', so the display text carries no
  double '@' and the rendered text (prefix/regexp rules, quotes,
  session context) is byte-identical to before.
- Missing/out-of-bounds mentions are skipped defensively.

target2yiri becomes an instance method (like wechatpad/aiocqhttp) so
the converters can hold bot_account_id; LINEAdapter passes it in from
its own config.
2026-08-27 18:38:27 +08:00