Commit graph

243 commits

Author SHA1 Message Date
Jiang Bohan
d5090441da fix(agent): use user message content type for displayContent 2026-02-09 16:37:33 +08:00
Jiang Bohan
ff0694175e Merge branch 'main' of https://github.com/multica-ai/super-multica 2026-02-09 16:25:30 +08:00
Bohan Jiang
a12907df86
Merge pull request #109 from multica-ai/Bohan-J/fix-chat-error-catch
fix(agent): only emit agent_error for LLM provider 401
2026-02-09 16:07:13 +08:00
Jiang Bohan
a8e7a803c9 fix(agent): separate display content from agent user turns 2026-02-09 15:54:10 +08:00
Jiang Bohan
7294e76929 fix(agent): only emit agent_error for auth issues, not runtime 400 errors
Previously all agent errors (including 400 invalid_request_error) were
emitted as agent_error events, triggering the UI error banner and
interrupting the chat flow. Now only auth-related errors (401, no API key)
emit agent_error so the "Configure" banner appears. Runtime errors like
400 are still shown as chat messages but don't block the agent.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 15:53:41 +08:00
Jiang Bohan
2fa8c383fb fix(agent): save original provider ID instead of alias in session meta
setProvider() was saving the alias-resolved provider (e.g. "anthropic"
instead of "claude-code") to session metadata. On restart, this caused
the wrong provider to be selected. Now saves the original providerId
so the exact user selection is preserved.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 15:45:11 +08:00
Jiang Bohan
15f6604a16 fix(agent): persist provider selection across restarts
Move session metadata loading before provider resolution so that
the stored provider from a previous setProvider() call is used
in the fallback chain (options > session meta > credentials > default)
instead of always falling back to "kimi-coding".

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 15:41:56 +08:00
Jiang Bohan
d6993000ca Merge branch 'main' of https://github.com/multica-ai/super-multica
# Conflicts:
#	apps/desktop/electron/electron-env.d.ts
2026-02-09 14:34:48 +08:00
Bohan Jiang
94d6e15117
Merge pull request #101 from multica-ai/fix/credentials-reload
fix(agent): reload credentials dynamically
2026-02-09 14:33:40 +08:00
Jiang Bohan
5716932903 fix(agent): resolve merge conflict in runner.ts for credentials reload
Merge main's run mutex + soft error return with branch's refreshAuthState(),
keeping getApiKey defensive throw as defense-in-depth.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 14:30:57 +08:00
Naiyuan Qing
0895d42d3b Merge remote-tracking branch 'origin/main' into feat/telegram-channel
# Conflicts:
#	apps/desktop/src/hooks/use-local-chat.ts
#	packages/sdk/src/actions/stream.ts
#	packages/ui/src/components/chat-view.tsx
#	src/agent/async-agent.ts
#	src/agent/events.ts
2026-02-09 14:28:06 +08:00
Jiang Bohan
9d6468acca Merge branch 'Bohan-J/rm-comm-style' into main 2026-02-09 14:25:44 +08:00
Jiang Bohan
22e225c6a8 refactor(profile): remove Communication Style UI and programmatic API
Style is now solely managed by the agent editing soul.md directly,
removing the need for UI controls, IPC handlers, and typed constants.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 14:25:38 +08:00
Jiang Bohan
667f3e533e fix(agent): improve time awareness with timestamped turns 2026-02-09 14:05:22 +08:00
Bohan Jiang
b7085b2bf5
Merge pull request #107 from multica-ai/fix/new-user-onboarding
fix(desktop): new user onboarding — show errors and configure dialog in Chat
2026-02-09 13:54:48 +08:00
Jiang Bohan
8d32a06b5c fix(agent): validate API key before calling PiAgentCore.prompt()
getApiKey errors thrown inside PiAgentCore's internal async context
result in UnhandledPromiseRejection instead of propagating to the
caller. Return a graceful error early so AsyncAgent can emit it
through the subscriber mechanism to the UI.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 13:51:45 +08:00
Naiyuan Qing
23905daaa1 Merge remote-tracking branch 'origin/main' into feat/telegram-channel
# Conflicts:
#	apps/desktop/electron/electron-env.d.ts
#	apps/desktop/electron/ipc/index.ts
#	apps/desktop/electron/preload.ts
#	apps/desktop/src/App.tsx
#	apps/desktop/src/pages/layout.tsx
#	src/agent/async-agent.ts
#	src/agent/runner.ts
#	src/hub/hub.ts
2026-02-09 13:44:08 +08:00
Naiyuan Qing
0542c82fe6 feat(channels): add credential write and per-account lifecycle control
Add setChannelAccountConfig/removeChannelAccountConfig to CredentialManager
for persisting channel tokens. Make ChannelManager.startAccount public and
add stopAccount for individual account lifecycle control via IPC.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 12:50:15 +08:00
Naiyuan Qing
614d2cfd88 fix(channels): address code review issues
Critical:
- describe-video: add mkdir for MEDIA_CACHE_DIR before ffmpeg write
- telegram: check bot ID (not is_bot) for reply-to detection in groups

Important:
- telegram: check @mention in caption for media messages in groups
- hub: add .catch() to channelManager.startAll()
- describe-image: add 20MB file size check to prevent OOM
- async-agent: remove dead writeWithImages, refactor with enqueue()
- manager: lazy agent subscription via ensureSubscribed() to handle
  late agent availability and agent replacement

Suggestions:
- telegram-format: escape quotes in link URLs to prevent HTML breakout
- transcribe: catch API errors and return null (match local fallback)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 11:22:17 +08:00
Naiyuan Qing
23da5a35ff feat(channels): route media messages through agent
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>
2026-02-09 09:44:39 +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
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
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
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
yushen
7726079648 fix(subagent): recover delete cleanup after crash 2026-02-06 17:31:21 +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
Jiang Bohan
ffa5355a95 feat(heartbeat): add heartbeat core runner and profile integration 2026-02-06 16:41:56 +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
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
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
Jiang Bohan
321b48a1cf feat(agent): register cron tool in agent toolset
Add createCronTool to the agent's default tools list so agents
can use the cron tool to manage scheduled tasks.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-06 14:47:54 +08:00
Jiang Bohan
f15a28e14a feat(cli): add multica cron commands
Adds CLI support for managing scheduled tasks:
- multica cron status: Show service status
- multica cron list: List all scheduled jobs
- multica cron add: Create new jobs with --at/--every/--cron
- multica cron run: Execute jobs immediately
- multica cron enable/disable: Toggle job status
- multica cron remove: Delete jobs
- multica cron logs: View run history

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-06 14:47:31 +08:00
Jiang Bohan
9d0cc6fdf6 feat(tools): add cron tool for agent job management
Adds a cron tool that allows agents to create, manage,
and execute scheduled tasks. Supports:
- status: Get service status
- list: List all jobs with optional filters
- add: Create one-shot, interval, or cron jobs
- update: Modify existing jobs
- remove: Delete jobs
- run: Execute jobs immediately
- logs: View run history

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-06 14:47:31 +08:00
yushen
ec6dbff61c Merge remote-tracking branch 'origin/main' into copilothub-web-search 2026-02-06 11:43:40 +08:00