Commit Graph

1292 Commits

Author SHA1 Message Date
Peter Steinberger
a71b810e43 fix(plugin-sdk): expose session store runtime helpers 2026-04-17 17:18:12 +01:00
Peter Steinberger
54d9a09912 perf: narrow Matrix monitor reply imports 2026-04-17 17:14:44 +01:00
Peter Steinberger
d851f9e816 perf: narrow Matrix thread binding runtime imports 2026-04-17 17:04:31 +01:00
Peter Steinberger
14c4d6457a perf: narrow Matrix account runtime imports 2026-04-17 16:53:46 +01:00
Peter Steinberger
d565c2cc34 perf: add lightweight secret input runtime 2026-04-17 16:28:15 +01:00
Peter Steinberger
2a0a498b0d perf: speed Matrix handler tests 2026-04-17 16:14:28 +01:00
Peter Steinberger
3b81bf4c7c perf: narrow Matrix handler session store import 2026-04-17 16:09:10 +01:00
Peter Steinberger
418056f7a0 perf: narrow plugin SDK import surfaces 2026-04-17 16:05:09 +01:00
Chinar Amrutkar
8205de84a9 fix: clear stale telegram ACP bindings on startup (#67822) (thanks @chinar-amrutkar)
* fix(telegram): clean up thread bindings to stale/failed ACP sessions on startup

When loading persisted thread bindings on manager creation, validate each
ACP session against the session store. Remove bindings where:
- Session entry doesn't exist (deleted externally)
- Session status is failed/killed/timeout
- ACP runtime state is 'error'

This addresses issue #60102 where Telegram DMs remained routed to stale
ACP sessions even after restart, because the binding file persisted
across restarts without validating the target session was still valid.

* fix(telegram): guard against null session entry and transient store read failures

Address review comments on PR #67822:

1. Skip bindings when readAcpSessionEntry returns null or when
   session store is temporarily unreadable (storeReadFailed: true).
   Without this, a transient I/O error would mark all ACP bindings
   as stale and delete them on every startup.

2. Only set needsPersist when bindings were actually removed.
   Previously, stale session keys from OTHER accounts could set
   needsPersist=true even when zero bindings were removed for
   the current account — causing spurious disk writes.

Also clean up redundant optional chaining on entry.status now
that we guard against undefined/nullable sessionEntry.

* perf(telegram): dedupe ACP session reads in startup cleanup

Cache readAcpSessionEntry calls by targetSessionKey. Multiple bindings
to the same ACP session now result in a single session store read instead
of one read per binding.

Addresses chatgpt-codex-connector P2 review comment on PR #67822.

* fix(telegram): skip non-ACP session keys in stale binding cleanup

Address chatgpt-codex-connector P1 review comment on PR #67822:

Plugin-bound Telegram conversations use "plugin-binding:*" keys
with targetKind === "acp", but these are NOT ACP runtime sessions.
readAcpSessionEntry() returns no entry for them, so !sessionEntry.entry
would classify them as stale and delete them on every startup.

Now checks isAcpSessionKey(binding.targetSessionKey) to skip plugin-bound
sessions from the stale session cleanup scan.

Also clarifies the comment to explain why we use targetKind === "acp"
// together with isAcpSessionKey() check.

* fix(telegram): import isAcpSessionKey from sessions/session-key-utils

isAcpSessionKey is not re-exported from openclaw/plugin-sdk/routing.
Fix import to use the correct subpath: openclaw/sessions/session-key-utils.

Addresses chatgpt-codex-connector P1 review comment on PR #67822.

* fix(telegram): import from relative path, remove unused variable

- Import isAcpSessionKey from relative path ../../sessions/session-key-utils.js
  (not openclaw/sessions/session-key-utils which doesn't exist)
- Remove unused 'bindings' variable in for-of loop

Addresses CI failures on PR #67822.

* fix(telegram): export isAcpSessionKey from plugin-sdk/routing

isAcpSessionKey lives in src/routing/session-key.ts, which is already
exported via openclaw/plugin-sdk/routing. Re-export it from routing.ts
so extensions can import via the public plugin-sdk path.

Fixes chatgpt-codex-connector P1: relative path ../../sessions/session-key-utils.js
doesn't exist in the build output, making the Telegram extension fail
module resolution before startup cleanup can run.

* test(telegram): cover startup ACP binding cleanup

* fix: clear stale telegram ACP bindings on startup (#67822) (thanks @chinar-amrutkar)

---------

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-04-17 11:03:36 +05:30
Peter Steinberger
77e6e4cf87 refactor: move memory embeddings into provider plugins 2026-04-17 02:57:18 +01:00
Peter Steinberger
6ba8626c25 test: trim remaining hotspot tests 2026-04-17 02:07:26 +01:00
Peter Steinberger
8a37bb4ed6 perf: speed up security audit test imports 2026-04-16 21:54:13 +01:00
Vincent Koc
f835da1667 fix(ci): trim slow task and gateway paths 2026-04-16 13:34:34 -07:00
Gustavo Madeira Santana
21d500a65f test: expose bundled plugin QA test APIs 2026-04-16 16:18:54 -04:00
Peter Steinberger
372c0051ba test: speed up slow import-boundary tests 2026-04-16 21:14:17 +01:00
Omar Shahine
4af7641350 BlueBubbles/catchup: per-message retry cap for wedged messages (#66870) (#67426)
Merged via squash.

Prepared head SHA: 39e3cf1df5
Co-authored-by: omarshahine <10343873+omarshahine@users.noreply.github.com>
Co-authored-by: omarshahine <10343873+omarshahine@users.noreply.github.com>
Reviewed-by: @omarshahine
2026-04-15 22:23:27 -07:00
Gustavo Madeira Santana
d5933af80b QA: fix private runtime source loading (#67428)
Merged via squash.

Prepared head SHA: b8bf2b6be6
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-04-15 21:59:16 -04:00
Peter Steinberger
943cb47274 fix(qa): use exported runner sdk seam 2026-04-15 20:26:12 +01:00
Peter Steinberger
229eb72cf6 build: exclude private QA from npm package 2026-04-15 09:39:51 -07:00
Gustavo Madeira Santana
78ac118427 fix(plugins): stabilize bundled setup runtimes (#67200)
Merged via squash.

Prepared head SHA: e8d6738fd0
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-04-15 12:35:18 -04:00
Vincent Koc
97ee0c6fd3 perf(migrations): trim legacy migration and bind cold paths 2026-04-15 00:38:45 +01:00
Josh Avant
1769fb2aa1 fix(secrets): align SecretRef inspect/strict behavior across preload/runtime paths (#66818)
* Config: add inspect/strict SecretRef string resolver

* CLI: pass resolved/source config snapshots to plugin preload

* Slack: keep HTTP route registration config-only

* Providers: normalize SecretRef handling for auth and web tools

* Secrets: add Exa web search target to registry and docs

* Telegram: resolve env SecretRef tokens at runtime

* Agents: resolve custom provider env SecretRef ids

* Providers: fail closed on blocked SecretRef fallback

* Telegram: enforce env SecretRef policy for runtime token refs

* Status/Providers/Telegram: tighten SecretRef preload and fallback handling

* Providers: enforce env SecretRef policy checks in fallback auth paths

* fix: add SecretRef lifecycle changelog entry (#66818) (thanks @joshavant)
2026-04-14 17:59:28 -05:00
Gustavo Madeira Santana
4491bdad76 QA: drop dead qa-lab-runtime shim
Remove the old qa-lab-runtime shim now that qa-runtime is the only live
consumer seam. This leaves one tiny shared runtime facade instead of two
parallel names for the same private helper surface.
2026-04-14 18:53:36 -04:00
Gustavo Madeira Santana
95be2c1605 QA: replace qa-lab-runtime with qa-runtime
Introduce a tiny generic qa-runtime seam for shared live-lane helpers and
repoint qa-matrix to it. This keeps the qa-lab host split while removing
the host-owned runtime name from runner code.

Drop the old qa-lab-runtime shim/export now that nothing consumes it and
keep the plugin-sdk surface aligned with the new seam.
2026-04-14 18:53:25 -04:00
Gustavo Madeira Santana
85eac42d34 QA: remove runner install fallback catalog
Drop the generated qa-runner catalog and the missing/install placeholder
path for repo-private QA runners. The host should discover bundled QA
commands from manifest plus runtime surface only.

Also trim stale qa-matrix install docs and package metadata so the
source-only QA policy stays consistent.
2026-04-14 17:37:18 -04:00
Gustavo Madeira Santana
653100488d QA: fix matrix runner staging and host registration 2026-04-14 17:18:25 -04:00
OfflynAI
d21f07a39e fix: allow workspace-rooted absolute media paths in auto-reply (#66689)
Merged via squash.

Prepared head SHA: 48206b5627
Co-authored-by: joelnishanth <140015627+joelnishanth@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-04-14 17:04:31 -04:00
Gustavo Madeira Santana
82a2db71e8 refactor(qa): split Matrix QA into optional plugin (#66723)
Merged via squash.

Prepared head SHA: 27241bd089
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-04-14 16:28:57 -04:00
Vincent Koc
1898b2093f fix(plugin-sdk): widen root alias source candidates 2026-04-14 18:09:36 +01:00
Vincent Koc
665a8496d7 fix(plugin-sdk): sort hashed root alias dist chunks 2026-04-14 17:53:10 +01:00
Vincent Koc
16851e2d55 fix(plugin-sdk): sort safe root alias subpaths 2026-04-14 17:49:41 +01:00
Vincent Koc
4d6eeebda2 fix(plugin-sdk): share facade runtime jiti cache helper 2026-04-14 17:46:30 +01:00
Vincent Koc
a80ecb9937 fix(plugin-sdk): align root alias scoped sdk map 2026-04-14 17:39:36 +01:00
Vincent Koc
9843a4f1fc fix(plugins): share source public surface resolver 2026-04-14 17:33:15 +01:00
Vincent Koc
f12d6bf3bb fix(plugins): share public surface source extensions 2026-04-14 17:29:44 +01:00
Vincent Koc
2f29a58b4e fix(plugin-sdk): share facade activation check candidate loader 2026-04-14 17:24:33 +01:00
Vincent Koc
eea7ba5345 fix(plugin-sdk): share canonical stream hook families 2026-04-14 17:13:31 +01:00
Vincent Koc
3bb9e5f580 fix(plugin-sdk): share facade loader jiti cache plumbing 2026-04-14 17:03:44 +01:00
Vincent Koc
0d2a4b4fec fix(plugin-sdk): reuse cached plugin jiti loader helper 2026-04-14 17:01:52 +01:00
Vincent Koc
66701d5a1e fix(plugin-sdk): share opencode catalog auth helper 2026-04-14 16:48:02 +01:00
Vincent Koc
e5c38290a6 fix(plugin-sdk): share anthropic replay hook constants 2026-04-14 16:37:29 +01:00
Vincent Koc
4c15f1310b fix(plugin-sdk): share canonical replay hook families 2026-04-14 16:34:09 +01:00
Vincent Koc
9c42e6424d fix(plugins): share tool-stream defaults and align xai sdk imports 2026-04-14 16:23:40 +01:00
Vincent Koc
3487e7f8e2 fix(plugin-sdk): route shared stream helpers through one barrel 2026-04-14 16:12:59 +01:00
Vincent Koc
e121889a9f fix(plugins): share native anthropic replay hooks 2026-04-14 16:07:16 +01:00
Vincent Koc
135c3848b9 fix(plugin-sdk): share provider stream wrapper composer 2026-04-14 16:05:58 +01:00
Peter Steinberger
a88c6f0fe7 fix: bound live video generation smoke 2026-04-14 14:59:01 +01:00
Vincent Koc
381a8e860a fix(discord): return native status replies directly (#66434) 2026-04-14 09:55:02 +01:00
Omar Shahine
0362f21784 fix: sendPolicy deny should suppress delivery, not inbound processing (#53328) (#65461)
* fix: sendPolicy deny suppresses delivery, not inbound processing (#53328)

Previously, sendPolicy "deny" returned early before the agent dispatch,
preventing the agent from ever seeing the message. This broke the use
case of an agent listening on WhatsApp groups with sendPolicy: deny to
read messages without replying — the agent couldn't read them at all.

Move the deny gate from before the agent dispatch to after it. The agent
now processes inbound messages normally (context, memory, tool calls),
but all outbound delivery paths are suppressed: final replies, tool
results, block replies, working status, plan updates, typing indicators,
and TTS payloads.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: propagate sendPolicy to ACP tail dispatch instead of hardcoded allow

The ACP tail dispatch path (ctx.AcpDispatchTailAfterReset) was passing
sendPolicy: "allow" unconditionally, which would bypass delivery
suppression in a /reset <tail> turn when the session has sendPolicy deny.

Pass through the resolved sendPolicy so the tail dispatch respects it.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: guard before_dispatch hook and ACP tail dispatch under sendPolicy deny

before_dispatch handled replies were leaking through sendFinalPayload
before the suppressDelivery guard was checked. ACP tail dispatch (from
/new <tail>) was being rejected by acp-runtime.ts deny checks instead
of proceeding with delivery suppression handled downstream.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* auto-reply: propagate deny suppression to reply_dispatch

* fix(acp): suppress onReplyStart when user delivery is denied

When sendPolicy resolves to "deny", ACP tail dispatch still invoked
onReplyStart via startReplyLifecycle before the suppressUserDelivery
check. Channels wire onReplyStart to typing indicators, so deny-scoped
sessions could still emit outbound typing events on /reset <tail>
flows and command bypass paths.

Gate startReplyLifecycleOnce on suppressUserDelivery so the lifecycle
is marked started but the callback is skipped. Payload delivery was
already suppressed; this closes the typing-indicator leak flagged by
Codex review (PR #65461 P1/P2).

* fix(acp): route non-tail deny turns through ACP when suppression is wired

tryDispatchAcpReplyHook was returning early for non-tail, non-command ACP
turns under sendPolicy: "deny", causing ACP-bound sessions to fall back
to the embedded reply path instead of flowing through acpManager.runTurn.
That diverged ACP session state, tool calls, and memory whenever
delivery suppression was active.

Now the early-return only fires when sendPolicy is "deny" AND the event
lacks suppressUserDelivery — i.e., when downstream delivery suppression
is not wired up. When suppressUserDelivery is set, dispatch-acp-delivery
already drops outbound sends (see onReplyStart / deliver guards), so ACP
can safely run the turn with state consistency preserved.

Existing behavior preserved:
- Command bypass still overrides deny
- Tail dispatch still overrides deny
- Plain-text deny turns without suppression still short-circuit

Addresses Codex bot P1 feedback on #65461.

* fix: gate empty-body typing indicator behind suppressTyping (#53328)

* fix: guard plugin-binding + fast-abort outbound paths under sendPolicy deny

The original PR computed suppressDelivery inside the try block, which was
after two outbound paths:

1. The plugin-owned binding block (sendBindingNotice calls for
   unavailable/declined/error outcomes, plus the plugin's own "handled"
   outcome) ran before the suppressDelivery flag existed, so plugin
   notices still leaked under deny.
2. The fast-abort path dispatched "Agent was aborted." via
   routeReplyToOriginating / sendFinalReply before the flag existed.

Move resolveSendPolicy() above the plugin-binding block so suppressDelivery
covers every outbound path downstream, matching the PR description's claim
that "all outbound paths are guarded by the flag."

Plugin-bound inbound handling under deny: plugin handlers can emit
outbound replies we cannot rewind, so skip the claim hook entirely under
deny and fall through to normal (suppressed) agent processing.
touchConversationBindingRecord still runs so binding activity stays
tracked.

Fast-abort under deny: still run the abort and record the completed
state, just don't emit the abort reply.

Tests:
- suppresses the fast-abort reply under sendPolicy deny
- delivers the fast-abort reply normally when sendPolicy is allow
  (regression guard)
- skips plugin-bound claim hook under deny and falls through to
  suppressed agent dispatch

Addresses Codex review findings on PR #65461.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Lobster <lobster@shahine.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 16:42:25 -07:00
rafaelreis-r
68e0e456f3 fix: allow plugin commands on Slack when channel supports native commands (#64578)
Merged via squash.

Prepared head SHA: 2ec97bf0b3
Co-authored-by: rafaelreis-r <57492577+rafaelreis-r@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
2026-04-13 13:14:02 -07:00