162 Commits

Author SHA1 Message Date
程序员阿江(Relakkes)
039ad8afd7 feat(skills): add server API, types, client, store, and i18n
- Server: GET /api/skills (list) and GET /api/skills/detail (tree + files)
- Desktop: type definitions, API client, Zustand store
- i18n: EN/ZH translation keys for Skills tab

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 11:30:16 +08:00
程序员阿江(Relakkes)
9bb05adc74 docs: add Skills UI design spec and implementation plan
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 11:18:08 +08:00
程序员阿江(Relakkes)
2c19bb77ac feat: add tab drag-to-reorder and complete context menu actions
- Tab drag-and-drop reordering with visual drop indicator
- Add moveTab action to tabStore with localStorage persistence
- Context menu: add "Close Left" and "Close All" options
- Add i18n translations for new menu items (en/zh)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 10:45:28 +08:00
程序员阿江(Relakkes)
5c4a1e8994 style: improve TabBar visual design and Settings sidebar alignment
- TabBar: darker background (surface-container), active tab uses top brand
  accent + lighter bg, consistent bottom border, draggable empty area
- Settings sidebar width matches TAB_WIDTH (180px) for vertical alignment
- Remove rounded corners and side borders from tabs for cleaner look

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 10:26:38 +08:00
程序员阿江(Relakkes)
e249c7ab76 fix: eliminate top gap by removing global drag overlay
The 38px absolute drag overlay was blocking tab clicks, requiring
padding that created a visible gap. Sidebar already handles its own
drag region, and TabBar uses data-tauri-drag-region directly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 09:21:45 +08:00
程序员阿江(Relakkes)
ed7b0b2629 fix: remove top gap and redundant StatusBar in desktop app
- Move Tauri title bar padding into TabBar instead of main container,
  eliminating the double spacing (38px gap + 36px tab bar)
- Remove StatusBar entirely (project/model info already in ChatInput)
- TabBar renders a drag region spacer even when no tabs are open

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 08:53:17 +08:00
程序员阿江(Relakkes)
a16eae3871 fix: remove unused AppShell import in test file
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 01:30:02 +08:00
程序员阿江(Relakkes)
7e2c8803f7 feat: unify Settings/Scheduled as tab pages, improve new session UX
- Settings and Scheduled Tasks now open as special tabs in the TabBar,
  matching IDE conventions (closeable, icon-prefixed, persistent)
- New Session directly creates a session with the current workDir
- ChatInput shows DirectoryPicker before first message, locks after
- Remove connection status from StatusBar (unnecessary noise)
- ContentRouter routes by tab type instead of activeView
- Settings page no longer has a back-button header

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 01:19:02 +08:00
程序员阿江(Relakkes)
f2fa6fc56d chore: gitignore .claude and docs/superpowers, clean up temp files
Remove .claude/ and docs/superpowers/ from git tracking as they are
local-only config and planning files. Also remove stale screenshots
and update docs/channel content.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 00:50:43 +08:00
程序员阿江(Relakkes)
db19491fc8 feat: add multi-tab sessions for desktop app
Support multiple concurrent sessions in the desktop webapp with VS Code-style tabs.
Each tab maintains its own independent WebSocket connection and message state.

Key changes:
- WebSocket manager: singleton → multi-connection Map
- chatStore: flat state → per-session isolated state
- New tabStore with localStorage persistence
- TabBar component with scroll overflow and context menu
- Sidebar/EmptySession integrated with tab system

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 00:48:04 +08:00
程序员阿江(Relakkes)
942df9d362 fix: update tests for multi-tab architecture
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 00:46:25 +08:00
程序员阿江(Relakkes)
9bfbadd170 fix: resolve TypeScript compilation errors in multi-tab refactor
Update all components, hooks, and tests to use the new per-session
chatStore API where state is keyed by sessionId under `sessions` and
all action methods require sessionId as the first parameter.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 00:42:18 +08:00
程序员阿江(Relakkes)
e462314100 feat: MessageList and ChatInput read from per-session state
Both components now look up state via activeTabId from useTabStore,
reading from sessions[activeTabId] in chatStore. Action calls
(sendMessage, stopGeneration) pass the sessionId as first argument.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 00:34:58 +08:00
程序员阿江(Relakkes)
f883208810 feat: sync tab status and title from server messages
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 00:34:44 +08:00
程序员阿江(Relakkes)
3ef1fff2b4 feat: ActiveSession reads from tabStore and per-session chatStore
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 00:33:32 +08:00
程序员阿江(Relakkes)
5daf49da9b feat: new session creation automatically opens as tab
Add useTabStore.openTab call after session creation so new sessions are
registered as tabs, and update sendMessage to pass sessionId as first arg.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 00:33:23 +08:00
程序员阿江(Relakkes)
8f0bbf0817 feat: integrate TabBar into AppShell layout and route by activeTabId
- Add TabBar, useTabStore, useChatStore imports to AppShell
- Restore tabs from localStorage during bootstrap and connect active session
- Render <TabBar /> before <ContentRouter /> in the main content area
- Replace useSessionStore/activeSessionId with useTabStore/activeTabId in ContentRouter

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 00:33:21 +08:00
程序员阿江(Relakkes)
e3accc4068 feat: sidebar click opens session in tab instead of replacing
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 00:33:13 +08:00
程序员阿江(Relakkes)
e43a0baa08 feat: add i18n translations for multi-tab feature
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 00:32:11 +08:00
程序员阿江(Relakkes)
9908c17b85 feat: add TabBar component with scroll overflow and context menu
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 00:31:58 +08:00
程序员阿江(Relakkes)
df288fe239 feat: add tabStore for multi-tab state management
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 00:31:08 +08:00
程序员阿江(Relakkes)
9dc2294954 refactor: chatStore supports per-session isolated state
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 00:30:05 +08:00
程序员阿江(Relakkes)
c056b3c4fd docs: add multi-tab sessions implementation plan
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 00:28:27 +08:00
程序员阿江(Relakkes)
3d04aa4c45 docs: add multi-tab sessions design spec
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 00:28:27 +08:00
程序员阿江(Relakkes)
2b21acf259 refactor: websocket manager supports multiple concurrent connections
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 00:23:30 +08:00
程序员阿江(Relakkes)
91b4d16dc5 Restore sub-agent context in the desktop chat transcript
The desktop chat view flattened Agent tool activity, which made sub-agent work
hard to follow and separated key evidence from the main conversation. This
change threads parent tool linkage through the server bridge and desktop store,
renders dispatched sub-agents as grouped cards with nested tool activity, and
moves long final outputs into a markdown preview dialog so the main transcript
stays readable on narrow layouts.

Constraint: Existing sessions and live websocket events both needed to preserve parent-child relationships
Rejected: Add brand-new subagent websocket event types | unnecessary protocol expansion when parent linkage already existed upstream
Rejected: Inline full sub-agent markdown in the card body | too cramped for narrow desktop chat layouts
Confidence: medium
Scope-risk: moderate
Reversibility: clean
Directive: Keep Agent card summaries compact; route long-form sub-agent output through the preview dialog unless the main chat layout is widened substantially
Tested: cd desktop && bun run test -- MessageList.test.tsx chatStore.test.ts
Tested: cd desktop && bun run lint
Tested: bun test src/server/__tests__/sessions.test.ts -t should\ reconstruct\ parent\ agent\ tool\ linkage\ from\ parentUuid\ chains
Not-tested: Full end-to-end visual verification against live CLI sessions with sub-agent text/thinking nested inline
2026-04-09 00:04:40 +08:00
程序员阿江(Relakkes)
bfd2405857 fix: disable run-now button for disabled scheduled tasks
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 23:29:30 +08:00
程序员阿江(Relakkes)
ce92de29f0 fix: prevent transient scheduled task write failures
Cron task metadata writes can overlap closely enough that a timestamp-only
$temp filename is not stable. Harden the atomic write path by using a
collision-resistant temp name and retrying once when rename reports ENOENT.

Constraint: Scheduled task persistence must keep atomic replace semantics in ~/.claude/scheduled_tasks.json
Rejected: Add explicit file locking around every scheduled task write | more coordination overhead than the observed transient rename race warrants
Confidence: high
Scope-risk: narrow
Directive: Keep scheduled task writes collision-resistant and retriable; do not revert to timestamp-only temp file names without reproducing concurrent writes
Tested: bun test src/server/__tests__/scheduled-tasks.test.ts
Not-tested: bun test src/server/__tests__/cron-scheduler.test.ts (existing timeouts and unrelated assertion failures in this checkout)
2026-04-08 23:21:28 +08:00
程序员阿江(Relakkes)
3c5290eec1 fix: reduce copy ambiguity in chat sessions
The session view exposed copy affordances in a way that implied the
whole conversation would be copied, while user prompts had no copy
path at all. This changes copy to a per-message footer action so the
scope is explicit for both prompts and assistant replies, and reuses
the shared clipboard helper instead of maintaining a second copy path.

Constraint: The worktree contains unrelated in-progress changes that must stay uncommitted
Rejected: Keep a floating action above each message | it interrupted reading order and still looked session-scoped
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep copy affordances attached to individual message blocks so the copied scope stays obvious
Tested: bun run test src/components/chat/MessageList.test.tsx; bun run lint
Not-tested: Manual desktop visual QA across dense multi-message sessions
2026-04-08 23:19:31 +08:00
程序员阿江(Relakkes)
90b5772fb4 fix: default to user home dir when no workDir selected on new session
Previously, creating a new session without selecting a project directory
defaulted to process.cwd(), which in the desktop app resolves to the app
installation path. Now it defaults to os.homedir().

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 21:40:05 +08:00
程序员阿江(Relakkes)
6aedd6eb53 fix: prevent cross-process duplicate execution of scheduled tasks
三层防护:内存 minuteKey 去重、文件 lastFiredAt 跨进程去重、启动时清理僵尸 running 条目。
将 updateLastFired 从任务完成后移至启动时,让其他调度器进程尽早感知。
2026-04-08 21:14:18 +08:00
程序员阿江(Relakkes)
00a9cba066 fix: enable macOS window dragging and rename app to Claude Code Haha
Add core🪟allow-start-dragging permission and acceptFirstMouse
config to fix window dragging on macOS with overlay title bar. Also add
JS-based startDragging() fallback in AppShell and Sidebar.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 21:11:26 +08:00
程序员阿江(Relakkes)
158f2de13e fix(security): add rate limiting, default-closed mode, extract isAllowedUser
- Rate limit: max 5 failed pairing attempts per user per 5 minutes
- Default closed: reject all users when no allowedUsers/pairedUsers configured
- Extract isAllowedUser() to common/pairing.ts to eliminate duplication

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 20:51:30 +08:00
程序员阿江(Relakkes)
bf5cd6e3b8 fix(security): eliminate modulo bias in pairing code generation
Use rejection sampling to ensure uniform distribution across the
safe alphabet. Values >= 232 are rejected and resampled.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 20:50:54 +08:00
程序员阿江(Relakkes)
9fc2d5a12f fix(security): fully mask pairing code in API response - prevent information leakage
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 20:50:20 +08:00
程序员阿江(Relakkes)
12cc872150 feat: auto-generate session titles using AI (Haiku model)
After the first assistant response, derive a quick placeholder title from
the user message, then asynchronously call the provider's Haiku model to
generate a polished 3-7 word title. Titles update again at message 3 with
fuller conversation context. Updates push to frontend in real-time via
WebSocket `session_title_updated` event.

- extractTitle now reads `ai-title` JSONL entries (priority: custom > ai > first message)
- New titleService with deriveTitle + generateTitle using active provider config
- Handler tracks per-session message count and triggers generation on result
- Frontend sessionStore receives live title updates for sidebar + header

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 20:48:48 +08:00
程序员阿江(Relakkes)
2523ce0cd7 feat(pairing): add pairing management UI to AdapterSettings page
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 20:12:13 +08:00
程序员阿江(Relakkes)
14a8322355 feat(pairing): add server-side pairing code masking and merge support
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 20:10:24 +08:00
程序员阿江(Relakkes)
4e66ef10c7 feat(pairing): add generatePairingCode and removePairedUser to adapter store
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 20:10:22 +08:00
程序员阿江(Relakkes)
5fe7542160 fix: prevent duplicate concurrent executions of the same scheduled task
executeTask() lacked a runningTasks guard, so manual "Run Now" or
server restarts could spawn a second subprocess while one was already
running. Now checks runningTasks at entry and skips if already in flight.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 20:09:32 +08:00
程序员阿江(Relakkes)
d9905c78fd feat(pairing): integrate pairing check into telegram adapter - private chat only
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 20:09:11 +08:00
程序员阿江(Relakkes)
74cf078ed3 feat(pairing): integrate pairing check into feishu adapter - DM only
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 20:08:52 +08:00
程序员阿江(Relakkes)
4bcac9d25f feat(pairing): implement core pairing logic module
Add adapters/common/pairing.ts with generatePairingCode(), isPaired(),
and tryPair() — one-time-use 6-char code flow with atomic config writes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 20:07:44 +08:00
程序员阿江(Relakkes)
88e7e14598 feat(pairing): extend type definitions with pairing and pairedUsers fields
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 20:06:37 +08:00
程序员阿江(Relakkes)
be2e9acdaa chore: update .gitignore to exclude temp screenshots and build artifacts
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 19:50:46 +08:00
程序员阿江(Relakkes)
82e6e27687 feat: add IM adapter integration (Telegram + Feishu) with web settings UI
Implement IM adapters allowing users to chat with Claude Code from Telegram
and Feishu/Lark. Includes persistent session management (chatId→sessionId
mapping), project selection via /projects command, and a web UI settings page
for configuring bot tokens, allowed users, and default project directory.

Key changes:
- adapters/: Telegram and Feishu adapter scripts with shared common modules
  (WsBridge, MessageBuffer, SessionStore, HttpClient, config, formatting)
- Backend: adapterService + REST API (GET/PUT /api/adapters) with secret masking
- Frontend: AdapterSettings page in Settings tab with i18n support
- DirectoryPicker: use React Portal for dropdown to fix overflow clipping

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 19:38:51 +08:00
程序员阿江(Relakkes)
983d83f86b feat: enhance scheduled tasks with flexible scheduling, run now, execution logs, and edit support
- Add 7 frequency modes (every N min/hours, daily, weekdays, specific days, monthly, custom cron) with progressive disclosure UI
- Add "Run Now" button with confirmation popover and fire-and-forget API
- Add execution logs panel (TaskRunsPanel) with auto-polling and accordion behavior
- Add task edit mode with cron reverse-parsing (parseCron) to populate form
- Add server-side extractAssistantText to store meaningful AI responses instead of raw NDJSON
- Fix session linking: pass --session-id to CLI subprocess so "View conversation" navigates to actual content
- Fix MACRO undefined error by adding --preload to Bun.spawn
- Add confirmation popovers for all destructive actions (run/disable/delete)
- Add DayOfWeekPicker component for specific-days scheduling
- Add cronDescribe utility with i18n support and unit tests
- Display task creation time and last run time
- Add ~50 i18n keys (en/zh) for all new UI elements

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 17:40:13 +08:00
程序员阿江(Relakkes)
41fb22790a feat: self-host fonts to eliminate Google CDN dependency
Replace Google Fonts CDN links with locally hosted woff2 files to avoid
FOUT/FOIT on slow networks and ensure the app works in regions where
Google is blocked. Material Symbols uses font-display: block to prevent
raw icon text from flashing on load.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 22:30:18 +08:00
程序员阿江(Relakkes)
b5d970dc8d fix: translate prompt placeholder in new task modal 2026-04-07 22:26:48 +08:00
程序员阿江(Relakkes)
5a8fb8ad4e feat: add i18n to ScheduledTasks page
Translate the scheduled tasks header, subtitle, desktop notice,
and new task button that were missed in the initial i18n pass.
2026-04-07 22:23:48 +08:00