Commit Graph
18 Commits
Author SHA1 Message Date
7418andClaude Opus 4.6 ad34fe387b chore: 禁用 native auto-updater,改为引导用户从 GitHub 下载
macOS 上 ad-hoc 签名无法通过 ShipIt 的 kSecCSStrictValidate 校验,
导致热更新始终失败。在获取 Apple 开发者证书之前,暂时禁用 native
auto-updater,改为 browser-mode 检查 GitHub Releases API:

- electron/updater.ts: 注释掉 electron-updater 逻辑,initAutoUpdater
  和 setUpdaterWindow 改为 no-op
- electron/preload.ts: 注释掉 updater IPC bridge,前端不再暴露
  window.electronAPI.updater
- AppShell.tsx: isNativeUpdater 硬编码为 false,移除 native IPC 订阅
  和 native check/download/quitAndInstall 逻辑;保留 browser-mode
  的 GitHub API 检查(mount 时 + 每 8 小时),发现新版本时弹窗引导
  用户跳转 GitHub Release 页面下载

设置页 UpdateCard 保持不变:「检查更新」按钮通过 /api/app/updates
查询 GitHub,有新版本时显示「查看发布」按钮跳转下载。

TODO: 获取 Apple 开发者证书后,取消注释恢复 native auto-updater。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 11:45:36 +08:00
7418andClaude Opus 4.6 4f4ba5f8eb feat: 聊天分屏功能 — 支持多会话并排查看
新增聊天分屏功能,允许同时查看和操作多个聊天会话:

新增文件:
- src/hooks/useSplit.ts: SplitContext 和 useSplit hook,管理分屏会话列表、
  活跃列、添加/移除/退出分屏等操作,状态通过 localStorage 持久化
- src/components/layout/SplitColumn.tsx: 单个分屏列组件,独立加载会话元数据
  和消息,渲染紧凑标题栏 + ChatView,活跃列蓝色描边并同步 PanelContext
- src/components/layout/SplitChatContainer.tsx: 分屏容器,并排渲染多个
  SplitColumn,列间以 1px 分隔线分隔

修改文件:
- AppShell.tsx: 新增分屏状态管理(splitSessions/activeColumnId),包裹
  SplitContext.Provider,分屏激活时渲染 SplitChatContainer 替代路由页面,
  URL 与活跃列同步,离开聊天路由自动退出分屏
- ChatListPanel.tsx: 聊天卡片 hover 交互重构 — 移除模式徽章(Code/Plan),
  左侧 indent 区域 hover 显示分屏图标(点击将该会话加入分屏),右侧时间区域
  hover 切换为删除图标;分屏激活时列表顶部显示灰色描边分屏组卡片,分屏中的
  会话从常规列表过滤掉;所有元素始终存在于 DOM 中通过 opacity 切换,避免
  hover 时布局跳动
- en.ts / zh.ts: 新增 split.splitScreen、split.closeSplit、
  split.splitGroup、chatList.splitScreen 翻译

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 01:13:19 +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 54515e1cec feat: stream session manager + always show Claude Code built-in models, bump v0.17.4
Stream Session Manager — 切换会话不中断流:

- src/lib/stream-session-manager.ts(新建): 全局单例管理所有 SSE 流,
  使用 globalThis 模式(同 conversation-registry.ts)保证 HMR 不丢状态。
  管理 AbortController、idle timeout (330s)、tool timeout 自动重试、
  5 分钟 GC,所有 SSE 回调写入 snapshot 并 emit 事件给订阅者。
  导出 startStream / stopStream / subscribe / getSnapshot /
  respondToPermission / clearSnapshot 等 API。

- src/types/index.ts: 新增 ToolUseInfo、ToolResultInfo(从 ChatView 提取)、
  StreamPhase、SessionStreamSnapshot、StreamEvent、StreamEventListener 类型,
  作为管理器与 ChatView 之间的数据契约。

- src/components/chat/ChatView.tsx(重构): 删除 abortControllerRef 及
  unmount abort effect(此前切换会话的根因)、整个 fetch/SSE 逻辑约 280 行、
  accumulatedRef/toolUsesRef/toolResultsRef/beforeunload handler。
  改为 subscribe() + getSnapshot() 订阅模式,unmount 仅 unsubscribe
  不 abort,mount 时通过 getSnapshot 恢复进行中的流状态。
  sendMessage / stopStreaming / handlePermissionResponse 全部委托管理器。

- src/hooks/usePanel.ts: PanelContextValue 新增
  activeStreamingSessions: Set<string> 和
  pendingApprovalSessionIds: Set<string>,支持多会话并发流指示。

- src/components/layout/AppShell.tsx: 监听 stream-session-event 窗口事件
  更新 activeStreamingSessions / pendingApprovalSessionIds Set 状态;
  将 beforeunload handler 从 ChatView 移至此处(全局感知所有流)。

- src/components/layout/ChatListPanel.tsx: 侧栏流指示器改用
  activeStreamingSessions.has() / pendingApprovalSessionIds.has(),
  支持同时显示多个会话的流/审批状态。

模型选择器始终显示 Claude Code 内置模型:

- src/app/api/providers/models/route.ts: 移除 hasEnvKey 环境变量检测条件,
  始终显示 "Claude Code" provider 组(Sonnet 4.6 / Opus 4.6 / Haiku 4.5)。
  根因:Claude Code CLI 通过 `claude login` 存储凭证在 ~/.claude/ 下,
  SDK 子进程可以读取,但 Next.js 进程的 process.env 中没有对应变量,
  导致之前的 hasEnvKey 检测失败时模型选择器不显示内置模型。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 13:58:30 +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 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
歸藏 cd807ef175 Merge pull request #49 from cyxer000/feat/error-boundary
Error Boundary for crash isolation. Minor fixes (i18n, icon, h-5 conflict) will follow.
2026-02-26 10:23:24 +08:00
7418 85940dfde3 fix: align title bar headers across panels, fix macOS Dock icon size
Title bar alignment (AppShell.tsx, page.tsx, DocPreview.tsx):
- Reduce AppShell draggable spacer from h-11 to h-5 to match side panels' mt-5
- Chat title bar uses normal flow h-12 instead of absolute positioning hack
- DocPreview header changed from h-10 to h-12 mt-5
- All three columns now align at the same vertical position

macOS Dock icon (build/icon.png, build/icon.icns):
- Add 100px transparent padding on all sides (content 824x824 in 1024x1024 canvas)
- Follows Apple Human Interface Guidelines for macOS app icons
- Regenerated icon.icns with all required sizes
- Original icon backed up as icon-original.png

Remove start execution button (ChatView.tsx):
- Remove showStartExecution logic and handleStartExecution callback
- Mode switching is now handled automatically by SDK
2026-02-24 15:30:42 +08:00
cyxer000 11ece8df88 feat: add React Error Boundary to prevent UI white-screen crashes
Wrap main content area and chat list panel with ErrorBoundary
components to gracefully handle runtime errors instead of
showing a blank white screen.

Closes #32
2026-02-24 11:12:53 +08:00
7418andClaude Opus 4.6 e86f0cfd8f perf: optimize polling with caching and event-driven approach (P1-2)
- CLI binary detection cached with 60s TTL
- Settings poll replaced with visibility/focus events
- Health check uses adaptive backoff (30s → 60s when stable)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 01:24:43 +08:00
7418andClaude Opus 4.6 8747464c2f fix: doc preview bugs — close on chat switch, copy content, filter binary files
- Close doc preview when switching between chats (pathname change)
- Copy button now copies file content instead of file path
- Skip preview for images, videos, audio, archives, and other binary files

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 23:26:29 +08:00
7418andClaude Opus 4.6 8c6e7bba5b feat: add doc preview panel for HTML and Markdown files
Click files in the file tree to open a dedicated preview panel with
source/rendered toggle for .md/.mdx/.html/.htm files. Preview panel
supports drag-to-resize (320–800px) with localStorage persistence.

Bump version to 0.9.0.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 13:50:21 +08:00
7418andClaude Opus 4.6 da07f1bd1b feat: draggable panel resize handles and remove extensions divider
Add ResizeHandle component for drag-to-resize side panels.
ChatListPanel (180–400px) and RightPanel (200–480px) widths
are persisted via localStorage. Also remove the border line
below the Extensions page tab selector.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 12:57:37 +08:00
7418andClaude Opus 4.6 74fb784f6d feat: auto update check and dangerously-skip-permissions mode
Add automatic update detection (checks GitHub Releases every 8h with
dialog prompt and blue dot on Settings icon) and a skip-permissions
toggle in Settings that uses the SDK's native bypassPermissions mode
to auto-approve all tool actions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 23:14:42 +08:00
7418andClaude Opus 4.6 ff1fb38735 feat: CodePilot - desktop GUI for Claude Code
Full-featured desktop application built with Next.js + Electron:
- Streaming chat with Claude Code via Agent SDK
- Session management with SQLite persistence
- Project file tree and file preview
- MCP server and custom skills management
- Permission controls with Code/Plan/Ask modes
- Dark/light theme, token tracking
- macOS DMG packaging with electron-builder

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 21:04:05 +08:00