* fix(doctor): resolve false positive for local memory search when no explicit modelPath
When memorySearch.provider is 'local' (or 'auto') and no explicit
local.modelPath is configured, the runtime auto-resolves to
DEFAULT_LOCAL_MODEL (embeddinggemma-300m via HuggingFace). However,
the doctor's hasLocalEmbeddings() check only inspected the config
value and returned false when modelPath was empty, triggering a
misleading warning.
Fix: fall back to DEFAULT_LOCAL_MODEL in hasLocalEmbeddings(), matching
the runtime behavior in createLocalEmbeddingProvider().
Closes#31998
* fix: scope DEFAULT_LOCAL_MODEL fallback to explicit provider:local only
Address review feedback: canAutoSelectLocal() in the runtime skips
local for empty/hf: model paths in auto mode. The DEFAULT_LOCAL_MODEL
fallback should only apply when provider is explicitly 'local', not
when provider is 'auto' — otherwise users with no local file and no
API keys would get a clean doctor report but no working embeddings.
Add useDefaultFallback parameter to hasLocalEmbeddings() to
distinguish the two code paths.
* fix: preserve gateway probe warning for local provider with default model
When hasLocalEmbeddings returns true via DEFAULT_LOCAL_MODEL fallback,
also check the gateway memory probe if available. If the probe reports
not-ready (e.g. node-llama-cpp missing or model download failed),
emit a warning instead of silently reporting healthy.
Addresses review feedback about bypassing probe-based validation.
* fix: add changelog attribution for doctor local fallback fix (#32014) (thanks @adhishthite)
---------
Co-authored-by: Adhish <adhishthite@Adhishs-MacBook-Pro.local>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
* fix(slack): remove message.channels/message.groups handlers that crash Bolt 4.6
Bolt 4.6 rejects app.event() calls with event names starting with
"message." (e.g. "message.channels", "message.groups"), throwing
AppInitializationError on startup. These handlers were added in #31701
based on the incorrect assumption that Slack dispatches typed event
names to Bolt. In reality, Slack always delivers events with
type:"message" regardless of the Event Subscription name; the
channel_type field distinguishes the source.
The generic app.event("message") handler already receives all channel,
group, IM, and MPIM messages. The additional typed handlers were
unreachable even if Bolt allowed them, since no event payload ever
carries type:"message.channels".
This preserves the handleIncomingMessageEvent refactor from #31701
(extracting the handler into a named function) while removing only
the broken registrations.
Fixes the Slack provider crash loop affecting all accounts on
@slack/bolt >= 4.6.0.
Closes#31674 (original issue was not caused by missing handlers)
* fix: document Slack Bolt 4.6 startup handler fix (#32033) (thanks @mahopan)
---------
Co-authored-by: Peter Steinberger <steipete@gmail.com>
* fix(gateway): move plugin HTTP routes before Control UI SPA catch-all
The Control UI handler (`handleControlUiHttpRequest`) acts as an SPA
catch-all that matches every path, returning HTML for GET requests and
405 for other methods. Because it ran before `handlePluginRequest` in
the request chain, any plugin HTTP route that did not live under
`/plugins` or `/api` was unreachable — shadowed by the catch-all.
Reorder the handlers so plugin routes are evaluated first. Core
built-in routes (hooks, tools, Slack, Canvas, etc.) still take
precedence because they are checked even earlier in the chain.
Unmatched plugin paths continue to fall through to Control UI as before.
Closes#31766
* fix: add changelog for plugin route precedence landing (#31885) (thanks @Sid-Qin)
---------
Co-authored-by: Peter Steinberger <steipete@gmail.com>
* fix(cron): pass job.delivery.accountId through to delivery target resolution
* fix(cron): normalize topic-qualified target.to in messaging tool suppress check
When a cron job targets a Telegram forum topic (e.g. delivery.to =
"-1003597428309:topic:462"), delivery.to is stripped to the chatId
only by resolveOutboundTarget. However, the agent's message tool may
pass the full topic-qualified address as its target, causing
matchesMessagingToolDeliveryTarget to fail the equality check and not
suppress the tool send.
Strip the :topic:NNN suffix from target.to before comparing so the
suppress check works correctly for topic-bound cron deliveries.
Without this, the agent's message tool fires separately using the
announce session's accountId (often "default"), hitting 403 when
default bot is not in the multi-account target group.
* fix(cron): remove duplicate accountId keys after rebase
---------
Co-authored-by: jaxpkm <jaxpkm@jaxpkmdeMac-mini.local>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>