* feat(slack): add download-file action for on-demand file attachment access
Adds a new `download-file` message tool action that allows the agent to
download Slack file attachments by file ID on demand. This is a prerequisite
for accessing images posted in thread history, where file attachments are
not automatically resolved.
Changes:
- Add `files` field to `SlackMessageSummary` type so file IDs are
visible in message read results
- Add `downloadSlackFile()` to fetch a file by ID via `files.info`
and resolve it through the existing `resolveSlackMedia()` pipeline
- Register `download-file` in `CHANNEL_MESSAGE_ACTION_NAMES`,
`MESSAGE_ACTION_TARGET_MODE`, and `listSlackMessageActions`
- Add `downloadFile` dispatch case in `handleSlackAction`
- Wire agent-facing `download-file` → internal `downloadFile` in
`handleSlackMessageAction`
Closes#24681
* style: fix formatting in slack-actions and actions
* test(slack): cover download-file action path
---------
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
* fix(slack): use SLACK_USER_TOKEN when connecting to Slack (closes#26480)
* test(slack): fix account fixture typing for user token source
---------
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
* feat(slack): track thread participation for auto-reply without @mention
* fix(slack): scope thread participation cache by accountId and capture actual reply thread ts
* fix(slack): capture reply thread ts from all delivery paths and only after success
* Slack: add changelog for thread participation cache behavior
---------
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
* fix(browser): expose url alias in tool schema
* fix(browser): accept url alias for open and navigate
* test(browser): cover url alias for open and navigate
`pickDefaultNode()` returned null when multiple connected canvas-capable
nodes existed and none matched the local Mac heuristic. This caused
"node required" errors for agents (especially sub-agents) calling the
canvas tool without an explicit node parameter.
In multi-node setups, any canvas-capable node is a valid target — the
receiving node broadcasts A2UI surfaces to all other connected devices.
Fall back to the first connected candidate instead of failing.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The web_search tool was not respecting HTTP_PROXY/HTTPS_PROXY environment
variables, causing 'fetch failed' errors when running behind a proxy.
This fix adds ProxyAgent support for the Brave Search API, similar to how
other tools in OpenClaw handle proxy configuration.
Fixes#27405
* Telegram: soft-fail reactions and fallback to inbound message id
* Telegram: soft-fail missing reaction message id
* Update CHANGELOG.md
---------
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
* feat: add Gemini (Google Search grounding) as web_search provider
Add Gemini as a fourth web search provider alongside Brave, Perplexity,
and Grok. Uses Gemini's built-in Google Search grounding tool to return
search results with citations.
- Add runGeminiSearch() with Google Search grounding via tools API
- Resolve Gemini's grounding redirect URLs to direct URLs via parallel
HEAD requests (5s timeout, graceful fallback)
- Add Gemini config block (apiKey, model) with env var fallback
- Default model: gemini-2.5-flash (fast, cheap, grounding-capable)
- Strip API key from error messages for security
- Add config validation tests for Gemini provider
- Update docs/tools/web.md with Gemini provider documentation
Closes#13074
* feat: auto-detect search provider from available API keys
When no explicit provider is configured, resolveSearchProvider now
checks for available API keys in priority order (Brave → Gemini →
Perplexity → Grok) and selects the first provider with a valid key.
- Add auto-detection logic using existing resolve*ApiKey functions
- Export resolveSearchProvider via __testing_provider for tests
- Add 8 tests covering auto-detection, priority order, and explicit override
- Update docs/tools/web.md with auto-detection documentation
* fix: merge __testing exports, downgrade auto-detect log to debug
* fix: use defaultRuntime.log instead of .debug (not in RuntimeEnv type)
* fix: mark gemini apiKey as sensitive in zod schema
* fix: address Greptile review — add externalContent to Gemini payload, add Gemini/Grok entries to schema labels/help, remove dead schema-fields.ts
* fix(web-search): add JSON parse guard for Gemini API responses
Addresses Greptile review comment: add try/catch to handle non-JSON
responses from Gemini API gracefully, preventing runtime errors on
malformed responses.
Note: FIELD_HELP entries for gemini.apiKey and gemini.model were
already present in schema.help.ts, and gemini.apiKey was already
marked as sensitive in zod-schema.agent-runtime.ts (both fixed in
earlier commits).
* fix: use structured readResponseText result in Gemini error path
readResponseText returns { text, truncated, bytesRead }, not a string.
The Gemini error handler was using the result object directly, which
would always be truthy and never fall through to res.statusText.
Align with Perplexity/xAI/Brave error patterns.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* style: fix import order and formatting after rebase onto main
* Web search: send Gemini API key via header
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>