Commit Graph
30 Commits
Author SHA1 Message Date
7418andClaude Opus 4.6 d9f2e6d614 refactor: replace inline layout patterns with SettingsCard/FieldRow/StatusBanner (PR3)
Settings pages:
- GeneralSection: 3 inline cards → SettingsCard, 3 field rows → FieldRow,
  warning banner → StatusBanner
- AppearanceSection: card → SettingsCard, mode/family rows → FieldRow,
  native <button> in ThemeModePills → Button, UIPreview buttons → Button

Bridge pages:
- BridgeSection: 5 inline cards → SettingsCard, master toggle/autostart → FieldRow,
  active hint → StatusBanner
- TelegramBridgeSection: 3 cards → SettingsCard, verify result → StatusBanner
- DiscordBridgeSection: 4 cards → SettingsCard, require mention/stream → FieldRow,
  verify result → StatusBanner
- FeishuBridgeSection: 4 cards → SettingsCard, require mention → FieldRow,
  verify result → StatusBanner
- QqBridgeSection: 4 cards → SettingsCard, image toggle → FieldRow,
  verify result → StatusBanner

Pure UI replacement — no data logic changes. All files retain identical
behavior and visual output.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 21:50:20 +08:00
7418andClaude Opus 4.6 e5a48ca6af feat: migrate icon library from Hugeicons to Phosphor + UI polish
Icon library migration:
- Replace @hugeicons/react with @phosphor-icons/react across 60+ components
  (Phosphor supports 6 weight variants: thin/light/regular/bold/fill/duotone)
- Update apps/site (marketing) to use Phosphor icons
- Remove leftover svg.hugeicons CSS rules from globals.css

UI improvements:
- NavRail: selected tab icons use filled weight, unselected use regular
- User chat bubble: dark bg + white text in light mode, light bg + dark text
  in dark mode (new --user-bubble / --user-bubble-foreground CSS variables)
- Fix expand/collapse icons: use CaretRight (triangle) instead of ArrowRight
  in file-tree.tsx and tool-actions-group.tsx

Lint fixes:
- Fix eslint react-hooks/static-components in CodeBlock, ToolCallBlock,
  tool-actions-group — use createElement() instead of PascalCase variable
- Fix react-hooks/rules-of-hooks in MessageItem — move early return after hooks
- Fix react-hooks/set-state-in-effect in GalleryDetail — use ref pattern

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 11:12:12 +08:00
7418andClaude Opus 4.6 5e18acb63d feat: provider auth style selector & edit UX improvements
- Anthropic Third-party API: add API Key / Auth Token selector in connect dialog
  with proper extra_env injection and auth style detection
- Edit mode: reuse PresetConnectDialog for matched providers instead of generic
  ProviderForm, showing only relevant fields consistent with connect experience
- Edit mode: show masked key (dots) instead of empty field; switching auth style
  clears key and requires re-entry; switching back restores masked value
- Edit mode: expose headers_json, env_overrides_json, notes in advanced section
  so all fields remain visible and editable
- Edit mode: role_models_json merge logic preserves unseen roles (reasoning, small)
  while allowing clearing of visible mapping fields
- Dialog: add max-h-[calc(100vh-4rem)] + overflow-y-auto to DialogContent base;
  remove overflow-hidden from preset dialog so scrolling actually works
- Connected provider badge: detect ANTHROPIC_AUTH_TOKEN in extra_env to show
  correct "Auth Token" vs "API Key" label
- i18n: add provider.authToken, provider.authStyle keys (en + zh)
- Bump version to 0.31.0

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 00:57:40 +08:00
7418andClaude Opus 4.6 f76e4747cd feat: unified provider resolver with protocol-based dispatch
Extract provider resolution logic into two new modules:
- provider-catalog.ts: vendor presets, default model catalogs, protocol definitions
- provider-resolver.ts: unified resolution for all consumers (Claude SDK, AI SDK, model listing)

DB migration:
- Add protocol, headers_json, env_overrides_json, role_models_json columns to api_providers
- Create provider_models table for per-provider model catalog

Consumer refactoring:
- claude-client.ts: replace inline env-building with toClaudeCodeEnv()
- text-generator.ts: replace inline config with toAiSdkConfig()
- conversation-engine.ts, onboarding, checkin, plan routes: use shared resolveProvider()
- /api/providers/models: read from catalog + provider_models table

UI improvements:
- Merge confusing "Custom API (Anthropic-compatible)" into "Anthropic Third-party API"
- Add 3-field model name mapping (sonnet/opus/haiku) in advanced options
- ProviderForm.tsx: support new fields (protocol, env_overrides, role_models)

Bug fixes:
- Protect auth credentials from being deleted by legacy extra_env empty-string overrides
- Fix env var names: ANTHROPIC_DEFAULT_SONNET → ANTHROPIC_DEFAULT_SONNET_MODEL (SDK convention)

Tests: 229/229 passed. Verified with aiberm (no mapping) and pipellm (with mapping).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 20:30:35 +08:00
7418andClaude Opus 4.6 94528edac9 fix: use local timezone for date-based features (check-in, usage stats)
Root cause: `new Date().toISOString().slice(0, 10)` returns UTC date,
causing date-based features to be off by up to ±1 day for non-UTC users.

Check-in / assistant workspace:
- Add `getLocalDateString()` utility, replace all UTC date comparisons
- Schema v2→v3 migration: normalize lastCheckInDate only when it matches
  UTC today (ambiguous window); leave past dates untouched so check-in
  triggers correctly after upgrade
- Runtime compat in `needsDailyCheckIn`: accept UTC today as fallback
  for edge cases the migration cannot catch
- `needsDailyCheckIn(state, now?)` accepts optional time for testability

Usage stats:
- Replace single-offset SQL bucketing (`DATE(datetime(..., '+N minutes'))`)
  with JS-side per-row aggregation using `getLocalDateString(new Date(utc))`
- Date methods account for historical DST offset at each message's timestamp
- `getTokenUsageStats(days, now?)` accepts optional time to pin window start
- Window boundary via `localDayStartAsUTC()` is already DST-aware

Tests (new file: timezone-boundaries.test.ts, 22 tests):
- getLocalDateString at UTC+9/UTC-5/UTC boundaries with fixed timestamps
- needsDailyCheckIn: compat suppression, clearly-past trigger, local match
- v2→v3 migration: targeted normalization, past-date preservation, null safe
- localDayStartAsUTC: UTC+8/UTC-5 midnight boundaries
- Usage stats bucketing: UTC+9 cross-day, summary window, DST spring-forward
- All usage stats tests use pinned `now` — no time-bomb from fixed test data

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 11:55:29 +08:00
7418andClaude Opus 4.6 4da188bfe5 feat: theme family system with 12 color palettes + NavRail redesign
Theme system:
- Two-layer architecture: mode (light/dark/system via next-themes) + theme family (color palette via CSS variables)
- 12 theme families: Default, GitHub, Rosé Pine, Tokyo Night, Everforest, Nord, Kanagawa, Night Owl, Poimandres, Vesper, Horizon, SynthWave '84
- Per-family code block highlighting for Prism, HLJS, and Shiki (no more generic oneLight/oneDark fallback)
- Anti-FOUC: synchronous script in <head> reads localStorage and sets data-theme-family before paint
- Theme JSON files in themes/ directory, auto-discovered by server-side loader
- OKLCH color space for all values; CSS specificity html[data-theme-family] beats :root

UI changes:
- NavRail: moved Settings to bottom (replacing theme toggle), removed light/dark toggle button
- Settings: merged General controls into one card with dividers; Appearance section with live Shiki code preview
- Replaced hardcoded blue-500/blue-600 with primary/primary-foreground across 19 components
- Appearance settings: pill mode selector (light/dark/system), theme family dropdown, live code preview

New files:
- src/lib/theme/{types,loader,render-css,context,code-themes}.ts — core theme infrastructure
- src/components/layout/ThemeFamilyProvider.tsx — client context provider
- src/components/settings/AppearanceSection.tsx — appearance settings UI
- src/hooks/useAppTheme.ts — combined theme hook
- themes/*.json — 12 theme family definitions
- docs/handover/theme-system.md — handover documentation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 11:15:01 +08:00
7418andClaude Opus 4.6 c18776f4ca feat: integrate Claude Agent SDK capabilities — model/command discovery, effort/thinking, MCP runtime, file rewind, structured output
Systematically integrate high-value SDK capabilities while preserving the
multi-provider architecture:

SDK capability discovery (per-provider cache):
- agent-sdk-capabilities.ts: cache models, commands, account info, MCP status
  per provider via Map<providerId, cache> to prevent cross-provider pollution
- claude-client.ts: fire-and-forget captureCapabilities() after query() init
- providers/models: merge SDK models with static defaults
- skills: merge SDK slash commands with filesystem skills

Query options passthrough:
- thinking (adaptive/enabled/disabled), effort (low/medium/high/max),
  outputFormat, agents, enableFileCheckpointing
- /chat page.tsx: first-message path now includes effort/thinking (was missing)
- stream-session-manager: passes effort/thinking in POST body

Graceful interrupt:
- /api/chat/interrupt: conversation.interrupt() before abort fallback
- stream-session-manager: tries interrupt first, aborts after 2s timeout

MCP runtime management:
- /api/plugins/mcp/status: live status from active Query, auto-resolves
  providerId from session DB record (prevents wrong-provider cache writes)
- /api/plugins/mcp/reconnect + toggle: reconnect/enable/disable servers
- McpManager + McpServerList: runtime status indicators with action buttons

File checkpointing & rewind:
- enableFileCheckpointing=true for code mode by default
- rewind_point SSE: only emitted for prompt-level user messages
  (parent_tool_use_id===null) and skips autoTrigger turns
- /api/chat/rewind: dry-run preview + actual rewind via rewindFiles()
- MessageList: RewindButton with dry-run preview

Structured output:
- /api/chat/structured: reads SDKResultSuccess.structured_output as primary
  path, text fallback only when absent

Account info & thinking config:
- /api/sdk/account: cached account info display
- Settings: thinking_mode in ALLOWED_KEYS, thinking mode selector in UI
- Effort selector in MessageInput with lifted state pattern

New files: 11 route handlers + 2 lib modules + 1 test file
Modified files: 18 (types, client, manager, UI components, i18n)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 18:22:05 +08:00
7418andClaude Opus 4.6 5eedb5bacc fix: resolve 7 bugs — idle output, permission scroll, file selector, drag area, input reset, markdown tables, panel collapse
- ChatView: consume unconsumed stream snapshots on mount so output
  appears after idle without needing a conversation switch
- PermissionPrompt: extract permission UI from StreamingMessage into a
  fixed-position component at the bottom of ChatView, preventing
  permission popups from scrolling off-screen during long responses
- StreamingMessage/MessageList: remove ~409 lines of permission UI code
  now handled by PermissionPrompt
- AssistantWorkspaceSection: fix macOS Electron file selector by using
  the correct IPC API (window.electronAPI.dialog.openFolder)
- AppShell: increase title bar drag region from h-5 to h-10 (#152)
- ChatView: add key={sessionId} on MessageInput to reset input state
  when switching conversations (#176)
- UpdateDialog: add remark-gfm plugin and table component mappings for
  proper GFM markdown rendering in release notes (#117)
- RightPanel: add border and top margin to collapsed panel toggle for
  visibility (#116)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 14:24:19 +08:00
7418andClaude Opus 4.6 94fdd36d27 feat: assistant workspace V2 — indexing, retrieval, security hardening & workspace switching
Assistant Workspace V2:
- Markdown indexing engine (incremental manifest + chunks JSONL)
- Keyword retrieval with CJK bigram support and hotset boosting
- Directory taxonomy inference and evolution suggestions
- Workspace config management (.assistant/config.json)
- Organize API: capture, classify, move, archive, suggest-evolution

Workspace switching:
- Inspect API (GET /api/workspace/inspect) for pre-switch validation
- Two-phase switching with confirmation dialogs (5 workspace statuses)
- Atomic save: init/reset runs before setSetting(), rollback on failure
- Auto-navigate to new/reused session after switch
- Mismatch banner in ChatView (only for former assistant sessions)
- Debounced path validation with visual indicators

Security hardening:
- Completion fence (onboarding-complete/checkin-complete) only processes
  when session.workingDirectory === assistant_workspace_path (frontend)
  AND session.working_directory === workspacePath (backend double-check)
- assertContained() in workspace-organizer: rejects absolute paths, ~/,
  ../ traversal, and symlink escapes for captureNote/moveFile
- organize API validates all path params at entry (validateRelativePath)
- captureDefault sanitized to relative path on onboarding write
- R_OK + W_OK validation on GET settings, session creation, and PUT

Bug fixes:
- hookTriggeredSessionId now read before auto-trigger; allows retry if
  session has no messages (previous trigger failed silently)
- workspace-switched event listener matches oldPath (not just != newPath)
  so normal project chats never show the mismatch banner
- Daily check-in card hidden when onboarding not complete
- Refresh docs now calls generateRootDocs() + generateDirectoryDocs()
- Banner "Open" button reuses latest session (checkin mode) instead of
  always creating new onboarding session

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 00:37:02 +08:00
7418andClaude Opus 4.6 19aba25c8f feat: assistant workspace — persistent AI personality & memory via Markdown files (#165)
Add "Assistant Workspace" feature that lets users designate a directory
(e.g. Obsidian vault) containing 4 Markdown files (soul.md, user.md,
memory.md, claude.md) to define AI personality, user profile, long-term
memory, and execution rules. These files are automatically injected into
the system prompt for assistant project sessions.

Core library (src/lib/assistant-workspace.ts):
- Workspace validation, initialization with template files
- File loading with 8000-char truncation, XML prompt assembly (40k limit)
- State management via .assistant/state.json
- Directory docs generation (README.ai.md + PATH.ai.md)
- Case-insensitive file name fallback (soul.md → SOUL.md)

System prompt injection (src/app/api/chat/route.ts):
- Scoped to sessions where working_directory === workspace path
- Workspace prompt prepended before session-level system prompt
- Onboarding/check-in instructions injected as <assistant-project-task>
- autoTrigger flag skips user message save and title update

Chat-based onboarding (10 questions) & daily check-in (3 questions):
- AI conducts conversation, outputs structured completion code blocks
- Frontend detects onboarding-complete/checkin-complete blocks
- Backend calls Claude API to generate file content from answers
- Fallback to raw answers if API call fails

Auto-trigger pipeline:
- Mount trigger (500ms delay) + focus fallback in MessageInput
- assistantTriggerFiredRef prevents duplicate triggers per mount
- hookTriggeredSessionId in state.json prevents cross-reload duplicates
- Daily check-in only triggers in the most recent workspace session
- hookTriggeredSessionId cleared via __clear__ sentinel after completion

API endpoints:
- GET/PUT /api/settings/workspace — path CRUD + file status
- POST /api/workspace/session — create (onboarding) or reuse (check-in)
- POST /api/workspace/onboarding — AI-generate soul.md + user.md
- POST /api/workspace/checkin — AI-update memory.md + user.md
- POST /api/workspace/hook-triggered — set/clear trigger guard
- GET /api/workspace/latest-session — latest session lookup
- POST /api/workspace/docs — refresh directory documentation

UI:
- Settings "Assistant" tab with workspace path, file status, controls
- Violet badge on workspace project group in ChatListPanel
- useAssistantWorkspace hook for state queries

Also includes:
- 102 passing tests (16 new regression tests for workspace logic)
- i18n keys for en.ts and zh.ts
- Handover documentation and execution plan

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 20:31:42 +08:00
7418 6dfe23a9a9 fix: 修复百炼 API key 配置并发布 v0.23.1 2026-03-03 16:36:10 +08:00
7418andClaude Opus 4.6 68bb6b60bb feat: 新增服务商 + 文件上传优化 + AskQuestion 改进
新增功能:
- 新增字节火山方舟 (Volcengine Ark) 快速配置预设
  - 支持用户输入模型名称,映射到聊天输入框模型选择器
  - 模型名称存入 extra_env 的 ANTHROPIC_MODEL
- 新增阿里云百炼 (Aliyun Bailian) 快速配置预设
  - 内置 7 个模型供用户直接选择(Qwen 3.5 Plus、Kimi K2.5、GLM-5 等)
  - 无需额外配置模型名称
- 两个服务商均使用 @lobehub/icons 品牌图标 (Volcengine, Bailian)
- ProviderManager 图标识别规则新增 volces.com/dashscope 等 URL 匹配
- PresetConnectDialog 新增 model_names 字段类型,渲染模型名称输入框
- models route 动态读取 extra_env 中的 ANTHROPIC_MODEL 展示到模型选择器

修复 & 优化:
- 移除文件上传的类型限制 (ACCEPTED_FILE_TYPES) 和大小限制 (MAX_FILE_SIZE)
  现在支持所有文件类型和任意大小,由 API 端处理限制
- AskQuestion 按钮样式对齐权限确认按钮 (h-8 px-3 text-sm font-medium)
- AskQuestion 组件渲染位置从工具调用区域移到流式文本下方
  解决长文本输出后用户找不到选择组件的问题
- Anthropic Third-party API 预设的 provider_type 从 "custom" 改为 "anthropic"
  修复第三方 Anthropic 兼容 API 无法正确生效的问题

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 12:44:07 +08:00
7418 c14fdb07ae fix: resolve mac updater no-response by shipping zip and surfacing errors 2026-02-27 14:35:22 +08:00
7418andClaude Opus 4.6 09908cfcb7 fix: resolve macOS build race condition and update download button unresponsive
CI 修复 (electron-builder.yml):
- 移除 mac target 的 arch: [arm64, x64],改由 CI matrix 的 --arch flag 控制
- 根因:两个 macOS job 各自构建两个架构的 DMG,产生两个 draft release,
  导致 release job 只发布了没有 DMG 的那个,macOS 产物丢失

下载按钮无响应修复:
- electron/updater.ts: downloadUpdate IPC handler 加 try-catch,
  失败时通过 sendStatus 发送 error 事件给前端,避免静默失败
- AppShell.tsx: downloadUpdate 回调点击后立即设置 downloadProgress=0
  提供即时 UI 反馈;加 await + catch 处理下载失败并重置状态
- AppShell.tsx: error 事件处理中重置 downloadProgress 为 null,
  使下载按钮在失败后重新出现
- UpdateDialog.tsx / GeneralSection.tsx: isDownloading 判断移除 > 0 条件,
  downloadProgress === 0 时也显示下载中状态,消除点击后无反馈的间隙

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 12:11:20 +08:00
7418andClaude Opus 4.6 fd03d179e3 fix: improve auto-update UX and proxy support, bump v0.17.1
Auto-update flow rework:
- updater.ts: disable autoDownload, add manual `updater:download` IPC handler
  so user explicitly triggers download via "Download & Install" button
- updater.ts: resolve system proxy via session.defaultSession.resolveProxy()
  and inject into HTTPS_PROXY env var, fixing zero download speed behind VPN/proxy
- preload.ts + electron.d.ts: expose `downloadUpdate` method to renderer

UI improvements:
- UpdateDialog: add "Download & Install" button when update available but not
  yet downloading; show progress bar during download; "Restart to Update" when ready
- GeneralSection UpdateCard: show "Download & Install" / "Restart to Update" button
  next to "Check for Updates"; show download progress bar inline; add "View Details"
  link to reopen update dialog
- AppShell: dismissUpdate no longer permanently hides update for that version
  (removed localStorage persistence), just closes the dialog
- useUpdate: add downloadUpdate to context

i18n:
- Added `update.installUpdate` key (en: "Download & Install", zh: "下载并安装")

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 11:19:48 +08:00
7418andClaude Opus 4.6 a5e2cedc12 feat: gallery masonry layout, favorites system, left-right detail dialog, bump v0.17.0
Gallery UI overhaul:
- GalleryGrid: replace equal-size grid with CSS columns masonry layout (6 columns),
  pure image cards without text/date info, hover gray ring highlight,
  favorited items show red heart badge
- GalleryDetail: left-right layout dialog (70% image / 30% info),
  nearly full-screen size with minimal margins, black background for image area,
  absolute-positioned image container for correct sizing across all aspect ratios,
  favorite toggle button replaces tag manager, removed outer border
- Gallery page: added "favorites only" filter button, replaced load-more button
  with IntersectionObserver infinite scroll, removed tag system references

Favorites system:
- db.ts: added `favorited` column to media_generations with migration
- New API: PUT /api/media/[id]/favorite for toggle
- gallery/route.ts: support favoritesOnly=1 filter, return favorited field
- i18n: added favorites-related translations (en/zh)

Other:
- Default image model changed from Nano Banana Pro to Nano Banana 2
- providers/models/route.ts: skip media provider types in chat model selector

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 11:00:58 +08:00
7418andClaude Opus 4.6 5ac4eb5eb6 feat: add Nano Banana 2 model, revert default to Nano Banana Pro, bump v0.16.0
模型变更:
- 新增 Nano Banana 2 (gemini-3.1-flash-image-preview) 到模型列表
- 默认模型恢复为 Nano Banana Pro (gemini-3-pro-image-preview)
  原因:Nano Banana 2 刚发布,部分区域尚未完全上线,调用会超时
- 模型列表顺序:Nano Banana 2 > Nano Banana Pro > Nano Banana
- 更新 ProviderManager、image-generator.ts、media/generate route 的默认值

依赖更新:
- @ai-sdk/google 3.0.31 → 3.0.32

版本:
- package.json 版本号 0.15.1 → 0.16.0

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 01:05:04 +08:00
7418andClaude Opus 4.6 d5dd9cfe34 feat: unify reference image data structure, add Nano Banana 2 model
Reference Image 统一重构:
- 新增 ReferenceImage 类型 (src/types/index.ts),统一承载 base64 和 localPath 两种来源
- 重写 image-ref-store.ts:单一 Map<string, ReferenceImage[]> 替代原来的
  imageGenRefStore + lastGeneratedImagePaths 双通路
  - sessionStorage 持久化 last-generated 路径,解决页面刷新后数据丢失
  - buildReferenceImages() 作为唯一的 merge 入口,消除各组件手写拼接逻辑
- ImageGenConfirmation props 从两个 (referenceImagePaths + referenceImagesData)
  合并为单一 referenceImages?: ReferenceImage[]
  - 预览渲染改为单循环,根据 data/localPath 决定 img src,上传图和结果图同时显示
  - API 调用时再拆分回 base64 和路径两个字段,后端无需改动
- StreamingMessage / MessageItem 各自 5 行手动 merge 逻辑替换为一行
  buildReferenceImages() 调用
- ChatView 改用 setLastGeneratedImages() 和 transferPendingToMessage()
  替代直接操作 Map
- MessageInput 改用 setRefImages() / deleteRefImages() 替代直接操作 Map

新增 Gemini 3.1 Flash Image 模型:
- 新增 Nano Banana 2 (gemini-3.1-flash-image-preview) 作为默认图片生成模型
- 模型列表: Nano Banana 2 > Nano Banana Pro > Nano Banana
- 更新 ProviderManager、image-generator.ts、media/generate route 的默认值

其他已有改动一并提交:
- batch image generation 功能文件
- 依赖更新 (package.json / package-lock.json)
- i18n、db schema、AppShell、uploads route 等相关改动

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 00:55:24 +08:00
7418 00d3fef5a4 feat: refactor image generation to bypass model dependency, fix UI issues
Image Generation Refactor:
- MessageInput: add onImageGenerate callback, remove skill fetch dependency
- ChatView: implement handleImageGenerate that creates image-gen-request
  message for ImageGenConfirmation UI, then user selects params and generates
- New API route POST /api/chat/messages for DB-only message persistence
- image-gen-completed event now only persists notice to DB, no longer triggers model
- Reference images passed via module-level Map (imageGenRefStore) to avoid
  DB bloat from base64 data; user message DB content stores metadata only

Bug Fixes:
- Fix useCallback dependency missing imageGen causing stale closure reads
- Fix React Hooks order violation in MessageItem (early return before hooks)
- Fix localStorage cache collision across sessions (key now includes sessionId)
- Fix empty src attribute in FileAttachmentDisplay for DB-restored messages
- Add JSON parse fallback for malformed image-gen-request blocks

Gallery Reference Images:
- /api/media/generate saves reference images to disk, stores paths in metadata
- /api/media/gallery extracts referenceImages from metadata in mapRow
- GalleryDetail displays reference image thumbnails
- ImageGenCard supports referenceImages prop for chat display

UI Changes:
- ImageGenToggle: replace paint brush icon with text label (en: Image, zh: 生图)
- Model selector button: remove provider name display to save space
- ImageGenConfirmation: support referenceImagesData prop for base64 preview

i18n:
- Add imageGen.toggleLabel key (en: Image, zh: 生图)
2026-02-26 21:07:48 +08:00
7418andClaude Opus 4.6 762953b2ad feat: integrate electron-updater for in-app auto-update
Replace the manual "jump to GitHub Release" update flow with native
in-app auto-update powered by electron-updater. The app now silently
downloads updates in the background and prompts the user to restart
when ready. Browser mode (`npm run dev`) retains the existing polling
fallback via `/api/app/updates`.

Main process (electron/updater.ts — new):
- Wrap electron-updater's autoUpdater, forward lifecycle events
  (checking / available / downloading / downloaded / error) to the
  renderer via IPC channel `updater:status`
- Register `updater:check` and `updater:quit-and-install` IPC handlers
- Auto-check 10s after launch, then every 4 hours
- Only initialized in packaged mode (!isDev)

Preload bridge (electron/preload.ts):
- Expose `updater` namespace with checkForUpdates, quitAndInstall,
  and onStatus callback (same pattern as install.onProgress)

Type declarations (src/types/electron.d.ts):
- Add UpdateStatusEvent, ElectronUpdaterAPI interfaces
- Add optional `updater` field to ElectronAPI

Update hook (src/hooks/useUpdate.ts):
- Extend UpdateInfo with downloadProgress, readyToInstall, isNativeUpdate
- Add quitAndInstall to UpdateContextValue

Renderer — dual-mode logic (src/components/layout/AppShell.tsx):
- Detect `window.electronAPI?.updater` to choose between native IPC
  subscription (Electron) and HTTP polling (browser)
- Map IPC events to UpdateInfo state, including download progress

UI components:
- UpdateDialog: three footer states — View Release (browser), progress
  bar + disabled button (downloading), Restart to Update (ready)
- UpdateBanner (new): persistent top banner when update is downloaded,
  shown even after dialog is dismissed
- NavRail: settings dot turns green + pulse when readyToInstall
- GeneralSection: UpdateCard shows download %, restart button, or
  View Release depending on mode

Build & CI:
- electron-builder.yml: add `publish` config (github provider) to
  generate latest-mac.yml / latest.yml metadata + blockmap files
- build.yml: change --publish never to --publish always with GH_TOKEN;
  release job now uses `gh release edit` instead of create

i18n:
- Add 6 translation keys (en + zh) for update UI strings

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 11:16:41 +08:00
7418andClaude Opus 4.6 5bace38e47 fix: improve ErrorBoundary i18n and update provider preset descriptions
ErrorBoundary (PR #49 follow-up):
- Replace inline SVG with lucide-react CircleAlert icon for consistency
- Add i18n support: extract fallback UI into functional ErrorFallback
  component so it can use useTranslation hook
- Remove unused withErrorBoundary HOC
- Add error.* translation keys to en.ts and zh.ts

ProviderManager:
- Add Claude Code default config entry in connected providers section
  with cc switch hint explaining configurations may not be readable
- Update GLM preset descriptions: "GLM" → "GLM Code Plan / 编程套餐"
- Update MiniMax preset descriptions: "MiniMax API" → "MiniMax Code Plan / 编程套餐"
- Add provider.ccSwitchHint translation key to en.ts and zh.ts

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 10:34:42 +08:00
7418andClaude Opus 4.6 d203b9802d feat: redesign Provider settings UI with brand icons and dialog-based quick-add
Completely rewrites the Provider management page in Settings to follow
the OpenCode reference design with two clear sections.

ProviderManager.tsx — full rewrite:
- Top section "Connected Providers": shows all configured providers as a
  clean list with brand icons from @lobehub/icons, name, badge, edit and
  disconnect buttons. Environment variables also shown here.
- Bottom section "Add Provider": preset list with icon + name + description
  + Connect button. Clicking Connect opens a dialog with only the fields
  needed for that preset.
- First 3 presets: Custom API (all fields), Anthropic Third-party API
  (name + URL + key), Anthropic Official (key only).
- Other presets (GLM, Kimi, Moonshot, MiniMax, etc.) simplified to key-only.
- Bedrock/Vertex show environment variable config.
- Removed the top-right "Add Provider" button entirely.
- Added PresetConnectDialog component: shows brand icon in title, only
  relevant fields, advanced options fold for extra_env, Cancel/Connect footer.

package.json:
- Add @lobehub/icons dependency for AI brand icons
- Bump version to 0.15.0

i18n (en.ts, zh.ts):
- Add translations: connectedProviders, noConnected, connect, disconnect,
  disconnectProvider, disconnectConfirm, addProviderSection, addProviderDesc,
  disconnecting

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 09:48:23 +08:00
7418andClaude Opus 4.6 448738d4f3 feat: provider/model system refactor — switch provider from chat input
Refactors the provider/model selection system so users can switch providers
directly from the chat input model selector, instead of having to go to
Settings to activate/deactivate providers.

types/index.ts:
- Add ProviderModelGroup interface for grouped provider+model data
- Extend SendMessageRequest, ClaudeStreamOptions, ChatSession with provider_id

db.ts:
- Migration: add provider_id column to chat_sessions
- Migration: convert is_active=1 provider to default_provider_id setting
- New helpers: updateSessionProviderId, getDefaultProviderId, setDefaultProviderId

providers/models/route.ts:
- Rewrite to return { groups, default_provider_id } instead of flat model list
- Each configured provider becomes a group; env vars become "Environment" group
- Deduplicate models within a group (e.g. GLM sonnet/opus both → "GLM-4.7" once)

chat/route.ts:
- Accept provider_id from request body
- Resolution chain: request → session → default_provider_id → env vars
- provider_id='env' is sentinel for environment variable fallback
- Pass resolved provider object to streamClaude()

claude-client.ts:
- Use options.provider ?? getActiveProvider() so explicit provider takes priority

ChatView.tsx:
- Track currentProviderId state, pass provider_id in fetch body
- New handleProviderModelChange callback

MessageInput.tsx:
- New props: providerId, onProviderModelChange
- Replace dynamicModels/activeProviderName with providerGroups/defaultProviderId
- Model selector UI: grouped by provider with section headers, ✓ for active item
- Persist both model and provider ID to localStorage

chat/page.tsx, chat/[id]/page.tsx:
- Track and pass provider_id through the component chain

ProviderManager.tsx:
- Remove handleActivate/handleDeactivate, activatingId, Apply/Disable buttons
- Remove Active badge and green border styling
- Simplify env variable banner
- Add provider-changed event dispatch to save/delete handlers

providers/route.ts:
- GET response now includes default_provider_id field

i18n (en.ts, zh.ts):
- Add provider.default, provider.setDefault, provider.environment translations

Backward compatible: old sessions without provider_id default to '' which
triggers the fallback chain. is_active column preserved but no longer written.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 00:22:18 +08:00
7418andClaude Opus 4.6 52f5bb5f86 feat: add token usage statistics page in Settings
New "Usage" tab in Settings showing token consumption analytics:

- **Data cards**: Total Tokens, Total Cost, Sessions, Cache Hit Rate
- **Bar chart**: Daily token usage with model/provider color grouping
  using recharts v3, with custom tooltip and continuous date x-axis
- **Provider tracking**: Each session now records the active provider
  name (e.g. "Kimi Coding Plan") so the chart distinguishes usage
  across different providers, not just model names

Backend changes (db.ts):
- Added `provider_name` column to chat_sessions with auto-migration
- Added `getTokenUsageStats(days)` with summary + daily aggregation
- SQL uses `json_valid()` guard to prevent malformed JSON crashes
- Fixed off-by-one: 7D now shows exactly 7 calendar days, not 8
- Provider-qualified grouping: shows provider name when set,
  plain model name when using direct Anthropic

API changes (route.ts):
- Persists effectiveModel and activeProvider name on every message
- Captures model from SDK init event for accurate tracking
- New GET /api/usage/stats endpoint

Frontend fixes:
- SettingsLayout: replaced useEffect+setState with useSyncExternalStore
  to fix react-hooks/set-state-in-effect lint error
- UsageStatsSection: AbortController prevents request race on rapid
  range switching; cache hit rate formula corrected to
  cache_read/(cache_read+input); date gaps filled with zeros for
  continuous x-axis
- Full i18n support (en + zh)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 00:07:41 +08:00
7418 c7c3ba5302 feat: v0.13.0 — add i18n support with Chinese/English translations
Implements a zero-dependency i18n framework with TypeScript type safety.
Thanks to @gy212 for the original i18n infrastructure design (PR #89)
and comprehensive translation files (PR #90-96) that inspired this implementation.

## New files (5)

- src/i18n/en.ts: English translations (source of truth, ~270 keys),
  exports TranslationKey type for compile-time key completeness
- src/i18n/zh.ts: Chinese translations, typed as Record<TranslationKey, string>
- src/i18n/index.ts: translate() function with {param} interpolation,
  Locale type, SUPPORTED_LOCALES array
- src/components/layout/I18nProvider.tsx: React Context provider,
  loads/persists locale preference via /api/settings/app
- src/hooks/useTranslation.ts: useTranslation() hook returning
  { locale, setLocale, t }

## Infrastructure wiring

- src/app/layout.tsx: I18nProvider wrapped inside ThemeProvider
- src/app/api/settings/app/route.ts: added "locale" to ALLOWED_KEYS
  for persistence

## Language picker

- src/components/settings/GeneralSection.tsx: added language selection
  dropdown (Select component) in Settings > General, using
  SUPPORTED_LOCALES and setLocale()

## String replacements (33 component files)

All hardcoded user-facing strings replaced with t() calls:

High priority (chat):
- ChatListPanel.tsx: session list, search, empty state, relative time
- NavRail.tsx: nav labels, theme toggle, auto-approve indicator
- MessageInput.tsx: command descriptions, mode labels, attach tooltip
- MessageList.tsx: empty state, load earlier, loading indicator
- StreamingMessage.tsx: thinking, permission actions
- chat/[id]/page.tsx: session title fallback

Settings:
- GeneralSection.tsx: update card, auto-approve section, warning dialog
- SettingsLayout.tsx: title, description, sidebar labels
- CliSettingsSection.tsx: form/json tabs, buttons, dynamic field labels
  (skipDangerousModePermissionPrompt etc.), Enabled/Disabled states
- ProviderForm.tsx: dialog title, form labels, buttons
- ProviderManager.tsx: status badges, delete dialog, section headers

Extensions:
- extensions/page.tsx: title, tab labels
- SkillsManager.tsx: empty state, loading, search
- SkillEditor.tsx: toolbar buttons, placeholder
- SkillListItem.tsx: delete confirmation
- CreateSkillDialog.tsx: form labels, scope, templates, validation

Plugins:
- McpManager.tsx: header, tabs, loading state
- McpServerList.tsx: empty state, badges, field labels
- McpServerEditor.tsx: dialog title, form labels, buttons
- ConfigEditor.tsx: save/format buttons

Layout:
- RightPanel.tsx: panel header, open/close tooltips
- FileTree.tsx: search placeholder, empty states
- FilePreview.tsx: back button, line count, copy path
- DocPreview.tsx: iframe title
- ConnectionStatus.tsx: install prompts, version display
- InstallWizard.tsx: phase descriptions, button labels
- ImportSessionDialog.tsx: search, relative time, import buttons
- FolderPicker.tsx: dialog title, loading, buttons
- TaskList.tsx: filter tabs, input placeholder, empty states
2026-02-24 16:50:57 +08:00
7418 9c13f043d0 feat: v0.11.0 — SDK settingSources, nested session fix, dynamic models, UX improvements
Core fixes:
- Add settingSources to SDK options so CodePilot loads user/project settings
  like the CLI (fixes WebFetch timeouts, tool permission issues)
- Delete CLAUDECODE env var to prevent nested session detection when
  CodePilot runs alongside Claude Code CLI (fixes 'exited with code 1')
- Remove manual MCP config reading (SDK handles it via settingSources)
- Remove hardcoded timeout env vars (SDK loads from user settings)

UX improvements:
- Remember last selected model across sessions (localStorage)
- Same-project new chat skips directory picker
- File tree auto-refreshes on project switch and after each tool completes
- Left sidebar projects default collapsed (only most recent expanded)
- Right-side file tree defaults collapsed
- Fix file tree icon alignment (spacer size-4 → size-5)
- Dynamic model list from /api/providers/models endpoint
- Provider change dispatches event to refresh model selector
- Improved error messages with provider name and troubleshooting hints
- Fix context button file type matching for extension patterns
- Default tool timeout 120s → 300s
2026-02-24 03:08:17 +08:00
7418andClaude Opus 4.6 d5b1d6eb9d feat: redesign settings page with sidebar navigation
Extract settings into General / Providers / Claude CLI sections with
a left sidebar layout. Keep Skills and MCP on the Extensions page.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 17:28:29 +08:00
7418andClaude Opus 4.6 5b69a63c06 fix: show env vars as overridden when a provider is active
When a manually configured provider is active, environment variables
are now shown with "Overridden" badge, strikethrough text, and muted
colors instead of both appearing as active simultaneously.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 10:32:37 +08:00
7418andClaude Opus 4.6 4617c71f34 fix: detect and display env var API config fallback (closes #22, closes #4)
Providers API now detects ANTHROPIC_API_KEY, ANTHROPIC_AUTH_TOKEN, and
ANTHROPIC_BASE_URL from environment. ProviderManager shows a banner
when env vars are detected, informing users they're used automatically
when no provider is active.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 20:54:10 +08:00
7418andClaude Opus 4.6 4e81eaa60b feat: fix slash commands, add badge UI, multi-provider management
Slash commands:
- Fix skills not appearing (removed non-existent `enabled` filter)
- Add badge/capsule UI for prompt-type commands (/compact, /review, etc.)
- SDK-native commands sent directly; CLI-only commands expanded to prompts
- /clear now resets SDK session and clears database messages
- /cost shows actual aggregated token usage statistics
- Keyboard: Backspace/Escape to remove badge, arrow keys auto-scroll popover
- Add /memory command for editing CLAUDE.md

Multi-provider management:
- CRUD API for API providers with SQLite storage
- ProviderManager UI with quick presets (GLM, Kimi, MiniMax, etc.)
- Dynamic model labels based on active provider
- Environment variable injection with conflict resolution

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 20:03:18 +08:00