Commit graph

261 commits

Author SHA1 Message Date
Naiyuan Qing
3c303df8f1 Merge branch 'main' into exec-approvals 2026-02-05 11:06:52 +08:00
Naiyuan Qing
037908cf8d feat(connection): add device verification status feedback for collaborators
Add a "verifying" connection state between "connected" and "registered"
so collaborators see clear feedback while waiting for the device owner
to approve their connection on Desktop.

Changes across the stack:
- Hub: verify RPC returns isNewDevice flag to distinguish new vs whitelisted
- SDK: emit "verifying" state before verify RPC, pass isNewDevice through
- Store: capture isNewDevice via onVerified, capture rejection via onError
- UI: ConnectionStatus (waiting), RejectedStatus (declined), and
  verify success overlay (approved) replace the stuck scanner screen

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 10:44:15 +08:00
Jiang Bohan
cdc64f9c83 feat(profile): enforce file-based memory with stronger guidance
Update workspace.md template to prevent agents from claiming to
"remember" things without actually editing files. The new guidance:

- Uses "No Mental Notes!" as a strong warning
- Lists specific trigger phrases (记住, Remember, I prefer, etc.)
- Maps each trigger to the appropriate file to edit
- Explicitly forbids saying "I'll remember" without file edits

This addresses the issue where agents would acknowledge user
preferences verbally but not persist them to profile files.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 03:32:53 +08:00
Jiang Bohan
a3e639f8f5 refactor(cli): make desktop app the default dev target
- Change `multica dev` default from gateway+console+web to desktop app
- Remove console from dev command options (use embedded Hub in desktop)
- Update package.json scripts to reflect new defaults
- Update README.md and CLAUDE.md architecture documentation

The desktop app has an embedded Hub, so no separate console/gateway is
needed for local development. Gateway is now optional, only needed for
remote client access.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 03:14:44 +08:00
Jiang Bohan
087d1a8653 refactor(tools): remove tool profile layer from policy system
Simplify 4-layer policy to 3-layer:
- Layer 1: Global allow/deny (user config)
- Layer 2: Provider-specific rules
- Layer 3: Subagent restrictions

Removed:
- ToolProfileId type (minimal/coding/web/full)
- TOOL_PROFILES constant
- getProfilePolicy function
- profile field from ToolsConfig

Users can achieve the same effect using allow/deny with group:* syntax.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 02:58:15 +08:00
Jiang Bohan
9b16001e0e feat(subagent): pass tools to subagent system prompt
Resolve tools before building subagent system prompt so the
"## Tooling" section is included, matching OpenClaw's pattern.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 02:58:08 +08:00
Jiang Bohan
5cdc6974f7 refactor(profile): implement progressive disclosure for profile loading
- Only inject workspace.md into system prompt (not soul, user, memory)
- Add profile directory path to workspace section for on-demand file access
- Agent now reads soul.md, user.md, memory.md on first session using tools
- Reduces system prompt size and improves token efficiency
- Aligns with workspace.md template instructions ("Read soul.md first")

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 02:41:29 +08:00
Jiang Bohan
d7eb0da49b feat(agent): add provider switching and OAuth credential support
- Add getProviderInfo() and setProvider() methods to Agent class
- Expose provider methods via AsyncAgent
- Add setLlmProviderOAuthToken() for storing OAuth credentials
- Extend ProviderConfig type with OAuth fields (oauthToken, oauthRefreshToken, oauthExpiresAt)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 18:25:06 +08:00
yushen
abc48e5152 fix(hub): honor exec approval timeout fallback 2026-02-04 17:23:11 +08:00
yushen
b85138d32d Merge remote-tracking branch 'origin/main' into exec-approvals 2026-02-04 17:22:02 +08:00
yushen
8406a1f5d3 fix(hub): use sessionId instead of profileId for exec approval routing
The createExecApprovalCallback was using profileId as the agentId for
approval requests, but agentSenders map is keyed by agent.sessionId.
This caused sendToClient lookups to fail, silently denying all Hub-mode
approvals. Now generates sessionId upfront and passes it separately
from profileId to the callback.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 17:12:21 +08:00
yushen
d742e668d7 feat(hub): integrate exec approval manager with Hub and Gateway
- ExecApprovalManager: tracks pending approvals, sends to clients via
  Gateway, resolves on RPC response, auto-denies on timeout (fail-closed)
- RPC handler: resolveExecApproval for client decision delivery
- Hub integration: creates approval callback per agent, injects into
  AsyncAgent, registers RPC handler, cancels pending on agent close
- Reads/writes exec approval config and allowlist from agent profile
- Test coverage for manager: request/resolve, timeout, cancel, errors

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 17:07:16 +08:00
yushen
89089ef866 feat(agent): wire exec approval callback into tool execution pipeline
- Add optional onApprovalNeeded callback to exec tool (backward compatible)
- Thread callback through CreateToolsOptions → AgentOptions → resolveTools
- Add ExecApprovalConfig to ProfileConfig for per-profile configuration
- Create CLI terminal approval callback (readline-based) for non-Hub mode
- Export all exec approval types and functions from tools index

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 17:07:07 +08:00
yushen
e67682cfa0 feat(agent): add exec approval type definitions and safety evaluation engine
Introduces the core exec approval system with:
- Type definitions: ExecSecurity, ExecAsk, ApprovalDecision, ExecApprovalConfig
- Command safety evaluation: shell syntax analysis, safe binary detection,
  dangerous pattern detection, allowlist matching
- Persistent allowlist management: glob pattern matching, dedup, usage tracking
- Comprehensive test coverage (76 tests)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 17:06:58 +08:00
Jiang Bohan
a098a78942 fix(agent): add getMessages method and fix TypeScript errors
- Add getMessages() to Agent and AsyncAgent for retrieving session history
- Fix type annotations in hub.ts for AgentMessage handling
- Remove duplicate type export in preload.ts

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 16:51:07 +08:00
Jiang Bohan
4086fa6985 feat(agent): add subscribe method for multiple event consumers
Add AsyncAgent.subscribe() that allows multiple subscribers to receive
the same agent events, enabling local IPC chat to coexist with other
event consumers.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 16:46:28 +08:00
LinYushen
c70dd338c2
Merge pull request #84 from multica-ai/reasoning-mode-support
feat(agent): add reasoning mode for thinking content display
2026-02-04 16:15:20 +08:00
yushen
f649792118 fix(agent): allow output reinit 2026-02-04 16:09:36 +08:00
yushen
8fe2b5f010 fix(agent): resolve reasoningMode from profile config and session meta
- Read reasoningMode from profile config and storedMeta when not
  explicitly set via options (matching thinkingLevel pattern)
- Skip extractThinking() call when reasoningMode is "off"
- Clean up redundant ?? undefined casts in CLI entry points

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 16:00:53 +08:00
yushen
f585882a06 fix(agent): keep skills prompt without profile 2026-02-04 15:57:06 +08:00
yushen
953a29672a feat(agent): implement reasoning mode in engine and CLI
Wire reasoningMode through Agent runner, CLI output, and all CLI
entry points (run, interactive, non-interactive). In stream mode,
thinking content is printed to stderr in real-time. In on mode,
thinking is shown after message completion. Default is stream.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 15:50:47 +08:00
yushen
77d5702f80 feat(agent): add reasoning mode types and thinking extraction
Add ReasoningMode type (off/on/stream) to AgentOptions and related
config types. Add extractThinking() for extracting thinking content
blocks from LLM responses, mirroring the existing extractText() pattern.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 15:50:35 +08:00
yushen
f733f0bcc3 fix(agent): fix system prompt reload and tool casing issues
- reloadSystemPrompt() now updates both agent and session prompt
- reloadSystemPrompt() uses buildSkillsPrompt() consistently (not buildModelSkillsPrompt)
- Extract rebuildSystemPrompt() to eliminate duplicated builder logic
- Preserve original tool name casing in tooling summary (matching OpenClaw)
- Fix report line count to use actual newline count

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 15:46:18 +08:00
yushen
8333615fb4 refactor(agent): integrate system prompt builder into profile, runner, and subagent
ProfileManager.buildSystemPrompt() now delegates to the structured builder.
Runner assembles prompt after tool resolution with safety, tooling summary,
and runtime info. Subagent prompts use minimal mode with safety constitution.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 15:41:22 +08:00
yushen
5a06bed549 feat(agent): add system prompt engineering module
Structured, mode-aware system prompt builder inspired by OpenClaw.
Supports three modes (full/minimal/none), safety constitution,
conditional tool sections, runtime info, and prompt telemetry.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 15:41:16 +08:00
Bohan Jiang
5760b86e80
Merge pull request #79 from multica-ai/feat/agent-style-setting
feat(desktop): add agent communication style setting
2026-02-04 14:48:29 +08:00
Jiang Bohan
4df39448be feat(agent): add communication style setting to profile
- Add AgentStyle type with 6 preset options (professional, friendly, etc.)
- Add getStyle/setStyle methods to ProfileManager
- Update soul.md template to include style section
- Add reloadSystemPrompt support for style changes

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 14:42:23 +08:00
yushen
f63a67e341 refactor(hub): improve device whitelist persistence format
- Rename storage path from ~/.super-multica/devices/ to
  ~/.super-multica/client-devices/ for clarity
- Change JSON format from bare array to { version, devices[] }
  dict for future extensibility
- Auto-migrate legacy array format on load

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 14:16:59 +08:00
yushen
c3ded8da41 merge: resolve conflicts with origin/main
Merge remote main branch, keeping both device verification (ws-auth-handshake)
and agent settings/profile features from main.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 14:04:47 +08:00
yushen
c604085065 fix(desktop): address review issues in device verification flow
- Add 60s timeout to pending device confirms to prevent Promise leaks
  when client disconnects before user responds
- Add offDeviceConfirmRequest to preload and clean up IPC listener on
  component unmount to prevent duplicate listener accumulation
- Extract duplicated parseUserAgent into shared lib/parse-user-agent.ts
- Clean up expired tokens in DeviceStore.registerToken to prevent
  memory accumulation from unscanned QR codes

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 13:54:09 +08:00
yushen
ef9b5af221 fix(hub): send error response to unverified device instead of silent drop
When an unverified device sends a non-RPC message, reply with an
"error" action containing UNAUTHORIZED code so the client knows
verification is required.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 13:46:29 +08:00
yushen
c581183839 feat(hub): store device metadata in whitelist and pass to confirm handler
Extend DeviceEntry with optional DeviceMeta field. Verify handler
extracts meta from params and passes it through to onConfirmDevice
callback and deviceStore.allowDevice for persistence.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 13:43:48 +08:00
yushen
b2c0711676 feat(hub): add device verification with token + whitelist + user confirmation
Add DeviceStore for managing one-time tokens and persistent device
whitelist. Create async verify RPC handler that validates tokens and
awaits Desktop user confirmation for first-time connections. Whitelisted
devices (reconnections) pass through instantly. Add message guard to
reject unverified device traffic.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 13:27:29 +08:00
Jiang Bohan
fa03ae6e62 feat(agent): add soul.md support for agent identity
- Add getSoulContent/updateSoulContent to ProfileManager
- Create soul.md with agent name when updating profile name
- Add reloadSystemPrompt() method to Agent and AsyncAgent
- Include soul.md content in system prompt build

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 13:26:40 +08:00
Jiang Bohan
a80c858ce5 feat(agent): add profile name and user content management
Add methods to ProfileManager, Agent, and AsyncAgent for:
- Getting/setting agent display name (stored in config.json)
- Getting/setting user.md content

This enables the desktop app to manage agent settings.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 13:26:40 +08:00
Jiang Bohan
f5a0d986a2 fix(desktop): resolve TypeScript build errors
- Disable noUnusedLocals/noUnusedParameters in desktop tsconfig
  (external src/ files have unused imports that fail strict checking)
- Add TSchema constraint to wrapTool generic to satisfy AgentTool type

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 19:26:25 +08:00
Jiang Bohan
4112d4511e fix(agent): resolve TypeScript errors with exactOptionalPropertyTypes
- Fix originalToolsConfig assignment to handle undefined properly
- Fix devNull type cast for WritableStream compatibility

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 18:58:45 +08:00
Jiang Bohan
dafbf856ac merge: resolve conflicts with main branch
- Merge auth-profiles feature from main into runner.ts
- Merge closeCallbacks feature from main into async-agent.ts
- Regenerate pnpm-lock.yaml with new dependencies

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 18:57:05 +08:00
yushen
a065d5f64c fix(auth-profiles): add jittered cooldowns 2026-02-03 18:27:21 +08:00
Jiang Bohan
864d9166fc feat(hub): support profileId in createAgent
- Add profileId option to createAgent() method
- Default to "default" profile for all agents
- Ensures every agent has an associated profile for memory and config

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 18:25:48 +08:00
Jiang Bohan
6f6a4f82e4 feat(agent): add tools and skills management methods
- Add setToolStatus() to persist tool enable/disable to profile config
- Add getActiveTools() and reloadTools() methods
- Add getSkillsWithStatus(), getEligibleSkills(), reloadSkills() methods
- Add updateToolsConfig() and setToolEnabled() to ProfileManager
- Ensure profile directory is created on Agent initialization
- Fix reloadTools() to re-read profile config for latest changes

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 18:25:43 +08:00
yushen
9ed4cdf2b0 fix(agent): handle auth profile failures and provider mismatch 2026-02-03 18:23:18 +08:00
yushen
617ddfbfea refactor(auth-profiles): replace proper-lockfile with custom file lock
Unify locking strategy across the project by using a custom synchronous
file lock (exclusive-create based, with PID stale detection) instead of
the proper-lockfile dependency, matching the pattern in session-write-lock.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 18:05:00 +08:00
yushen
4b10420324 Merge remote-tracking branch 'origin/main' into auth-profile-rotation
# Conflicts:
#	pnpm-lock.yaml
#	src/agent/runner.ts
2026-02-03 17:58:50 +08:00
yushen
0fee16f735 test(session): reset lock mock 2026-02-03 17:49:26 +08:00
yushen
f2ca86aa1f fix(session): harden write lock and repair 2026-02-03 17:47:41 +08:00
yushen
f1334349ca Merge remote-tracking branch 'origin/main' into session-writelock-repair 2026-02-03 17:45:56 +08:00
yushen
e8815dbb97 fix(agent): loop-based rotation, timeout rotatable, error classification tests
- Replace single-retry with while loop that exhausts all candidate profiles
- Add "format" detection to classifyError (400, malformed, bad request, schema)
- Make timeout errors rotatable (some providers hang on rate limit)
- Export classifyError and isRotatableError for testing
- Add error-classification.test.ts with coverage for all failure reasons

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 17:26:16 +08:00
yushen
a8c5042554 fix(auth-profiles): add file locking, type priority sort, credential filtering
- Add proper-lockfile for concurrent-safe store updates with fallback
- Add "format" to AuthProfileFailureReason
- Two-level round-robin sort: credential type priority (OAuth > API key), then lastUsed
- Filter out profiles with missing/invalid credentials from candidates
- Add preferredProfile option to resolveAuthProfileOrder
- Export coerceStore and ensureAuthStoreFile for testing
- Add store.test.ts with coerceStore, load/save round-trip, corruption handling
- Update order.test.ts mocks for resolver and registry dependencies

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 17:26:09 +08:00
yushen
30f23459ce fix(agent): align subagent lifecycle with openclaw 2026-02-03 17:22:41 +08:00