1916 Commits

Author SHA1 Message Date
teconomix
6bea6df33f fix(mattermost): keep text+media together; avoid split captioned posts (ID=2965096969)
Patching preview text then delivering media separately splits a captioned-file
reply into two posts: a text-only preview + captionless file attachment.

New logic in the isFinal branch:
- Text-only payload: patch in place as before (no change for common case)
- Media payload: skip the patch, reset state, deliver full payload via
  deliverMattermostReplyPayload (text+media together), then delete preview.
- Patch failure: same fallback as media payload — full delivery + delete.
2026-03-20 11:15:46 +00:00
teconomix
f49c6a402c fix(mattermost): deliver media attachments after successful final patch (ID=2965023940)
After a successful patchMattermostPost in the isFinal branch, the code returned
immediately without delivering any media attachments. deliverMattermostReplyPayload
is the only path that uploads/sends media, so caption+image/file/audio payloads
were silently dropping the attachment whenever streaming was active and the patch
succeeded.

Fix: after a successful patch, check whether the payload has mediaUrls/mediaUrl.
If so, call deliverMattermostReplyPayload with text=undefined to deliver only the
media through the normal attachment path.
2026-03-20 10:38:24 +00:00
teconomix
dff71545a6 fix(mattermost): track patchInflight in P4; use direct await in onSettled cleanup
Add patchInflight Promise tracking to P4 (feat/mattermost-block-streaming-rebased),
mirroring the existing P5 approach. The onSettled cleanup previously used a 3-second
busy-wait on patchSending, which would race on slow Mattermost links: if the first
preview POST takes longer than 3s the cleanup exits early, patchSending is forced false,
and when the POST later resolves it creates an orphan post that is never deleted.

Fix: track the interval tick's async function as patchInflight. onSettled awaits it
directly so the cleanup always captures the final streamMessageId, regardless of how
long the POST takes. (Codex ID=2964616785)
2026-03-20 10:21:19 +00:00
teconomix
374c92947a fix(mattermost): latch send failures; include patchInterval in onSettled cleanup
Two fixes:

1. Failure latch (Codex ID=2964357928): add previewSendFailed boolean that is set true
   in both the initial-send and patch-edit catch blocks (alongside stopPatchInterval).
   schedulePatch() checks it before re-arming the interval, so subsequent onPartialReply
   calls during a run with a permanent failure (missing permission, DM-creation error)
   no longer recreate the timer and retry indefinitely.

2. patchInterval in onSettled guard (Codex ID=2964357925): onSettled now triggers
   cleanup when patchInterval is non-null, even if streamMessageId and patchSending
   are still falsy. This covers the window between schedulePatch arming the interval
   and the first 200ms tick flipping patchSending — if the run ends in that window
   (same-target messaging-tool sends, empty/heartbeat replies), the interval is now
   stopped and the pending state is cleared.
2026-03-20 08:21:53 +00:00
teconomix
0ecdda1433 fix(mattermost): wait for in-flight preview send in onSettled cleanup
When the first preview POST is still in flight (patchSending=true, streamMessageId=null),
the previous onSettled check was skipped entirely — the POST would resolve after cleanup
and leave an orphaned preview post with no interval to clear it.

Fix: trigger cleanup when either streamMessageId is set OR patchSending is true.
Stop the interval immediately, clear pending state, then wait up to 3s for patchSending
to clear before capturing the final streamMessageId and deleting the post.
2026-03-20 07:15:22 +00:00
teconomix
e2c4d8bd45 fix(mattermost): clean up streaming preview when no final payload arrives; stop retrying failed initial sends
Two fixes:

1. onSettled orphan cleanup (Codex ID=2963834802): add cleanup in the streaming
   dispatcher's onSettled callback for cases where the reply pipeline produces no
   final payload — e.g. messaging-tool sends suppressed by agent-runner-payloads.ts,
   or empty/heartbeat responses. Without this, onPartialReply could create a preview
   post that is never finalized or deleted. The cleanup mirrors the existing logic in
   #43041 (P5).

2. Initial-send retry storm (Codex ID=2963834806): call stopPatchInterval() in the
   sendMessageMattermost catch block, mirroring the existing fix for patchMattermostPost
   failures. Without this, a failed initial post attempt (missing post permission, DM
   creation failure, etc.) causes the 200ms interval to retry indefinitely for the rest
   of the response, flooding the API and gateway logs.
2026-03-20 06:03:16 +00:00
teconomix
38f3e76f97 fix(mattermost): wait for in-flight preview send before divergent delivery; stop retrying failed patches
Two fixes:

1. Divergent-target flush (Codex ID=2962544342): when replyTargetDiverged is true
   the flush is skipped to avoid creating a preview in the wrong thread, but the
   patch interval was not stopped and any in-flight first sendMessageMattermost
   was not awaited. If that send resolved after the divergent delivery returned,
   it created a stray preview post with no cleanup path. Fix: always stop the
   interval and wait for patchSending to settle (up to 2s) even on the divergent
   path, so streamMessageId is populated if the send resolves during this window
   and the orphan cleanup below can capture and delete it.

2. Patch-failure retry storm (Codex ID=2962544347): after a patchMattermostPost
   failure in the schedulePatch interval, streamMessageId remained set and every
   subsequent 200ms tick retried the same failing request, spamming the API until
   final delivery. Fix: call stopPatchInterval() in the catch block so retries
   stop immediately. The preview stays frozen at its last successful text; deliver()
   will patch or replace it when the final reply arrives.
2026-03-20 03:53:16 +00:00
teconomix
59db1c2b67 fix(mattermost): deliver media-only final before deleting streamed preview
When the final payload has no text (media-only), the in-place text patch branch
is skipped, but the streamed preview post was previously left in the channel
alongside the attachment. The orphanedStreamId capture now always holds the
stream post ID (not only on divergent-target paths), and a new branch delivers
the media payload first and deletes the stale preview only after delivery
succeeds. If delivery fails, the preview stays visible as a fallback.
2026-03-19 20:17:51 +00:00
teconomix
e1e572b9ca fix(mattermost): compute replyTargetDiverged before flush; deliver-before-delete for divergent thread; fix disableBlockStreaming undefined
Three fixes from latest Codex review:

1. Compute replyTargetDiverged before flushPendingPatch: previously the flush
   always ran first, potentially creating a preview post under effectiveReplyToId
   even when the final payload would land in a different thread. Now flush is
   skipped when the target diverges, avoiding a transient post in the wrong thread.

2. Divergent-thread cleanup order: when replyTargetDiverged, deliver the correct
   message first and delete the orphaned preview only afterward. This matches the
   same pattern as the fallback path — if delivery fails, the user keeps the
   partial preview rather than losing all visible output.

3. disableBlockStreaming: changed fallback from false to undefined so accounts
   without an explicit blockStreaming setting preserve the agent blockStreamingDefault
   instead of having block streaming forced on.
2026-03-18 14:43:22 +00:00
teconomix
276e5d735b fix(mattermost): deduplicate truncated patch edits; delete orphan only after fallback succeeds
Two fixes from latest Codex review:

1. Truncation dedup: compare lastSentText against the truncated text (not the full
   rawText) in both schedulePatch and flushPendingPatch. Previously, once a reply
   grew past textLimit the guard compared the growing rawText against the stored
   rawText, so the post would be patched every 200 ms with the same truncated body
   — running into avoidable Mattermost rate limiting on long responses.

2. Orphan cleanup order: in the final-edit fallback path, deliver the replacement
   message first and only delete the orphaned stream post afterward. If the fallback
   send also fails, the user keeps the partial preview instead of losing all visible
   output.
2026-03-18 13:31:11 +00:00
teconomix
7ed3db579f fix(mattermost): make streaming opt-in; apply textLimit to patches; handle reply target divergence
Three fixes addressing Codex review feedback:

1. Streaming opt-in: change streamingEnabled from (blockStreaming !== false) to
   (blockStreaming === true) so accounts without an explicit blockStreaming setting
   preserve their agent blockStreamingDefault instead of having edit-in-place
   streaming silently enabled.

2. Text limit: apply textLimit truncation in schedulePatch and flushPendingPatch
   before sending/patching. Intermediate preview posts only need the first chunk;
   final delivery goes through deliverMattermostReplyPayload which applies full
   chunking. This prevents oversize patch loops when responses exceed the limit.

3. Reply target divergence: when the final payload carries an explicit replyToId
   that resolves to a different root than the streaming post was created under
   (e.g. a [[reply_to_current]] directive), skip the in-place patch and fall
   through to normal delivery so the reply lands in the correct thread. Any
   orphaned stream post is deleted before the correct reply is sent.
2026-03-18 13:31:11 +00:00
teconomix
33678bb973 fix(mattermost): set lastSentText after network success; wait for in-flight tick in flush
Race condition: lastSentText was set synchronously before the async send/patch
completed, so a failed request was treated as delivered and subsequent ticks
skipped retrying. flushPendingPatch also didn't wait for in-flight interval ticks,
causing it to exit early (text === lastSentText guard) when a tick had just fired
but hadn't resolved yet, leaving streamMessageId null and forcing final delivery
to send a new post instead of patching the streamed one.

Fixes:
- schedulePatch interval: set lastSentText only after successful send/patch
- flushPendingPatch: wait up to 2s for in-flight patchSending before proceeding
- flushPendingPatch: set lastSentText after network success, not before
2026-03-18 13:31:10 +00:00
teconomix
ee6d984950 fix(mattermost): use client.request in patchMattermostPost and deleteMattermostPost
Both functions called the global fetch directly, bypassing the fetchImpl
stored in the client closure. This silently ignored any custom fetch
implementation passed to createMattermostClient (test mocks, proxy-aware
fetchers, SSRF guards).

Switch both to client.request<void>() which uses fetchImpl, auto-injects
the Authorization header, handles Content-Type for JSON bodies, and
propagates errors consistently with every other client function.

uploadMattermostFile retains its direct fetch call (multipart/form-data
conflicts with request's automatic Content-Type injection).

Addresses Greptile review: 'New functions bypass client.request,
ignoring custom fetchImpl'.
2026-03-18 13:31:10 +00:00
teconomix
ec10de7361 fix(mattermost): inherit agent block-streaming default in button/model-picker paths
When account.blockStreaming is unset, pass undefined instead of false for
disableBlockStreaming so downstream get-reply-directives inherits the
agent-level default rather than forcing block streaming on.

Affected paths: button-click interactions (handleInteractiveMenuInteraction)
and model picker confirmations (handleModelPickerInteraction).

slash-http.ts already used undefined correctly; this brings monitor.ts
into alignment.

Addresses Codex P2 review: 'Preserve inherited block-streaming default
for model picker replies' and 'Preserve default block-streaming behavior
for button replies'.
2026-03-18 13:31:10 +00:00
teconomix
9f29865224 feat(mattermost): block streaming edit-in-place (v3.12 rebase)
Rebased onto v3.12 main. Upstream extracted deliver logic to reply-delivery.ts,
so streaming now wraps deliverMattermostReplyPayload() instead of replacing
the inline deliver body.

Changes:
- client.ts: add patchMattermostPost() + deleteMattermostPost() API helpers
- monitor.ts: inject streaming state (schedulePatch, flushPendingPatch, setInterval)
  before main inbound createReplyDispatcherWithTyping only (3 dispatch paths exist,
  only main handler gets streaming via unique humanDelay+typingCallbacks anchor)
- monitor.ts: upgrade deliver signature to (payload, info) for isFinal detection
- monitor.ts: wrap deliverMattermostReplyPayload() with isFinal streaming logic
  (final+streaming: patch in-place or fallback; non-streaming: delegate to helper)
- monitor.ts: add onPartialReply + disableBlockStreaming override in replyOptions

pnpm check: no new errors introduced (pre-existing errors on main unrelated to this PR)

Fixes: https://github.com/openclaw/openclaw/issues/XXXX
PR: https://github.com/openclaw/openclaw/pull/33506
2026-03-18 13:31:10 +00:00
Onur Solmaz
d41c9ad4cb
Release: add plugin npm publish workflow (#47678)
* Release: add plugin npm publish workflow

* Release: make plugin publish scope explicit
2026-03-18 13:44:23 +01:00
Ayaan Zaidi
f2655e1e92
test(telegram): fix incomplete sticker-cache mocks in tests 2026-03-18 15:37:24 +05:30
Vincent Koc
238c036b0d Tlon: pin api-beta to current known-good commit 2026-03-18 02:43:43 -07:00
Vincent Koc
f96ee99bbc Plugin SDK: harden provider auth seams 2026-03-18 02:29:25 -07:00
Vincent Koc
d8a1ad0f0d Plugin SDK: split provider auth login seam 2026-03-18 02:04:10 -07:00
Vincent Koc
1040ae56b5 Telegram: fix reply-runtime test typings 2026-03-18 01:53:29 -07:00
Vincent Koc
61a19107e1 Tlon: install api from tarball artifact 2026-03-18 01:49:47 -07:00
Vincent Koc
d1ef7d64e9 Contracts: harden provider registry loading 2026-03-18 01:30:05 -07:00
Ayaan Zaidi
0567f111ac
test(telegram): stabilize inbound media harness 2026-03-18 13:35:56 +05:30
Ayaan Zaidi
d9e776eb47
test(telegram): align create-bot assertions 2026-03-18 13:35:56 +05:30
Vincent Koc
9b6859e5db Feishu: break plugin-sdk setup cycle 2026-03-18 01:02:16 -07:00
Vincent Koc
2afa556746 Format: sync seam fixes with oxfmt 2026-03-18 01:02:16 -07:00
Vincent Koc
0ae3e70a5c Plugin SDK: fix contract seam regressions 2026-03-18 00:50:19 -07:00
Vincent Koc
fbd88e2c8f
Main recovery: restore formatter and contract checks (#49570)
* Extensions: fix oxfmt drift on main

* Plugins: restore runtime barrel exports on main

* Config: restore web search compatibility types

* Telegram: align test harness with reply runtime

* Plugin SDK: fix channel config accessor generics

* CLI: remove redundant search provider casts

* Tests: restore main typecheck coverage

* Lobster: fix test import formatting

* Extensions: route bundled seams through plugin-sdk

* Tests: use extension env helper for xai

* Image generation: fix main oxfmt drift

* Config: restore latest main compatibility checks

* Plugin SDK: align guardrail tests with lint

* Telegram: type native command skill mock
2026-03-18 00:30:01 -07:00
Vincent Koc
466510b6d8 refactor: replace "seam" terminology across codebase
Replace "seam" with clearer terms throughout:
- "surface" for public API/extension boundaries
- "boundary" for plugin/module interfaces
- "interface" for runtime connection points
- "hook" for test injection points
- "palette" for the lobster palette reference

Also delete experiments/acp-pluginification-architecture-plan.md

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 00:20:15 -07:00
Ayaan Zaidi
6802a768cf
fix(zalo): break account helper cycles 2026-03-18 12:46:09 +05:30
Ayaan Zaidi
4e265fe7d6
test(telegram): fix native command runtime mocks 2026-03-18 12:46:09 +05:30
Vincent Koc
c99c4b1e27
Plugin SDK: restore read-only directory inspection seam 2026-03-18 00:10:35 -07:00
Vincent Koc
0dda3e66b5 Plugin SDK: align docs and fix runtime imports 2026-03-17 23:57:38 -07:00
Vincent Koc
3d31ba7830
Plugin SDK: guard package subpaths and fix Twitch setup export
* fix(plugins): add missing secret-input-schema build entry and Matrix runtime export

buildSecretInputSchema was not included in plugin-sdk-entrypoints.json,
so it was never emitted to dist/plugin-sdk/secret-input-schema.js. This
caused a ReferenceError during onboard when configuring channels that use
secret input schemas (matrix, feishu, mattermost, bluebubbles, nextcloud-talk, zalo).

Additionally, the Matrix extension's hand-written runtime-api barrel was
missing the re-export, unlike other extensions that use `export *` from
their plugin-sdk subpath.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Plugin SDK: guard package subpaths and fix Twitch setup export

* Plugin SDK: fix import guardrail drift

---------

Co-authored-by: hxy91819 <masonxhuang@icloud.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 23:56:49 -07:00
Vincent Koc
0385553918 Plugin SDK: trim lobster and qwen helper exports 2026-03-17 23:48:19 -07:00
Vincent Koc
d341d68180 Plugin SDK: trim legacy helper exports 2026-03-17 23:32:16 -07:00
Val Alexander
d1fe30b35f
Plugins: add Twitch runtime barrel 2026-03-18 01:29:33 -05:00
Vincent Koc
fe84354a33
fix(plugins): add missing secret-input-schema build entry and Matrix runtime export
buildSecretInputSchema was not included in plugin-sdk-entrypoints.json,
so it was never emitted to dist/plugin-sdk/secret-input-schema.js. This
caused a ReferenceError during onboard when configuring channels that use
secret input schemas (matrix, feishu, mattermost, bluebubbles, nextcloud-talk, zalo).

Additionally, the Matrix extension's hand-written runtime-api barrel was
missing the re-export, unlike other extensions that use `export *` from
their plugin-sdk subpath.

Co-authored-by: hxy91819 <masonxhuang@icloud.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 23:28:23 -07:00
Vincent Koc
b333eb137b Tests: align plugin test imports with local barrels 2026-03-17 23:23:58 -07:00
Vincent Koc
77dfa73736 Plugins: internalize whatsapp SDK imports 2026-03-17 23:10:51 -07:00
Vincent Koc
6e723dfd69 Plugins: internalize medium extension SDK imports 2026-03-17 23:09:26 -07:00
Vincent Koc
df79113593 Plugins: internalize telegram SDK imports 2026-03-17 23:09:26 -07:00
Vincent Koc
0bdd17aef2 Plugins: finish signal SDK internalization 2026-03-17 23:09:26 -07:00
scoootscooob
08a0219b1a
Google Chat: thin runtime api seam (#49504)
Merged via squash.

Prepared head SHA: 3369cf2c35cbf03bc4008d123e69f43f1cc083e9
Co-authored-by: scoootscooob <167050519+scoootscooob@users.noreply.github.com>
Co-authored-by: scoootscooob <167050519+scoootscooob@users.noreply.github.com>
Reviewed-by: @scoootscooob
2026-03-17 23:02:30 -07:00
Vincent Koc
d949a513c5 Plugins: internalize small extension SDK imports 2026-03-17 23:01:28 -07:00
Ayaan Zaidi
c245c8b39d
refactor(plugin-sdk): split interactive runtime helpers 2026-03-18 11:30:34 +05:30
Vincent Koc
4d551e6f33 Plugins: internalize acpx SDK imports 2026-03-17 22:58:43 -07:00
Vincent Koc
02826eaa0c Plugins: internalize lobster SDK imports 2026-03-17 22:58:03 -07:00
Vincent Koc
ed479f96a1 Plugins: internalize qwen portal auth SDK imports 2026-03-17 22:57:58 -07:00