Bundled skill that enables the agent to transcribe audio files using
OpenAI Whisper CLI. Uses anyBins requirement so the skill is only
visible when whisper is installed. Includes brew and uv install specs.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add writeWithImages() to AsyncAgent for passing images directly to
the LLM via ImageContent. Extend Agent.run() to accept optional
images parameter. Update ChannelManager.routeIncoming() to download
media files and forward them: images as ImageContent to the LLM,
audio/video/document as file paths for agent-driven processing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add handlers for voice, audio, photo, video, and document messages.
Each handler emits a ChannelMessage with media attachment metadata.
Implement downloadMedia() to fetch files from Telegram API and save
to the local media cache directory.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add ChannelMediaAttachment type with support for audio, image, video,
and document media types. Extend ChannelMessage with optional media
field and ChannelPlugin with optional downloadMedia method.
Add MEDIA_CACHE_DIR path for downloaded media files.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Forward voice messages and audio files to the agent as <media:audio>
placeholder text. In groups, only process voice/audio that replies to
the bot. Includes caption text if present.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add sendTyping to ChannelOutboundAdapter (optional per platform)
- Implement typing lifecycle in ChannelManager (5s interval, cleanup on message_end/error/clear)
- Convert Markdown to Telegram HTML subset (bold, italic, code, links, blockquotes)
- Fallback to plain text on HTML parse errors
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Use setWindowOpenHandler to intercept window.open calls and route
them through shell.openExternal instead of navigating inside Electron.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
StreamPayload.event was missing the agent_error event type, causing
TypeScript errors in useGatewayChat and useLocalChat where the
comparison payload.event.type === "agent_error" had no type overlap.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Desktop path already forwards agent_error to chat.setError() via
use-local-chat.ts, but the Web/Gateway path was missing this handling.
Add agent_error interception in the StreamAction branch so Web clients
render LLM errors the same way Desktop does.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When the agent encounters an error (e.g. no API key configured),
the Chat UI now shows an error banner instead of silently hanging.
The user can still type and retry after fixing their configuration.
- Add AgentErrorEvent to SDK stream types
- Forward agent_error events through IPC to renderer
- Handle error events in useLocalChat hook
- Keep chat input enabled for AGENT_ERROR (retriable)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
PiAgentCore was created with an empty object when no API key was
initially configured. This broke dynamic provider switching because
setProvider() updated currentApiKey but PiAgentCore had no getApiKey
callback to read it. Always provide the callback so it dynamically
reads the current key.
Also adds AgentErrorEvent to MulticaEvent and emits it from
AsyncAgent.write() catch handlers so errors flow through the
subscriber mechanism to IPC listeners.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Each tool call added an abort listener to the shared agent signal
without cleanup, exceeding the default 10-listener limit after 11+
exec calls. Fix by using { once: true } and removing the listener
on child process close (exec) to prevent accumulation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Instead of keeping announced runs in the registry for 60 minutes
(archive sweeper), delete them right after findings are delivered
to the parent. This prevents stale completed tasks from appearing
in sessions_list on subsequent parent turns.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
After child subagents complete, the coalesced announcement runs as an
internal turn which rolls back all messages from the parent's in-memory
context. This causes the parent LLM to lose findings in subsequent turns.
Add persistResponse option to writeInternal that re-injects the LLM's
summary as a non-internal assistant message after the internal run
completes. The internal prompt stays hidden while the summary persists
in both memory and session JSONL for future turns.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Document the three independent message paths (Desktop IPC, Web
WebSocket, Channel Bot API) including send/receive flows, error
handling, lastRoute pattern, and event filtering comparison.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Forward agent_error as passthrough event to renderer. Add
clearLastRoute() calls in hub:sendMessage and localChat:send
handlers so channel replies stop when desktop sends a message.
Handle agent_error in use-local-chat to show error UI.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add agent_error event type to MulticaEvent union so errors from
agent runs reach subscribe() consumers (Desktop IPC + Channel).
Make emitMulticaEvent public on Runner so AsyncAgent can emit errors.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace per-conversation agent creation with single Hub agent model.
Messages from channels are routed to the existing Hub agent via
agent.write(), and replies are sent back through the lastRoute context.
Desktop and Gateway paths call clearLastRoute() so channel replies
stop when the user switches input surface.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Announcement messages from subagent completion flows were persisted as
regular user messages, polluting conversation history and leaking
orchestration instructions to frontend/CLI.
- Add `internal?: boolean` to SessionEntry message variant
- SessionManager.saveMessage accepts { internal: true } option
- SessionManager.loadMessages filters internal by default
- Agent.runInternal() tags messages as internal, rolls back from memory
- Agent.withRunMutex() prevents concurrent run/runInternal mis-tagging
- AsyncAgent.writeInternal() suppresses event forwarding during internal runs
- Announce flows use writeInternal() instead of write()
- Desktop IPC getHistory reads from session storage (filtered)
- CLI session show parses SessionEntry, supports --show-internal flag
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Change default security from "allowlist" to "full" (allow all commands)
- Change default ask from "on-miss" to "off" (never prompt)
- Change DEFAULT_APPROVAL_TIMEOUT_MS from 60s to -1 (no timeout)
- Support timeoutMs=-1 to wait indefinitely for user decision
- Update CLI and Hub approval flows to skip setTimeout when timeout<0
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds a new `sessions_list` tool to the Subagent tool group, allowing
agents to query the status of their spawned sub-tasks. Supports both
list mode (all runs) and detail mode (specific runId).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Cover formatCoalescedAnnouncementMessage (single/multi record,
mixed outcomes, missing findings), registry coalescing state
transitions, shutdown capture, and new field serialization.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When multiple children complete, buffer findings per-child and only
send one combined announcement to the parent after all unannounced
runs for the same requester have finished. This avoids N separate
LLM calls and gives the parent a complete picture of all results.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Handle 409 conflict (another bot instance running) with a clear error
message instead of an unhandled promise rejection.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move channel configuration into the existing credentials.json5 under a
`channels` section, matching OpenClaw's single-config-file approach.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Wire up channel system in Hub constructor and shutdown.
Add grammy dependency for Telegram bot support.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
ChannelManager orchestrates channel lifecycles and routes messages to per-conversation Agents.
Telegram plugin uses grammy for long polling with group @mention detection.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Introduces the extensible channel plugin architecture for messaging platform integrations.
- ChannelPlugin interface with config, gateway, and outbound adapters
- Plugin registry with register/get/list operations
- Config loader for ~/.super-multica/channels.json5
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>