Add safety rules for git worktree workflows:
- Changes scoped to worktree only
- No cross-worktree commits or push
- Port isolation for dev server
- No cross-directory file edits
- Check untracked files before merge
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Feishu card button clicks:
- Add encryptKey/verificationToken to FeishuConfig for EventDispatcher
- Gateway monkey-patch: rewrite type="card" → "event" for WSClient
- Gateway safeCardActionHandler: 2.5s timeout guarantee with fallback toast
- Embed chatId in button value (Feishu card.action.trigger has no open_chat_id)
- Support both callback_data and action/operation_id button value formats
- Domain resolution: 'feishu' → Domain.Feishu, 'lark' → Domain.Lark
Bridge reliability:
- Clear sessionLocks and activeTasks on bridge stop() to prevent
stuck sessions after restart (processWithSessionLock chains to
unresolved promises from previous bridge lifecycle)
Settings UI:
- Add encryptKey and verificationToken fields to Feishu settings
- Mask encryptKey in GET, skip masked values in PUT
- Add i18n strings (marked as optional for WSClient mode)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Windows installers create multiple entry points in the same directory
(e.g. claude.exe + claude, claude.cmd + claude). These are variants for
different shells, not separate installations. Deduplicate by directory +
base name stripped of executable extensions (.exe/.cmd/.bat).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- installation.mdx: expand "First Launch" into detailed Setup Center walkthrough
covering CLI detection, provider configuration, and project directory setup
- installation.mdx: add "Claude Code Conflicts" section with detection logic,
uninstall commands per install type, and recommended installation method
- faq.mdx: add troubleshooting entries for CLI not detected, multi-version
conflicts, and Setup Center auto-open behavior
- providers.mdx: mention ANTHROPIC_AUTH_TOKEN alongside API_KEY for env detection
All changes in both English and Chinese versions.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add a skippable first-use Setup Center that guides users through three
prerequisites: Claude Code CLI detection, API provider configuration,
and default project directory selection. Replace passive fail-then-hint
patterns with proactive guidance and actionable error recovery.
Setup Center (13 new files):
- SetupCenter overlay with 4 cards (Welcome, ClaudeCode, Provider, ProjectDir)
- Auto-close only when user completes last card in current session
- Re-openable from Settings > General > "首次设置引导"
- Claude Code conflict detection with per-install-type uninstall commands
- Provider detection covers DB providers, env vars, and legacy app-settings token
- ANTHROPIC_BASE_URL excluded from credential check (not a real credential)
- skipped != completed: /chat still prompts for provider after skip
Project directory:
- Validation via /api/files/browse before trusting saved paths
- Fallback chain: localStorage → setup_default_project → empty state
- Cross-component sync via project-directory-changed CustomEvent
Toast system:
- Global showToast() API with success/error/warning/info types
- FIFO eviction (max 3), action button support
Git panel:
- Move Commit + Push buttons from UnifiedTopBar into GitStatusSection
- Push enabled for new branches (backend auto-handles -u origin)
Other:
- Windows top-bar safe zone (138px spacer for caption buttons)
- Cross-platform path splitting with /[\\/]/ regex
- Platform-aware file manager name (Finder/Explorer/Files)
- ~80 new i18n keys (en + zh)
- Handover doc: docs/handover/onboarding-setup-center.md
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Root cause: esbuild 0.27.3 misparses `node-pty` inside JSDoc comments as a
code expression `node - pty` (subtraction). This produces a bare
`ReferenceError: node is not defined` at app.asar/dist-electron/main.js:35
on startup.
Fixes:
- terminal-manager.ts: replace JSDoc block with line comments and remove all
literal `node-pty` strings (reference docs/handover instead)
- build-electron.mjs: clean dist-electron/ before every build to prevent
stale artifact contamination in app.asar
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- provider-catalog: getDefaultModelsForProvider() now returns preset's
defaultModels even when empty, instead of falling through to
ANTHROPIC_DEFAULT_MODELS. Fixes Volcengine (defaultModels: []) incorrectly
showing Sonnet/Opus/Haiku.
- providers/models route: remove DEFAULT_MODELS fallback when both DB and
catalog are empty — providers like Volcengine that require user-specified
model names should show only those models.
- Add missing src/app/api/chat/sessions/by-cwd/route.ts that was untracked;
without it worktree switching would 404 in release builds.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Assistant trigger CAS (P1):
- hook-triggered route: added expectedOwner param for compare-and-swap —
rejects if current owner doesn't match, closing the race where two tabs
both clear then both claim the lock
- useAssistantTrigger: clear sends expectedOwner (stale session), set sends
expectedOwner: null; non-2xx responses now bail instead of falling through
- Server-side completion (chat/route.ts): only clears lock if owner matches
current sessionId, preventing completed sessions from wiping active locks
- Compensation branch: clear now passes expectedOwner to avoid bypassing CAS
Image-gen LIKE escape (P2):
- db.ts: escape backslashes before % and _ since ESCAPE '\' makes \ the
escape char — prevents Windows paths / escaped JSON from corrupting the
LIKE pattern and silently falling back to prompt-prefix matching
Provider options fetch race (P2):
- page.tsx + ChatView.tsx: provider options fetch now uses AbortController
with cleanup on dependency change — prevents stale slow responses from
overwriting the current provider's thinking/context_1m state
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- New plugin-discovery.ts: scans ~/.claude/plugins/marketplaces/ and
external_plugins/, reads .claude-plugin/plugin.json manifests, merges
enabledPlugins across user/project/local settings layers with write
escalation to local when higher layers override
- Rewrite /api/plugins and /api/plugins/[id] to use real plugin manifests
with name@marketplace composite keys, blocklist, and multi-layer
enable/disable with CAS-style write escalation
- SDK plugin loading delegated to SDK itself (no explicit queryOptions.plugins)
— ensures parity with Claude CLI's settingSources resolution
- Extended init meta forwarding (plugins, mcp_servers, output_style) in
claude-client.ts and useSSEStream.ts
- Per-provider plugin cache in agent-sdk-capabilities.ts with
getCachedPlugins/setCachedPlugins
- Skills route: provider-scoped plugin cache lookup via sessionId param,
external_plugins commands scan, loaded status annotation
- Updated PluginInfo type with marketplace, location, author, capability flags
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Rewrite install-check-prerequisites with multi-path Claude CLI detection
(native, bun, homebrew, npm) and structured result reporting
- Improve InstallWizard with step-by-step progress and better error handling
- Enhance ConnectionStatus with detailed status display and invalidation
- Add /api/claude-status/invalidate route for cache-busting
- Expand platform.ts with richer detection utilities
- Add onInitMeta handler in stream-session-manager
- Update electron.d.ts types for new IPC channels
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace fixed-timeout stale detection with localStorage heartbeat mechanism
- Heartbeat writes {sid, ts} every 10s; isOwnerAlive checks sid matches AND freshness
- Stop heartbeat when triggered stream completes (useEffect on !isStreaming)
- removeHeartbeatIfOwned: only delete key if it still belongs to this session
(prevents new owner's heartbeat from being wiped by old session's cleanup)
- Export clearOnboardingHeartbeat with optional sessionId parameter
- hook-triggered route sets/clears hookTriggeredAt alongside hookTriggeredSessionId
- MiniMax model auto-correction: reset model when not in current provider's list
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Image reference store session-scoped:
- Rewrite image-ref-store.ts: all keys/functions now scoped by sessionId
- Thread sessionId through MessageList → StreamingMessage/MessageItem → ImageGenConfirmation
- ChatView loads last-generated images for current session on mount
Image write-back robustness:
- Remove localStorage caching from ImageGenConfirmation (root cause of stale results)
- Add rawRequestBlock for exact content matching in DB fallback query
- updateMessageBySessionAndHint prefers exact block match, falls back to prompt hint
- PUT route passes raw_request_block to DB function
- Add retry-after-3s when first PUT fails and no messageId available
- Exclude already-completed messages (NOT LIKE image-gen-result) from update query
New session page (/chat) fix:
- Add createdSessionId state, set after session creation, pass to MessageList
- Prevents first-message image-gen-request from inheriting stale panel sessionId
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add ProviderOptionsSection component for per-provider thinking_mode and context_1m
- Store options in options_json column (DB providers) or settings table (env provider)
- Add /api/providers/options GET/PUT route
- Fix SDK integration: use `betas` (not `betaHeaders`) for context-1m-2025-08-07
- ChatView and /chat page always reset thinkingMode on provider change (isolation fix)
- Auto-correct model when switching providers if model not in new provider's list
- Add i18n keys for provider options in both en.ts and zh.ts
- Update test fixtures with options_json field
- Remove unused lastAssistantText variable in claude-client.ts
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extract 4 self-contained sub-components from MessageInput.tsx:
- SlashCommandPopover (243L): slash command filtering, rendering, selection
- CliToolsPopover (128L): CLI tool selection with search/filter
- ModelSelectorDropdown (150L): provider/model selector dropdown
- EffortSelectorDropdown (75L): thinking effort level selector
All components have clean props interfaces ready for integration.
MessageInput.tsx wiring deferred to follow-up — the file's 1,659 lines
of tightly coupled state make this a careful, incremental process.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Merge chat/CodeBlock.tsx (Prism via react-syntax-highlighter) into
ai-elements/code-block.tsx (Shiki):
- Port collapse/expand (COLLAPSE_THRESHOLD=20, VISIBLE_LINES=10) from Prism version
- Port InlineCode component export
- Port "Copy as Markdown" functionality
- Update ToolCallBlock.tsx import to use ai-elements/code-block
- Delete src/components/chat/CodeBlock.tsx
Note: react-syntax-highlighter still used by DocPreview and FilePreview,
so dependency not removed yet.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New hooks:
- useSettings: generic settings CRUD (fetch/save with loading/saving states)
- useBridgeAdapter: bridge adapter settings + verify flow
- useBridgeStatus: bridge status polling + start/stop control
- useAccountInfo: Claude SDK account info fetching
Refactored components:
- GeneralSection: replace inline fetchAccountInfo with useAccountInfo hook
- BridgeSection: replace inline fetchStatus/startBridge/stopBridge + polling
interval with useBridgeStatus hook (removed ~50 lines)
The remaining bridge adapter sections (Telegram/Discord/Feishu/QQ) can be
migrated to useBridgeAdapter in a follow-up — hooks are ready for adoption.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Create src/components/patterns/ with 6 pure-presentation components
that abstract repeated layout patterns from settings/bridge pages:
- SettingsCard: rounded card with optional title/description
- FieldRow: label+description left, control right, optional separator
- SectionPage: max-width page container with consistent spacing
- StatusBanner: success/warning/error/info inline status messages
- EmptyState: centered empty state with icon, title, description, action
- IconAction: ghost icon button with optional tooltip wrapper
All components are zero-side-effect, only import from React and @/lib/utils
(plus ui/button and ui/tooltip for IconAction).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add .editorconfig for consistent formatting (2-space indent, LF, UTF-8)
- Add docs/ui-governance.md defining 4-layer architecture, icon strategy,
color token rules, component size limits, and new primitive approval flow
- Update eslint.config.mjs with governance rules:
- warn on native <button/input/select/textarea> in business components
- warn on lucide-react imports (prefer @phosphor-icons/react)
- warn on component files exceeding 500 lines
- error on data logic imports in patterns/ layer
- Update components.json iconLibrary from "hugeicons" to "phosphor"
Note: 4 pre-existing test failures (assistant-workspace, db-shutdown,
provider-resolver, timezone-boundaries) unrelated to this change.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The bg-[var(--user-bubble)] arbitrary value syntax wasn't working with
Tailwind v4's Lightning CSS pipeline. Switch to bg-(--user-bubble) which
is Tailwind v4's native CSS variable reference syntax.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
File tree "+" button (Bug 1):
- Replace fragile fetch/blob attachment bridge with @filepath text insertion
- Works identically on web and Electron (pure text, no /api/files/raw fetch)
- Remove unused mimeFromFilename helper
Model selection follows session (Bug 2):
- page.tsx: include model/provider_id in session creation request
- [id]/page.tsx: add sessionInfoLoaded gate — ChatView only mounts after
session metadata is fetched, preventing stale localStorage fallback
- SplitColumn.tsx: same sessionInfoLoaded gate for split-pane mode
- ChatView.tsx: useEffect sync only overrides model/provider when props
are non-empty; empty = genuinely no model saved (old/imported sessions)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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>
Link to codepilot.sh docs (en + zh) for Providers, MCP, Skills,
Bridge, Assistant Workspace, Installation, and FAQ.
Updated English, Chinese, and Japanese READMEs.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- 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>
- RainbowButton: dark mode text white→dark for contrast on white bg
- DownloadButton: dark mode invert to white bg + dark text
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>