Prepend [ChannelName · private/group] prefix to debounced messages so
the LLM knows the message source. Add sendFile() for outbound media
routing and listChannelInfos() for system prompt channel awareness.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New send_file tool with TypeBox schema, auto-detect media type from
file extension, and file validation. Wired through AgentOptions and
resolveTools with conditional registration when callback is provided.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add OutboundMedia interface and OutboundMediaType to the channel type
system. Implement sendMedia in the Telegram plugin using grammy's
InputFile API with HTML caption formatting and plain-text fallback.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Guide the LLM to evaluate snippet quality after web_search and
follow up with web_fetch on the most relevant URLs when deeper
content is needed for accurate answers.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Hidden directory ~/.super-multica is not user-friendly for a working
directory. Move default workspace base to ~/Documents/Multica so
users can easily find agent-created files in Finder.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add MessageSource type to track where user messages originate (local, gateway, channel)
- Broadcast inbound messages from all channels to local Desktop UI via Hub.onInboundMessage()
- Persist source field in JSONL session storage so it survives page refresh
- Display source icon (Monitor/Smartphone/Send) with tooltip for non-local user messages
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Each agent profile now gets a dedicated workspace directory
(~/.super-multica/workspace/{profileId}) used as the default CWD
for tool operations. Supports override via MULTICA_WORKSPACE_DIR
env var or config.json workspaceDir field. The workspace path is
injected into system prompt and runtime info.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
A subagent that times out loses all its work, so a generous default
reduces wasted compute. Update the constant, tool description, system
prompt guidelines, and documentation to reflect the new 1800s default.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When writeInternal fails with a transient error (e.g. undici
"terminated", connection reset, 502/503), wait 5 seconds and retry
once. This prevents continuation tasks from silently failing when
the LLM streaming connection is interrupted mid-generation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
sessions_spawn now accepts groupId and next parameters. First spawn with
next auto-creates a group; subsequent spawns join via groupId. sessions_list
groups runs by groupId with completion progress display.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When all runs in a group complete, deliver combined findings plus the
`next` continuation prompt to the parent agent via writeInternal. The
parent can then act on the collected data (summarize, write files, etc).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add SubagentGroup for "collect all, then act" workflows where multiple
subagents complete before a continuation task runs. Groups are persisted
alongside run records and support a `next` continuation prompt.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add CompactionItem component that renders a subtle inline notification
in the chat stream when the agent compacts its context window. Extends
Message type with "system" role and handles compaction_end events in
useChat's handleStream.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Rename channels.tsx to clients.tsx
- Remove standalone skills.tsx and tools.tsx pages
- Add agent/ directory for agent-related pages
- Update layout and navigation structure
- Add tabs component to ui package
- Update fonts and global styles
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Root cause: compaction only ran after successful assistant response,
never before calling the LLM API. Internal runs skipped it entirely,
and the fire-and-forget void swallowed errors with race conditions.
Layer 1 - Pre-flight compaction in transformContext:
Runs before EVERY LLM call (including internal runs). Prunes tool
results and drops oldest messages when utilization exceeds 80%.
Pure in-memory, no disk writes.
Layer 2 - Fix post-hoc compaction:
Store compaction promise instead of voiding it, await at _run() start
to prevent race conditions. Emit compaction_start before the actual
compaction. Remove useless catch-rethrow block.
Layer 3 - Context overflow recovery:
Catch context overflow 400 errors → auto-compact → retry (up to 2
attempts). Runs before classifyError/auth rotation so overflow errors
are handled by compaction, not profile switching.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- ESTIMATION_SAFETY_MARGIN: 1.2 → 1.5 (50% buffer covers CJK text)
- estimateSystemPromptTokens: /3 → /2 (conservative for mixed content)
This makes the 80% compaction trigger fire earlier, reducing the gap
between estimated and actual token counts that caused overflow errors.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Detects context overflow 400 errors from various LLM providers
(prompt too long, context length exceeded, request too large, etc.)
for use in auto-compaction recovery.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add stop button to interrupt agent generation mid-stream. The send button
toggles to a stop icon during loading. Abort propagates from UI through
IPC to the Agent layer (PiAgentCore.abort()), preserving all partial
content in the agent's context so users can follow up immediately.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add AppState module in core for managing app state persistence
- Add app-state IPC handlers for reading/writing onboarding state
- Hydrate onboarding state from file system on app startup
- Prevent flash by showing blank screen during hydration
- Update onboarding store to sync with file system
- Improve MulticaIcon with enhanced animation states
- Minor UI fixes in chat and device list components
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Replace @hugeicons/react with lucide-react across all packages
- Update all components to use Lucide icon components
- Add silent option to store refresh methods to control toast display
- Simplify icon usage with direct component imports
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Scroll cursor into view on content changes (e.g., Shift+Enter)
- Add scroll threshold and margin for better edge handling
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add remark-math + rehype-katex plugins to render inline ($...$) and
display ($$...$$) math expressions. Includes dark mode CSS overrides,
streaming block splitting for math fences, and math range exclusion
in link preprocessing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Web tools are always available, so the conditional branching was
unnecessary. Data section now always includes the dynamic evidence
decision guidance.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The finance-decisioner used hardcoded keyword matching and arbitrary
scoring weights to decide evidence plans — the LLM reading the
improved SKILL.md already makes this decision more intelligently.
Removes: finance-decisioner.ts, its tests, runner.ts integration
(applyFinanceResearchGuidance, saveFinanceDecisionMeta,
rebuildSystemPromptWithExtra shim), and researchDecision from
session meta.
Keeps: SKILL.md improvements, sections.ts dynamic data/web guidance.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The heartbeat runner used agent.write() (normal write), which persisted
both the heartbeat prompt and HEARTBEAT_OK response as regular messages
visible in the UI chat history.
Switch to runInternalForResult() — a new AsyncAgent method that runs
via runInternal() (messages marked internal: true, rolled back from
in-memory state). This hides both the heartbeat prompt and response
from the UI entirely, while still persisting to JSONL for diagnostics.
The previous commit's event-stream heartbeat ACK filter remains as a
defense-in-depth layer for edge cases.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The heartbeat runner uses agent.write() (normal write), so heartbeat
ACK responses like "HEARTBEAT_OK" were not suppressed by the internal
run filter and leaked into the desktop UI chat. The Gateway path was
already fixed (Hub has delayed-start + isHeartbeatAckEvent filtering),
but the local Desktop path through AsyncAgent had no such filtering.
Add createFilteredHandler() to AsyncAgent that buffers message_start
for assistant messages and checks subsequent events with
isHeartbeatAckEvent(). Pure heartbeat ACKs are suppressed end-to-end;
all other messages are forwarded normally.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Changed forwardAssistant from false to true in sendAnnounceDirect() so
the assistant's summary response is streamed to the desktop UI in
real-time. The announcement prompt stays internal (hidden from UI), but
the user now sees the completion notification.
Previously, persistAssistantSummary saved the response to JSONL but
never emitted events to the UI subscriber, leaving users with no
visible feedback after subagent tasks completed.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
setProvider() updated toolsOptions.provider but didn't reload tool
instances. The sessions_spawn tool captured the old provider in its
closure at creation time, causing subagents to inherit a stale provider.
Now calls resolveTools() + setTools() after updating toolsOptions so
sessions_spawn gets a fresh closure with the correct provider.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace ring-[3px] with ring-3 in button and input
- Use data-horizontal/data-vertical in separator
- Fix sidebar data attributes and RTL support
- Simplify tooltip provider nesting
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Separate entrance animation from hover animation
- Use state to track entrance completion
- Hover spin only activates after entrance is done
- Shorten entrance animation to 0.6s
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add radio button style indicators for provider selection
- Add HoverCard component for provider setup help
- Add Link component for external URLs
- Add Popover component (dependency for HoverCard)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>