Adds a complete Linq iMessage channel adapter that replaces the existing
iMessage channel's Mac Mini + dedicated Apple ID + SSH wrapper + Full Disk
Access setup with a single API key and phone number.
Core implementation (src/linq/):
- types.ts: Linq webhook event and message types
- accounts.ts: Multi-account resolution from config (env/file/inline token)
- send.ts: REST outbound via Linq Blue V3 API (messages, typing, reactions)
- probe.ts: Health check via GET /v3/phonenumbers
- monitor.ts: Webhook HTTP server with HMAC-SHA256 signature verification,
replay protection, inbound debouncing, and full dispatch pipeline integration
Extension plugin (extensions/linq/):
- ChannelPlugin implementation with config, security, setup, outbound,
gateway, and status adapters
- Supports direct and group chats, reactions, and media
Wiring:
- Channel registry, dock, config schema, plugin-sdk exports, and plugin
runtime all updated to include the new linq channel
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(slack): download all files in multi-image messages
resolveSlackMedia() previously returned after downloading the first
file, causing multi-image Slack messages to lose all but the first
attachment. This changes the function to collect all successfully
downloaded files into an array, matching the pattern already used by
Telegram, Line, Discord, and iMessage adapters.
The prepare handler now populates MediaPaths, MediaUrls, and
MediaTypes arrays so downstream media processing (vision, sandbox
staging, media notes) works correctly with multiple attachments.
Fixes#11892, #7536
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(slack): preserve MediaTypes index alignment with MediaPaths/MediaUrls
The filter(Boolean) on MediaTypes removed entries with undefined contentType,
shrinking the array and breaking index correlation with MediaPaths and MediaUrls.
Downstream code (media-note.ts, attachments.ts) requires these arrays to have
equal lengths for correct per-attachment MIME type lookup. Replace filter(Boolean)
with a nullish coalescing fallback to "application/octet-stream".
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(slack): align MediaType fallback and tests (#15447) (thanks @CommanderCrowCode)
* fix: unblock plugin-sdk account-id typing (#15447)
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
* feat: add Claude Opus 4.6 to built-in model catalog
- Update default model from claude-opus-4-5 to claude-opus-4-6
- Add opus-4.6 model ID normalization
- Add claude-opus-4-6 to live model filter prefixes
- Update image tool to prefer claude-opus-4-6 for vision
- Add CLI backend alias for opus-4.6
- Update onboard auth default selections to include opus-4.6
- Update model picker placeholder
Closes#9811
* test: update tests for claude-opus-4-6 default
- Fix model-alias-defaults test to use claude-opus-4-6
- Fix image-tool test to expect claude-opus-4-6 in fallbacks
* feat: support claude-opus-4-6
* docs: update changelog for opus 4.6 (#9853) (thanks @TinyTb)
* chore: bump pi to 0.52.0
---------
Co-authored-by: Slurpy <slurpy@openclaw.ai>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
The previous migration to tsdown was reverted because it caused a ~20x slowdown when running OpenClaw from the repo. @hyf0 investigated and found that simply renaming the `dist` folder also caused the same slowdown. It turns out the Plugin script loader has a bunch of voodoo vibe logic to determine if it should load files from source and compile them, or if it should load them from dist. When building with tsdown, the filesystem layout is different (bundled), and so some files weren't in the right location, and the Plugin script loader decided to compile source files from scratch using Jiti.
The new implementation uses tsdown to embed `NODE_ENV: 'production'`, which we now use to determine if we are running OpenClaw from a "production environmen" (ie. from dist). This removes the slop in favor of a deterministic toggle, and doesn't rely on directory names or similar.
There is some code reaching into `dist` to load specific modules, primarily in the voice-call extension, which I simplified into loading an "officially" exported `extensionAPI.js` file. With tsdown, entry points need to be explicitly configured, so we should be able to avoid sloppy code reaching into internals from now on. This might break some existing users, but if it does, it's because they were using "private" APIs.
- Update @mariozechner/pi-agent-core, pi-ai, pi-coding-agent, pi-tui to 0.51.0
- Delete src/types/pi-coding-agent.d.ts (declared additionalExtensionPaths which SDK never supported)
- Fix ToolDefinition.execute signature (parameter order changed in 0.51.0)
- Remove dead additionalExtensionPaths from createAgentSession calls