Commit Graph

3004 Commits

Author SHA1 Message Date
Peter Steinberger
15c3aa82bf refactor: unify approval forwarding and rendering 2026-03-30 08:28:33 +09:00
Peter Steinberger
8720070fe0 refactor: rename channel approval capabilities 2026-03-30 08:28:33 +09:00
Armand du Plessis
b888741462 fix: QMD 1.1+ mcporter compatibility with legacy fallback [AI-assisted] (#54728)
* fix: QMD 2.0 mcporter compatibility with v1 fallback [AI-assisted]

QMD 2.0 unified all search modes under a single 'query' MCP tool
with typed sub-queries, replacing search/vector_search/deep_search.

- Default to QMD 2.0 'query' tool with {searches: [...]} format
- Auto-detect version on first call and cache for the session
- Fall back to v1 tool names if 'query' is not found
- Backwards compatible: v1 users get one retry then cached

AI-assisted: Built with Claude (Opus 4.6) via OpenClaw. Fully tested
against QMD 2.0 with mcporter 0.7.3 daemon. v1 fallback path not
live-tested (no v1 instance available). Code reviewed and understood.

* test: add QMD v2 tool format and v1 fallback tests

- Verify mcporter bridge uses 'query' tool with {searches: [...]} format (v2)
- Verify fallback to 'deep_search' with {query, limit} format when v2 not found
- Verify v1 fallback logs a warning for visibility

* fix: address review feedback — multi-collection v1 fallback + test cleanup

- Fix multi-collection v1 fallback: resolve effectiveTool at the top
  of runQmdSearchViaMcporter so stale 'query' tool names from the
  loop are corrected once qmdMcpToolVersion is set to 'v1'
- Assert callCount in v1 fallback test (one v2 attempt + one v1 retry)
- Remove spurious global state reset (qmdMcpToolVersion is per-instance)

* docs: correct version references — breaking change was QMD 1.5, not 2.0

The MCP tool removal (search/vector_search/deep_search → query) happened
in QMD 1.5, not 2.0. QMD 2.0 was the SDK/library refactor.
Updated all comments, test names, and documentation to reflect this.

* fix: respect searchMode when building v2 mcporter queries

When searchMode is 'search' (BM25), only send lex sub-query.
When 'vsearch', only send vec. Default 'query' sends all three
(lex + vec + hyde) for full hybrid search with reranking.

Previously all three sub-queries were always sent regardless of
the configured searchMode, which could trigger unnecessary vector
embedding and HyDE LLM work on setups explicitly requesting
lexical-only search.

Addresses Codex P2 review feedback.

* docs: correct to QMD 1.1.0 — that's the actual version that removed the tools

Per CHANGELOG.md, MCP tools search/vector_search/deep_search were removed
in QMD 1.1.0 (2026-02-20), not 1.5 (which doesn't exist). Versions go
1.0.7 → 1.1.0 → 1.1.1 → 1.1.2 → 1.1.5 → 1.1.6 → 2.0.0.

* fix: remove redundant v1 guard (race condition) + tighten error matching

1. Remove qmdMcpToolVersion !== 'v1' guard from catch block. It's
   redundant (effectiveTool === 'query' already prevents infinite retry)
   and introduces a race condition: concurrent searches that both probe
   with 'query' while version is null would fail after the first sets
   version to 'v1'.

2. Tighten isToolNotFoundError regex to require 'Tool' near 'not found'
   (within 40 chars, no sentence boundary). Prevents false-positives
   when user query text in the mcporter args contains both words.

Addresses Greptile P1 (concurrent-search race) and Codex P2
(overly broad error matching).

* fix: address claude code review — type safety, minScore docs, explicit switch

- Restore type union for tool param instead of bare string
- Add comment explaining minScore omission for v2 (QMD 1.1+ uses
  its own reranking pipeline, no minScore parameter)
- Make buildV2Searches switch exhaustive with explicit case 'query'

* fix: resolve CI failures — oxfmt formatting + TypeScript type errors

- Run oxfmt to fix formatting issues
- Add union return type to resolveQmdMcpTool() and
  runMcporterAcrossCollections() tool param to satisfy tsc
  (string was not assignable to the union type)

* fix(memory): align qmd query collection filters

* fix(memory): narrow qmd missing-tool fallback detection

* fix(memory): ignore qmd timeout text for v1 fallback

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-03-30 08:07:14 +09:00
Peter Steinberger
52fb4a149a refactor: share approval interactive renderers 2026-03-30 08:03:59 +09:00
Peter Steinberger
cfac0e8698 refactor: move plugin-owned test support into plugins 2026-03-30 08:03:04 +09:00
Vincent Koc
1ace91ee00 fix(bluebubbles): coalesce URL-only inbound shares 2026-03-30 08:00:25 +09:00
Gustavo Madeira Santana
e5dac0c39e CLI: keep root help plugin descriptors non-activating (#57294)
Merged via squash.

Prepared head SHA: c8da48f689
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-03-29 18:49:57 -04:00
Peter Steinberger
1efef8205c fix: stabilize extensions surface test gate 2026-03-30 07:47:58 +09:00
Peter Steinberger
07c6981c70 refactor: localize zalo test support 2026-03-30 07:47:28 +09:00
Peter Steinberger
8861cdbb6f refactor(plugin-sdk): untangle extension test seams 2026-03-29 23:43:53 +01:00
Peter Steinberger
69eea2cb80 refactor: split approval auth delivery and rendering 2026-03-30 07:36:18 +09:00
Peter Steinberger
f8dc4305a5 refactor: share native approval delivery helpers 2026-03-30 07:16:33 +09:00
Peter Steinberger
6d9a7224aa refactor: unify approval command authorization 2026-03-30 07:06:29 +09:00
Peter Steinberger
168ab94eee refactor(config): pin runtime snapshot and drop ttl cache 2026-03-29 22:57:31 +01:00
Peter Steinberger
3ec000b995 refactor: align same-chat approval routing 2026-03-30 06:52:28 +09:00
Peter Steinberger
2e0682d930 refactor: finish decoupling plugin sdk seams 2026-03-29 22:42:06 +01:00
Peter Steinberger
574d3c5213 fix: make same-chat approvals work across channels 2026-03-30 06:35:04 +09:00
Peter Steinberger
1ca01b738b fix: stabilize exec approval approver routing 2026-03-30 06:25:03 +09:00
Peter Steinberger
2f19b303c6 build: fix packaged plugin dependency ownership 2026-03-29 22:21:29 +01:00
Peter Steinberger
35233bae96 refactor: decouple bundled plugin sdk surfaces 2026-03-29 21:20:46 +01:00
Peter Steinberger
73477eee4c fix: harden ACP plugin tools bridge (#56867) (thanks @joe2643) 2026-03-30 05:09:59 +09:00
Gustavo Madeira Santana
9b4f26e70a Plugins/CLI: add descriptor-backed lazy root command registration (#57165)
Merged via squash.

Prepared head SHA: ad1dee32eb
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-03-29 16:02:59 -04:00
Peter Steinberger
d330782ed1 fix(matrix): stop discovering runtime helper as plugin entry 2026-03-29 21:00:57 +01:00
Gustavo Madeira Santana
dc192d7b2f Build: mirror Matrix crypto WASM runtime deps (#57163)
Merged via squash.

Prepared head SHA: b3aeb9d08a
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-03-29 15:57:28 -04:00
Peter Steinberger
cce6d3bbb7 fix: resolve CI type and lint regressions 2026-03-30 04:51:33 +09:00
Peter Steinberger
855878b4f0 fix: stabilize serial test suite 2026-03-30 04:46:04 +09:00
Peter Steinberger
fc5fdcb091 refactor(plugin-sdk): remove bundled provider setup shims 2026-03-29 20:23:20 +01:00
Marcus Castro
34648235a3 WhatsApp: use shared resolveReactionMessageId for context-aware reactions (#57226)
Wire the shared resolveReactionMessageId helper into the WhatsApp
channel adapter, matching the pattern already used by Telegram, Signal,
and Discord. The model can now react to the current inbound message
without explicitly providing a messageId.

Safety guards:
- Only falls back to context when the source is WhatsApp
- Suppresses fallback when targeting a different chat (normalized comparison)
- Throws ToolInputError (400) instead of plain Error (500) when messageId
  is missing, preserving gateway error mapping
2026-03-29 15:42:19 -03:00
Peter Steinberger
5801506ce7 test(discord): fix hoisted configured-binding mocks 2026-03-29 19:17:08 +01:00
Keith Elliott
2d2e386b94 fix(matrix): resolve crypto bootstrap failure and multi-extension idHint warning (#53298)
Merged via squash.

Prepared head SHA: 6f5813ffff
Co-authored-by: keithce <2086282+keithce@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-03-29 12:38:10 -04:00
Peter Steinberger
637b4c8193 refactor: move remaining provider policy into plugins 2026-03-29 23:05:58 +09:00
Peter Steinberger
edc58a6864 refactor: generalize provider transport hooks 2026-03-29 23:05:58 +09:00
Peter Steinberger
8109195ad8 fix(plugin-sdk): avoid recursive bundled facade loads 2026-03-29 15:00:25 +01:00
Peter Steinberger
2c9bc0bb78 chore(deps): bump workspace dependencies 2026-03-29 14:41:58 +01:00
Peter Steinberger
f1af7d66d2 chore: bump version to 2026.3.29 2026-03-29 14:33:12 +01:00
Thomas M
0a01386756 fix: canonicalize session keys at write time (#30654) (thanks @thomasxm)
* fix: canonicalize session keys at write time to prevent orphaned sessions (#29683)

resolveSessionKey() uses hardcoded DEFAULT_AGENT_ID="main", but all read
paths canonicalize via cfg. When the configured default agent differs
(e.g. "ops" with mainKey "work"), writes produce "agent:main:main" while
reads look up "agent:ops:work", orphaning transcripts on every restart.

Fix all three write-path call sites by wrapping with
canonicalizeMainSessionAlias:
- initSessionState (auto-reply/reply/session.ts)
- runWebHeartbeatOnce (web/auto-reply/heartbeat-runner.ts)
- resolveCronAgentSessionKey (cron/isolated-agent/session-key.ts)

Add startup migration (migrateOrphanedSessionKeys) to rename existing
orphaned keys to canonical form, merging by most-recent updatedAt.

* fix: address review — track agent IDs in migration map, align snapshot key

P1: migrateOrphanedSessionKeys now tracks agentId alongside each store
path in a Map instead of inferring from the filesystem path. This
correctly handles custom session.store templates outside the default
agents/<id>/ layout.

P2: Pass the already-canonicalized sessionKey to getSessionSnapshot so
the heartbeat snapshot reads/restores use the same key as the write path.

* fix: log migration results at all early return points

migrateOrphanedSessionKeys runs before detectLegacyStateMigrations, so
it can canonicalize legacy keys (e.g. "main" → "agent:main:main") before
the legacy detector sees them. This caused the early return path to skip
logging, breaking doctor-state-migrations tests that assert log.info was
called.

Extract logMigrationResults helper and call it at every return point.

* fix: handle shared stores and ~ expansion in migration

P1: When session.store has no {agentId}, all agents resolve to the same
file. Track all agentIds per store path (Map<path, Set<id>>) and run
canonicalization once per agent. Skip cross-agent "agent:main:*"
remapping when "main" is a legitimate configured agent sharing the store,
to avoid merging its data into another agent's namespace.

P2: Use expandHomePrefix (environment-aware ~ resolution) instead of
os.homedir() in resolveStorePathFromTemplate, matching the runtime
resolveStorePath behavior for OPENCLAW_HOME/HOME overrides.

* fix: narrow cross-agent remap to provable orphan aliases only

Only remap agent:main:* keys where the suffix is a main session alias
("main" or the configured mainKey). Other agent:main:* keys — hooks,
subagents, cron sessions, per-sender keys — may be intentional
cross-agent references and must not be silently moved into another
agent's namespace.

* fix: run orphan-key session migration at gateway startup (#29683)

* fix: canonicalize cross-agent legacy main aliases in session keys (#29683)

* fix: guard shared-store migration against cross-agent legacy alias remap (#29683)

* refactor: split session-key migration out of pr 30654

---------

Co-authored-by: Your Name <your_email@example.com>
Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-03-29 18:59:25 +05:30
Peter Steinberger
270d0c5158 fix: avoid telegram plugin self-recursive sdk imports 2026-03-29 11:32:29 +01:00
xingjie zhou
81193336d0 fix(acpx): read ACPX_PINNED_VERSION from package.json instead of hard… (#49089)
* fix(acpx): read ACPX_PINNED_VERSION from package.json instead of hardcoding

The hardcoded ACPX_PINNED_VERSION ("0.1.16") falls out of sync with the bundled acpx version in package.json every release, causing ACP runtime to be marked unavailable due to version mismatch (see #43997).

* Validate and sanitize ACPX version retrieval

Add validation for acpx version from package.json
2026-03-29 18:05:55 +09:00
Hsiao A
cea7162490 feat(slack): status reaction lifecycle for tool/thinking progress indicators (#56430)
Merged via squash.

Prepared head SHA: 1ba5df3e3b
Co-authored-by: hsiaoa <70124331+hsiaoa@users.noreply.github.com>
Co-authored-by: frankekn <4488090+frankekn@users.noreply.github.com>
Reviewed-by: @frankekn
2026-03-29 16:49:53 +08:00
Peter Steinberger
8e0ab35b0e refactor(plugins): decouple bundled plugin runtime loading 2026-03-29 09:10:38 +01:00
Vignesh Natarajan
8bdb518bde Memory/LanceDB: fix bundled runtime manifest lookup (#56623) 2026-03-29 00:37:46 -07:00
Peter Steinberger
c48e0f8e6a style: normalize import order and formatting 2026-03-29 16:33:22 +09:00
Peter Steinberger
04c976b43d refactor(markdown): share render-aware chunking 2026-03-29 16:33:22 +09:00
Peter Steinberger
c664b67796 fix: apply Mistral compat across proxy transports 2026-03-29 16:32:31 +09:00
Ayaan Zaidi
4a5885df3a fix(imessage): try all inbound echo ids 2026-03-29 13:00:01 +05:30
Rohan Marr
b29e180ef4 fix: prevent self-chat dedupe false positives (#55359) (thanks @rmarr)
* fix(imessage): prevent self-chat dedupe false positives (#47830)

Move echo cache remember() to post-send only, add early return when
inbound message ID doesn't match cached IDs (prevents text-based
false positives in self-chat), and reduce text TTL from 5s to 3s.

Three targeted changes to fix silent user message loss in self-chat:

1. deliver.ts: Remove pre-send remember() call — cache only reflects
   successfully-delivered content, not pre-send full text.

2. echo-cache.ts: Skip text fallback when inbound has a valid message ID
   that doesn't match any cached outbound ID. In self-chat, sender == target
   so scopes collide; a user message with a fresh ID but matching text was
   incorrectly dropped as an echo.

3. echo-cache.ts: Reduce text TTL from 5000ms to 3000ms — agent echoes
   arrive within 1-2s, 5s was too wide.

Adds self-chat-dedupe.test.ts (7 tests) + updates deliver.test.ts.
BlueBubbles uses a different cache pattern — no changes needed there.

Closes #47830

* review(imessage): strip debug logs, bump echo TTL to 4s (#47830)

Bruce Phase 4 review changes:
- Remove all [IMSG-DEBUG] console.error calls from inbound-processing.ts
  and monitor-provider.ts (23 lines, left over from Phase 2 debug deploy)
- Bump SENT_MESSAGE_TEXT_TTL_MS from 3s to 4s in echo-cache.ts to give
  ~2s margin above the observed 2.2s echo arrival time under load
- Update TTL tests to reflect 4s TTL (expired at 5s, live at 3s)

* fix(imessage): add dedupe comments and canary/compat/TTL tests

* fix(imessage): address review feedback on echo cache, shadowing, and test IDs

* refactor(imessage): hoist inboundMessageId to eliminate duplicate computation (#47830)

* fix(imessage): unify self-chat echo matching

* fix: use inbound guid for self-chat echo matching (#55359) (thanks @rmarr)

---------

Co-authored-by: Rohan Marr <rmarr@users.noreply.github.com>
Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-03-29 12:51:17 +05:30
Vignesh Natarajan
1a0c3bf400 Memory: fix FTS-only branch compile on rebased main 2026-03-29 00:09:33 -07:00
Vignesh Natarajan
598f539be5 Memory: keep FTS-only indexing on reindex (#42714) 2026-03-29 00:06:49 -07:00
opriz
41c30f0c59 fix: populate FTS-only memory search without provider (#56473) (thanks @opriz)
* fix(memory): build FTS index when no embedding provider is available

* fix(memory): trigger full reindex on provider→FTS-only transition

* fix(memory): return FTS-only keyword hits at default threshold

* fix: keep FTS-only memory hits at default threshold (#56473) (thanks @opriz)

---------

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-03-29 12:22:35 +05:30
gfzhx
d458e1d05c fix(discord): do not bypass requireMention for configuredBinding channels 2026-03-29 11:17:15 +05:30