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.
Replace the global streaming ref with a streamingSessionId that
records which session is actively streaming. The streaming computed
now returns true only when the current session matches, so switching
sessions no longer leaks the generating indicator to unrelated sessions.
Constrain the main layout to viewport height (h-dvh) and override
SidebarProvider's min-h-svh so the height chain propagates correctly.
Change main-container overflow from auto to hidden so the outer
container never scrolls. Use absolute-positioning pattern for
session sidebar ScrollArea (matching chat messages pattern) to
ensure sessions scroll independently while the chat input stays fixed.
These two fields controlled history context window (time-based) and token-based
trimming. They are no longer needed — the resolver now always uses the hardcoded
24-hour default and skips token-based history trimming.
- Add `enable` column (default false) to search_providers and tts_providers tables
- Auto-create default entries for all provider types on startup (disabled by default)
- Add enable/disable Switch toggle in frontend for both search and TTS providers
- Show green status dot in sidebar for enabled providers, sort enabled first
- Filter bot settings dropdowns to only show enabled providers
Add a dropdown menu to each bot item in the chat sidebar with:
- "Details" option to navigate to the bot's settings page
- "Pin/Unpin" option to pin bots to the top of the list, persisted via localStorage
Backend
- New subject kinds: all / channel_identity / channel_type
- Source scope fields on bot_acl_rules: source_channel,
source_conversation_type, source_conversation_id, source_thread_id
- Fix source_scope_check constraint: resolve source_channel server-side
(channel_type → subject_channel_type; channel_identity → DB lookup)
- Add GET /bots/:id/acl/channel-types/:type/conversations to list
observed conversations by platform type
- ListObservedConversations: include private/DM chats, normalise
conversation_type; COALESCE(name, handle) for display name
- enrichConversationAvatar: persist entry.Name → conversation_name
(keeps Telegram group titles current on every message)
- Unify Priority type to int32 across Go types to match DB INTEGER;
remove all int/int32 casts in service layer
- Fix duplicate nil guard in Evaluate; drop dead SourceScope.Channel field
- Migration 0048_acl_redesign
Frontend
- Drag-and-drop rule priority reordering (SortableJS/useSortable);
fix reorder: compute new order from oldIndex/newIndex directly,
not from the array (which useSortable syncs after onEnd)
- Conversation scope selector: searchable popover backed by observed
conversations (by identity or platform type); collapsible manual-ID fallback
- Display: name as primary label, stable channel·type·id always shown
as subtitle for verification
- bot-terminal: accessibility fix on close-tab button (keyboard events)
- i18n: drag-to-reorder, conversation source, manual IDs (en/zh)
Tests: update fakeChatACL to Evaluate interface; fix SourceScope literals.
SDK/spec regenerated.
* feat(web): add provider oauth management ui
* feat: add OAuth callback support on port 1455
* feat: enhance reasoning effort options and support for OpenAI Codex OAuth
* feat: update twilight-ai dependency to v0.3.4
* refactor: promote openai-codex to first-class client_type, remove auth_type
Replace the previous openai-responses + metadata auth_type=openai-codex-oauth
combo with a dedicated openai-codex client_type. OAuth requirement is now
determined solely by client_type, eliminating the auth_type concept from the
LLM provider domain entirely.
- Add openai-codex to DB CHECK constraint (migration 0047) with data migration
- Add ClientTypeOpenAICodex constant and dedicated SDK/probe branches
- Remove AuthType from SDKModelConfig, ModelCredentials, TriggerConfig, etc.
- Simplify supportsOAuth to check client_type == openai-codex
- Add conf/providers/codex.yaml preset with Codex catalog models
- Frontend: replace auth_type selector with client_type-driven OAuth UI
---------
Co-authored-by: Acbox <acbox0328@gmail.com>
- Add reusable TimezoneSelect component with search and UTC offset labels
- Replace plain Select with searchable TimezoneSelect in profile settings,
bot settings, and browser context settings
- Move bot timezone setting from header dialog into bot settings tab
- Resolve timezone with bot > user > system priority for all LLM-facing
time formatting (user message header, system prompt, heartbeat, tools,
memory extraction)
- Format tool output timestamps (history, contacts) in resolved timezone
Move CreateModel, BuildReasoningOptions, ReasoningBudgetTokens and
related types from internal/agent to internal/models as NewSDKChatModel,
SDKModelConfig, etc. This eliminates duplicate ClientType constants and
centralises all Twilight AI SDK instance creation in a single package.
NewSDKEmbeddingModel now accepts a clientType parameter and dispatches
to the native Google embedding provider for google-generative-ai,
instead of always using the OpenAI-compatible endpoint.
The immediate watcher on configuredChannels accessed list[0].meta.type
without checking if the list was empty, causing a TypeError on initial
mount before data loaded. This crashed the component during setup and
corrupted KeepAlive state, making all bot detail tabs unresponsive.
Made-with: Cursor
Images sent by users were silently dropped when the model supported
vision: routeAttachmentsByCapability classified them as "Native", but
extractFileRefPaths only collected "Fallback" (tool_file_ref) paths,
so the image data URL was computed and then discarded — the model saw
neither the image nor its container path.
- Add InlineImages field to RunConfig to carry native image data
- Replace extractFileRefPaths with extractAttachmentPaths that
collects paths from both Native (FallbackPath) and Fallback
attachments so the YAML header always lists every attachment
- Add extractNativeImageParts to extract inline image data URLs
- Pass InlineImages as sdk.ImagePart in prepareRunConfig so the
LLM receives the actual image content alongside the text query
* # This is a combination of 6 commits.
# This is the 1st commit message:
feat(channel): add WeChat (weixin) adapter with QR code (#278)
* feat(channel): add WeChat (weixin) adapter with QR code
* fix(channel): fix weixin block streaming
* chore(channel): update weixin logo
# The commit message #2 will be skipped:
# build: 修改lint配置
# The commit message #3 will be skipped:
# build: 修改lint配置
# The commit message #4 will be skipped:
# 修改lint配置
# The commit message #5 will be skipped:
# 检测类型错误
# The commit message #6 will be skipped:
# ts类型检测错误
* feat(husky): update linting configuration to improve pre-commit checks
---------
Co-authored-by: 晨苒 <16112591+chen-ran@users.noreply.github.com>
Replace FontAwesome/CDN brand icons with local SVG-based Vue components
in a new shared @memoh/icon package. Provider icon URLs in conf/providers
YAML files are replaced with preset names, intercepted by ProviderIcon
component on the frontend. SearchProviderLogo and ChannelIcon components
are migrated to @memoh/icon. All icon containers now use a unified
circular gray (rounded-full bg-muted) style. Adds wechat and matrix
channel icons.
* feat(channel): add Matrix adapter support
* fix(channel): prevent reasoning leaks in Matrix replies
* fix(channel): persist Matrix sync cursors
* fix(channel): improve Matrix markdown rendering
* fix(channel): support Matrix attachments and multimodal history
* fix(channel): expand Matrix reply media context
* fix(handlers): allow media downloads for chat-access bots
* fix(channel): classify Matrix DMs as direct chats
* fix(channel): auto-join Matrix room invites
* fix(channel): resolve Matrix room aliases for outbound send
* fix(web): use Matrix brand icon in channel badges
Replace the generic Matrix hashtag badge with the official brand asset so channel badges feel recognizable and fit the circular mask cleanly.
* fix(channel): add Matrix room whitelist controls
Let Matrix bots decide whether to auto-join invites and restrict inbound activity to allowed rooms or aliases. Expose the new controls in the web settings UI with line-based whitelist input so access rules stay explicit.
* fix(channel): stabilize Matrix multimodal follow-ups and settings
* fix(flow): avoid gosec panic on byte decoding
* fix: fix golangci-lint
* fix(channel): remove Matrix built-in ACL
* fix(channel): preserve Matrix image captions
* fix(channel): validate Matrix homeserver and sync access
Fail Matrix connections early when the homeserver, access token, or /sync capability is misconfigured so bot health checks surface actionable errors.
* fix(channel): preserve optional toggles and relax Matrix startup validation
* fix(channel): tighten Matrix mention fallback parsing
* fix(flow): skip structured assistant tool-call outputs
* fix(flow): resolve merged resolver duplication
Keep the internal agent resolver implementation after merging main so split helper files do not redeclare flow symbols. Restore user message normalization in sanitize and persistence paths to keep flow tests and command packages building.
* fix(flow): remove unused merged resolver helper
Drop the leftover truncate helper and import from the resolver merge fix so golangci-lint passes again without affecting flow behavior.
---------
Co-authored-by: Acbox Liu <acbox0328@gmail.com>
* refactor: replace persistent subagents with ephemeral spawn tool (#subagent)
- Drop subagents table, remove all persistent subagent infrastructure
- Add 'subagent' session type with parent_session_id on bot_sessions
- Rewrite subagent tool as single 'spawn' tool with parallel execution
- Create system_subagent.md prompt, add _subagent.md include for chat
- Limit subagent tools to file, exec, web_search, web_fetch only
- Merge subagent token usage into parent chat session in reporting
- Remove frontend subagent management page, update chat UI for spawn
- Fix UTF-8 truncation in session title, fix query not passed to agent
* refactor: remove history message page
* refactor: move client_type to provider, replace model fields with config JSONB
- Move `client_type` from `models` to `llm_providers` table
- Add `icon` field to `llm_providers`
- Replace `dimensions`, `input_modalities`, `supports_reasoning` on `models`
with a single `config` JSONB column containing `dimensions`,
`compatibilities` (vision, tool-call, image-output, reasoning),
and `context_window`
- Auto-imported models default to vision + tool-call + reasoning
- Update all backend consumers (agent, flow resolver, handlers, memory)
- Regenerate sqlc, swagger, and TypeScript SDK
- Update frontend forms, display, and i18n for new schema
* ui: show provider icon avatar in sidebar and detail header, remove icon input
* feat: add built-in provider registry with YAML definitions and enable toggle
- Add `enable` column to llm_providers (default true, backward-compatible)
- Create internal/registry package to load YAML provider/model definitions
on startup and upsert into database (new providers disabled by default)
- Add conf/providers/ with OpenAI, Anthropic, Google YAML definitions
- Add RegistryConfig to TOML config (providers_dir, default conf/providers)
- Model listing APIs and conversation flow now filter by enabled providers
- Frontend: enable switch in provider form, green status dot in sidebar,
enabled providers sorted to top
* fix: make 0041 migration idempotent for fresh databases
Guard data migration steps with column-existence checks so the
migration succeeds on databases created from the updated init schema.
When input tokens exceed a configurable threshold after a conversation round,
the system asynchronously compacts older messages into a summary. Cascading
compactions reference prior summaries via <prior_context> tags to maintain
conversational continuity without duplicating content.
- Add bot_history_message_compacts table and compact_id on messages
- Add compaction_enabled, compaction_threshold, compaction_model_id to bots
- Implement compaction service (internal/compaction) with LLM summarization
- Integrate into conversation flow: replace compacted messages with summaries
wrapped in <summary> tags during context loading
- Add REST API endpoints (GET/DELETE /bots/:bot_id/compaction/logs)
- Add frontend Compaction tab with settings and log viewer
- Wire compaction service into both dev (cmd/agent) and prod (cmd/memoh) entry points
- Update test mocks to include new GetBotByID columns