* feat: add Supermarket integration (MCP & Skill marketplace)
Backend:
- Add [supermarket] config section with base_url (default: supermarket.memoh.ai)
- Add SupermarketHandler with proxy endpoints for MCPs, Skills, and Tags
- Add install endpoints: POST /bots/:id/supermarket/install-mcp (creates MCP
connection with env vars) and install-skill (downloads tar.gz, extracts to
container via gRPC)
- Register handler in FX wiring, generate Swagger docs and TypeScript SDK
Frontend:
- Add /settings/supermarket route with Store icon in sidebar
- Create supermarket page with search, tag filtering, MCP and Skill sections
- Add MCP/Skill card components with tag badges and install buttons
- Add install dialogs: MCP (bot selector + env var form), Skill (bot selector)
- Add i18n entries for en.json and zh.json
* fix: improve supermarket install UX
- Create BotSelect component with avatar + name using UI Select
- Replace NativeSelect in install dialogs and usage page with BotSelect
- Change MCP install flow: navigate to bot detail MCP tab with pre-filled
draft instead of direct install, letting users review before saving
- Move Supermarket sidebar entry between Browser and Usage
* web: remove supermarket page top tag selector bar
Drop the horizontal tag chips and getSupermarketTags fetch; keep
search and tag filter via card tag clicks with clearable badge.
* web: add homepage link to supermarket MCP and Skill cards
Show an external-link icon next to the card title when homepage is
available, opening in a new tab on click.
The fallback provider introduced in 5aeb2fd3 wrapped containerfs but did
not implement storage.ContainerFileOpener, causing IngestContainerFile to
fail with "provider does not support container file reading". This broke
outbound file attachments on all IM channels (Telegram, Discord, etc.)
because container paths like /data/xxx.xlsx were passed as-is to the
platform API instead of being ingested into the media store first.
- Add localfs storage provider as fallback when containerfs is unreachable
- Wrap media service with fallback provider in both entry points
- Fix gallery lightbox src matching by comparing pathnames only
- Add SupportsToolCall to RunConfig; only inject tools into SDK when set
- Update twilight-ai to 497ad09 which adds SSE scanner 10MB buffer
(fixes token-too-long on large image payloads) and parses the images
array from OpenAI-compatible chat completions into StreamFilePart
Large directories like node_modules/.venv could return thousands of entries,
wasting tokens and causing timeouts. Add offset/limit pagination to ListDir
RPC and collapse heavy subdirectories (>50 items) into summaries in recursive
mode. Collapsing runs at the bridge layer before pagination so the page window
reflects the collapsed view.
When messages like [assistant(tool_calls), tool, assistant(text)] are
merged into a single ChatMessage by convertMessagesToChats, the merged
message uses the first assistant's ID. The SSE /messages/events backlog
(which uses >= for the since filter) could re-deliver the final assistant
message, and hasMessageWithId failed to recognize it because the merged
ID was different. This caused the last assistant message to appear twice
after a page refresh.
Track all original server message IDs in a Set (knownServerMessageIds)
so that hasMessageWithId can catch messages whose IDs were absorbed
during merging.
Use stream-monaco's useMonaco composable instead of raw monaco-editor
to share the same theme registration system with markstream-vue.
Pass isDark prop to MarkdownRender to follow app dark mode.
Three independent bugs fixed:
1. IM channels were sending raw <attachments>/<reactions>/<speech> tag blocks
alongside file attachments. Now ExtractAssistantOutputs strips these tags
before building the outbound channel message.
2. WebUI rendered these tags as markdown after page refresh. Now
extractMessageText strips agent tags for non-user messages.
3. WebUI lost attachment blocks after refresh because convertMessagesToChats
did not call buildAssetBlocks when merging assistant messages into a
pending tool-call group. Also made LinkOutboundAssets session-aware so
assets are linked to the correct assistant message.
* Enhance Matrix bot setup documentation
Added instructions for obtaining an access token using the Matrix Client Login API and clarified the importance of keeping it secret. Updated details on bot capabilities and linked to the roadmap for future features.
* Add warning about access token security
Added important note about keeping the access token secret.
WiX MSI only supports numeric-only versions (X.Y.Z). When the tag
contains a pre-release identifier (e.g. 0.6.0-beta.5), override the
MSI version via `bundle.windows.wix.version` with the stripped numeric
portion while keeping the full semver for other bundle formats.
The SDK persists tool results as ToolResultPart with a "result" JSON field,
but extractAllToolResults was only reading "output", causing exec tool
stdout/stderr/exit_code to be lost when loading chat history.
Replace the static Globe icon with dynamic type-specific icons
(MessageSquare, HeartPulse, Clock, GitBranch) that match the
session item icons, updating both icon and color on filter change.
The child-selector border styles (*:border-b *:border-x etc.) on
CollapsibleContent caused unexpected white outlines around thinking
blocks and tool-call detail panels in chat messages.
Allow users to select a different model and reasoning effort level
directly from the chat input toolbar, overriding the bot defaults
on a per-message basis. The backend accepts optional model_id and
reasoning_effort parameters via both WebSocket and HTTP APIs, with
request-level values taking priority over bot/session settings.
- Backend: extend wsClientMessage and LocalChannelMessageRequest with
model_id/reasoning_effort fields; add ReasoningEffort to ChatRequest;
update resolver to prioritize request-level reasoning effort
- Frontend: add ModelOptions and ReasoningEffortSelect shared components;
refactor model-select to reuse ModelOptions; add model/reasoning
selectors to chat input toolbar; initialize from bot settings
- Regenerate swagger spec and TypeScript SDK
Container terminals were echoing raw ANSI escape sequences (^[[A, ^[[B,
etc.) instead of handling arrow keys because /bin/sh (dash/ash) lacks
readline support. Two changes fix this:
1. Bridge execPTY now directly exec's bare paths (e.g. /bin/bash) instead
of always wrapping through "/bin/sh -c", preserving readline behavior.
2. Terminal handler detects bash/zsh in the container and prefers them
over /bin/sh for interactive PTY sessions.
Replace fixed-width session sidebar with a draggable resize handle on
its right edge (180–480px, persisted to localStorage). Convert the file
manager from a Sheet overlay to an embedded right-side panel with a
left-edge resize handle (320–800px, also persisted).
Allow users to configure what percentage of older messages to compact,
keeping the most recent portion intact. Default ratio is 80%, meaning
the oldest 80% of uncompacted messages are summarized while the newest
20% remain as-is for full-fidelity context.
Tauri desktop artifacts were always named with hardcoded version 0.1.0
(from tauri.conf.json) instead of the actual release version. Extract
the version from the git tag and update tauri.conf.json and Cargo.toml
before building.
Extract ModelCapabilities and ContextWindowBadge into shared components.
Model type badge moved to title row with icon, capabilities shown as
icon-only colored tags, context window formatted as colored badge (k/M).
Also add capability and context info to model select dropdown options.
Bumps twilight-ai to 3ebcc56 which strips data URL prefixes and
validates media_type before sending to Anthropic API, preventing
400 errors for unsupported image MIME types.
- Prevent Enter from sending message during IME composing (keyCode 229)
- Remove separator line between textarea and toolbar
- Change send/stop buttons to compact circular icon-only style
- Fix send icon color to white for dark mode visibility
- Add missing hidden file input element so the attach button works
Replace all FontAwesome icon usage across 80+ Vue files with lucide-vue-next
components. Remove FontAwesome dependencies (@fortawesome/*) and global
registration from main.ts. Delete unused components (data-table, warning-banner,
session-metadata, bot-sidebar/bot-item in home, message-list, tts-provider-select),
dead utilities (channel-icons.ts, custom-icons.ts), and stale assets (vue.svg).
Update AGENTS.md to reflect the new icon strategy.
Add version and commit_hash fields to the /ping endpoint response,
sourced from the existing internal/version package (ldflags or
Go build info). The frontend capabilities store reads these values
and displays them as badges at the bottom of the Profile page.
Remove per-session-type (chat/heartbeat/schedule) bar series from the
Daily Tokens chart, keeping only aggregated Total Input and Total Output
as stacked bars for a cleaner visualization.
- Fix cookie check logic: use `!includes('sidebar_state=false')` instead
of `includes('sidebar_state=true')` so sidebar defaults to open when
no cookie is set
- Add --sidebar-width CSS variable binding to desktop sidebar element
- Adjust SIDEBAR_WIDTH_MOBILE value
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Provider preset YAML files under conf/providers were not bundled into
the server Docker image or preserved by the install script, so fresh
deployments started without any pre-configured LLM providers.
Replace the single browser image (which required local build) with three
prebuilt images: browser-chromium, browser-firefox, and browser (both).
Each is exposed as a separate Docker Compose profile so users can simply
`docker compose --profile browser-chromium up -d` without any local build
step, significantly reducing install time.