Commit Graph

2422 Commits

Author SHA1 Message Date
Naiyuan Qing
54b3ebe9e9 feat(ui): render error messages with Markdown
Use MemoizedMarkdown for error messages so links are clickable
instead of plain text.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 08:04:19 +08:00
Naiyuan Qing
1819f4196d fix(sdk): add AgentErrorEvent to StreamPayload type
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>
2026-02-09 08:04:13 +08:00
Naiyuan Qing
56ebe613db fix(hooks): handle agent_error events in useGatewayChat
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>
2026-02-09 07:30:35 +08:00
Jiang Bohan
0e383f51ab feat(desktop): display agent errors in Chat UI instead of hanging
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>
2026-02-06 22:23:53 +08:00
Jiang Bohan
9fe6b920c4 fix(agent): always provide getApiKey callback and emit error events
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>
2026-02-06 22:23:44 +08:00
LinYushen
0edc98142d Merge pull request #102 from multica-ai/sessions-spawn-parent-trigger
feat(subagent): coalesce spawn announcements
2026-02-06 20:03:29 +08:00
yushen
c24fafadeb fix(tools): prevent AbortSignal listener leak in exec and process tools
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>
2026-02-06 19:58:31 +08:00
yushen
a3f5a21561 fix(subagent): clear run records immediately after successful announcement
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>
2026-02-06 19:53:31 +08:00
yushen
a7db286530 Merge remote-tracking branch 'origin/main' into sessions-spawn-parent-trigger 2026-02-06 19:44:17 +08:00
yushen
a3acd732e0 fix(subagent): persist LLM summary after internal announce to parent context
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>
2026-02-06 19:38:18 +08:00
Naiyuan Qing
be71614cf5 docs(channels): add message paths documentation
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>
2026-02-06 19:35:51 +08:00
Naiyuan Qing
e99600c356 fix(desktop): register ChatPage element in router
The /chat route was missing its element prop, causing React Router
to render an empty Outlet.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 19:35:46 +08:00
Naiyuan Qing
72598322d1 feat(desktop): handle agent_error events and clearLastRoute in IPC
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>
2026-02-06 19:35:39 +08:00
Naiyuan Qing
4a503ecf4c feat(agent): add AgentErrorEvent for error propagation via subscribe
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>
2026-02-06 19:35:32 +08:00
Naiyuan Qing
9bb1fd6e12 refactor(channels): rewrite ChannelManager with lastRoute pattern
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>
2026-02-06 19:35:25 +08:00
yushen
a50239a9f5 fix(subagent): require coalesced announce to include all findings 2026-02-06 19:12:51 +08:00
yushen
12075b96f2 fix(subagent): capture latest non-empty findings from child runs 2026-02-06 19:10:44 +08:00
yushen
4d6017e782 fix(subagent): forward assistant stream events for internal announce 2026-02-06 19:04:40 +08:00
yushen
9687e7f2a6 fix(subagent): forward announce replies from internal runs 2026-02-06 18:58:54 +08:00
yushen
f7267f6698 fix(agent): prevent internal run leaks in async streams 2026-02-06 18:38:54 +08:00
yushen
d392238be3 feat(subagent): tag internal orchestration messages and filter from user-facing history
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>
2026-02-06 18:34:11 +08:00
LinYushen
f31439ee97 Merge pull request #104 from multica-ai/explore-approval-config
feat(exec-approval): relax defaults and support no-timeout
2026-02-06 18:13:09 +08:00
yushen
6ecdbc5783 fix(exec-approval): treat expiresAtMs=-1 as non-expiring 2026-02-06 18:09:01 +08:00
yushen
a36cbac3fd feat(exec-approval): default to full/off security and support no-timeout
- 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>
2026-02-06 18:02:07 +08:00
yushen
9cc89cf297 feat(subagent): add sessions_list tool for viewing spawned sub-tasks
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>
2026-02-06 17:58:22 +08:00
Bohan Jiang
dacf8894e9 Merge pull request #103 from multica-ai/feat/heartbeat-mechanism
feat(heartbeat): add heartbeat runner and integrate with hub/cron
2026-02-06 17:46:51 +08:00
Jiang Bohan
02838bba78 fix(desktop): remove heartbeat section from home page 2026-02-06 17:36:46 +08:00
yushen
7726079648 fix(subagent): recover delete cleanup after crash 2026-02-06 17:31:21 +08:00
Jiang Bohan
b9d9ae99b0 fix(heartbeat): keep manual trigger runs out of chat stream 2026-02-06 17:28:25 +08:00
Jiang Bohan
9f2a1c240f fix(hub): suppress heartbeat ack messages in streamed chat 2026-02-06 17:25:22 +08:00
yushen
7f9a0181c8 test(subagent): add coalescing announcement tests
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>
2026-02-06 17:24:44 +08:00
yushen
6786af4aa3 feat(subagent): coalesce announcements into single parent notification
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>
2026-02-06 17:24:39 +08:00
Naiyuan Qing
ee95102613 docs(channel): add OpenClaw channel system source code research
Comprehensive research document covering OpenClaw's channel architecture,
plugin system, message flow (inbound → agent → outbound), Telegram
integration details, routing/session management, and security model.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 17:13:43 +08:00
Jiang Bohan
9663079f48 feat(desktop): expose heartbeat controls and status card 2026-02-06 16:42:21 +08:00
Jiang Bohan
8c87c50281 feat(hub): wire heartbeat controls into hub and cron wake mode 2026-02-06 16:42:14 +08:00
Jiang Bohan
ffa5355a95 feat(heartbeat): add heartbeat core runner and profile integration 2026-02-06 16:41:56 +08:00
Naiyuan Qing
287e6d5c4f fix(channels): catch telegram bot polling errors gracefully
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>
2026-02-06 16:07:27 +08:00
Naiyuan Qing
112ae6cac9 refactor(channels): read config from credentials.json5 instead of separate file
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>
2026-02-06 16:00:44 +08:00
Jiang Bohan
24df8b02e7 fix(agent): reload credentials dynamically 2026-02-06 15:48:29 +08:00
Naiyuan Qing
9922355d0c feat(hub): integrate ChannelManager into Hub lifecycle
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>
2026-02-06 15:47:47 +08:00
Naiyuan Qing
971d68b605 feat(channels): add ChannelManager and Telegram plugin
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>
2026-02-06 15:47:41 +08:00
Naiyuan Qing
5d63727a04 feat(channels): add channel plugin system with types, registry, and config
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>
2026-02-06 15:47:36 +08:00
Bohan Jiang
91aa433f34 Merge pull request #100 from multica-ai/Bohan-J/cron-job-tool
feat(cron): add cron job scheduling system with Desktop UI
2026-02-06 15:46:41 +08:00
Jiang Bohan
4983debf0c fix(desktop): add cron API type to ElectronAPI interface
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 15:43:55 +08:00
Jiang Bohan
b5eca456ab fix(cron): clarify agent-turn can use all tools in description
The model was confused about payload capabilities. Explicitly state
that agent-turn spawns an isolated agent with ALL tools (exec, write,
web_fetch, etc.) and add usage guidance for choosing between
system-event and agent-turn.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 15:31:29 +08:00
Jiang Bohan
2129feaf3a fix(cron): replace require("fs") with ESM renameSync import
The bundled ESM environment does not support require(). Use the
already-imported fs functions instead.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 15:21:12 +08:00
Jiang Bohan
a8dd9f2bbb feat(desktop): add Cron Jobs management page
- Add "Cron" tab to navigation bar with Time04Icon
- Add /crons route with CronsPage component
- Add cron IPC handlers (list, toggle, remove) in electron/ipc/cron.ts
- Expose cron API in preload.ts for renderer process
- Add useCronJobs hook for fetching and managing jobs
- Add CronJobList component with status badges, toggle switches,
  delete buttons, relative time display, and empty state

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 15:16:33 +08:00
Jiang Bohan
9bd18472b8 refactor(cron): align tool schema with OpenClaw patterns
- Replace Type.Union(Type.Literal(...)) with flat stringEnum helper
  to avoid anyOf in JSON schema (better LLM provider compatibility)
- Rewrite description to structured ACTIONS/SCHEDULE/PAYLOAD/CONSTRAINTS
  format without markdown headers or code blocks
- Add CRITICAL CONSTRAINTS section for sessionTarget+payload rules

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 15:08:15 +08:00
Jiang Bohan
ab85a01431 fix(cron): improve action parameter description for better model understanding
- Add explicit list of valid actions in parameter description
- Add IMPORTANT note at start of tool description

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-06 14:59:35 +08:00
Jiang Bohan
ea7a2c837b feat(desktop): add cron tool to Tools page UI
- Add 'group:cron' to TOOL_GROUPS in IPC handler and agent tools
- Add cron tool description and group name to use-tools hook
- Add Time04Icon for cron group in tool-list component
- Add subagent group icon (UserMultipleIcon) for completeness

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-06 14:47:54 +08:00