Commit Graph

202 Commits

Author SHA1 Message Date
ZhenYi
e185885557 fix(react): switch namespace import to default import to fix stale Vite CJS interop
- 3 files: theme-provider, carousel, sidebar
- index.html: set title to GitData.AI, favicon to /logo.png
- add public/logo.png and robots.txt
2026-05-12 22:03:54 +08:00
ZhenYi
033cfda6c5 feat: add explore page and AI elements components 2026-05-12 13:07:58 +08:00
ZhenYi
d63ca39ca4 refactor(layout): update layout components, header, navigation and API client 2026-05-12 13:06:19 +08:00
ZhenYi
e86803d235 refactor(ui): update UI components, theme system and utilities 2026-05-12 13:05:28 +08:00
ZhenYi
b384f92bbf refactor(chat): update frontend chat components 2026-05-12 13:05:20 +08:00
ZhenYi
ac9ffb2a7a feat(frontend): update UI components, skill pages, and hooks
Refactor ChatMessageList, ChannelSidebar, and skill detail/pages.
Add CreateSkillDialog and DeleteSkillDialog. Update MarkdownRenderer,
use-mobile hook, and useSkillsQuery.
2026-05-11 17:06:13 +08:00
ZhenYi
f082429a58 feat(core): initialize project with access control and AI integration 2026-05-10 22:52:16 +08:00
ZhenYi
ba2490dab4 feat(core): initialize project with access control and AI integration 2026-05-10 21:01:21 +08:00
ZhenYi
14f6e1e500 feat(core): initialize project with access control and AI integration
- Add gitignore and prettier configuration files for project scaffolding
- Implement room access control service with project member verification
- Create user access key management with CRUD operations and activity logging
- Add accordion UI component for frontend expandable sections
- Implement room AI configuration with list, upsert, and delete operations
- Add AI event types for agent join/leave/status change tracking
- Create streaming AI processing services for mode and react patterns
- Build room AI service with model detection and idempotency handling
- Integrate chat service orchestration for AI message processing
- Add typing indicators and stream cancellation for AI interactions
- Implement mention parsing and context extraction for AI agents
2026-05-03 06:04:31 +08:00
ZhenYi
c7cee8c344 misc: polish git hooks, billing services, fctool, and API/WebSocket
- git: clean up hook pool worker, commit sync, HTTP rate limiting
- billing: tighten workspace/project/agent billing logic
- fctool: add project boards and issues management tools
- api/ws: minor room WebSocket protocol adjustments
- frontend: add RoomSettingsPanel component
2026-04-30 19:16:57 +08:00
ZhenYi
e9d5407c66 feat(room): add AI streaming and message hooks for frontend
Add use-ai-streaming hook for SSE-based AI response streaming,
use-room-messages for real-time message updates, and wire up
room context + ws protocol changes.
2026-04-30 19:15:42 +08:00
ZhenYi
867f216a1f feat(theme): add preset color schemes and theme token system
Add 9 preset themes (Midnight, Forest, Sunset, Rose, Lavender,
Arctic, Nord, Dracula, Clean Light) with full palette definitions.

Implement theme token encoding/decoding algorithm:
- Token format: "T1:" + base64url(minified JSON)
- Share any theme via copyable token string
- Import themes by pasting tokens
- Only 16 core color fields encoded (badge classes derived)
2026-04-29 09:50:13 +08:00
ZhenYi
907b5ee3bf fix(room): fix file upload missing /api prefix and credentials
Upload URL was missing /api prefix causing 404, and missing
credentials: 'include' for cookie-based authentication.
2026-04-29 09:40:58 +08:00
ZhenYi
bba35f1b2c fix(room): increase streaming timeout from 60s to 120s
Some checks failed
CI / Rust Lint & Check (push) Has been cancelled
CI / Rust Tests (push) Has been cancelled
CI / Frontend Lint & Type Check (push) Has been cancelled
CI / Frontend Build (push) Has been cancelled
Give more buffer for heartbeat chunks to arrive during long tool
execution, reducing false "Stream timed out" errors.
2026-04-29 09:03:33 +08:00
ZhenYi
c2b4553537 feat(client): generate API client SDK with auto-generated exports
Some checks are pending
CI / Rust Lint & Check (push) Waiting to run
CI / Rust Tests (push) Waiting to run
CI / Frontend Lint & Type Check (push) Waiting to run
CI / Frontend Build (push) Blocked by required conditions
2026-04-29 00:06:30 +08:00
ZhenYi
7ce113a765 feat(agent): paginated model catalog with pricing + redesigned Add AI panel
Backend:
- New GET /api/agents/models/catalog endpoint with page/per_page/search
  params, excludes deprecated models, returns pricing data via
  model→version→pricing join
- ModelWithPricingResponse includes input_price, output_price, currency
- ModelListResponse with pagination metadata (total, page, per_page)
- Batch-fetches default versions + latest pricing to avoid N+1

Frontend:
- RoomSettingsPanel: replace Dialog with inline two-step panel
  - Step 1: paginated model browser with search, shows context length,
    max output tokens, pricing per 1K tokens, capability/modality badges
  - Step 2: selected model info card + AI configuration form
- Removed Dialog import and related unused dependencies
2026-04-28 23:58:46 +08:00
ZhenYi
bc1bdd8491 fix(room): never expose AI model UID to frontend
Backend:
- room_ai_list: batch-fetch models, skip entries where model_name
  cannot be resolved (instead of falling back to "AI {uid}")
- room_ai_upsert: return None for model_name when lookup fails
  (instead of "AI {uid}")

Frontend:
- room-context: discard configs with missing modelName after retries
- DiscordMemberList: filter out configs without modelName
- MessageInput: filter out configs without modelName
- RoomSettingsPanel: prefer model_name from API, fallback to
  availableModels lookup, never render raw UID
- RoomAiTasksPanel: fix broken id/name mapping (was cfg.id/cfg.name
  which don't exist), filter out configs without model_name
2026-04-28 23:21:45 +08:00
ZhenYi
db0a2eca16 feat(ssh): add complete SSH server implementation for Git operations
- Implement SSHandle struct with comprehensive Git service handling capabilities
- Add support for multiple authentication methods including password, public key and certificate
- Integrate Git command parsing and execution with proper channel management
- Implement branch protection rules enforcement during Git operations
- Add robust error handling and logging for SSH connections and Git processes
- Create secure Git command execution with environment isolation
- Implement proper resource cleanup for channels and subprocesses
- Add support for receive-pack, upload-pack and upload-archive services
- Integrate with existing authz and database services for permission checks
- Implement proper data forwarding between SSH channels and Git processes

fix(config): improve environment loading with error reporting

- Replace silent dotenv loading failures with informative error messages
- Handle global config race conditions safely during application startup
- Improve config loading reliability and debugging capabilities

fix(link-unfurl): handle server-side rendering compatibility

- Add undefined window object check for SSR environments
- Prevent client-side only code from breaking server-side rendering

refactor(agent): improve tool registry error handling

- Replace panics with graceful error logging for duplicate tool registrations
- Add proper error type definitions for tool registry operations
- Implement safe merging of registries with duplicate detection

fix(room-context): enhance WebSocket connection reliability

- Add proper error handling for room subscription operations
- Improve connection management with better error suppression
- Add console warnings for debugging connection issues

feat(ws-client): add comprehensive WebSocket client implementation

- Create RoomWsClient class with complete WebSocket communication layer
- Implement request-response pattern with timeout handling
- Add support for various room-related events and actions
- Include proper connection status tracking and management
- Implement callback system for different event types
- Add automatic reconnection and error recovery mechanisms
2026-04-28 21:29:34 +08:00
ZhenYi
aab9f0dbf1 feat(frontend): 替换全屏loading动画为SVG逐帧绘制动画
- 新增 loading-animation.tsx 组件,从 public/load.html 转换
- 动画特性: SVG路径逐条绘制 + 渐变填充,最少展示1.5秒
- 替换 homepage/layout.tsx, workspace/redirect.tsx, protected-route.tsx 中的全屏加载
- 修复 sidebar-user.tsx 中 Invitations 按钮在缩回状态下的居中问题
2026-04-28 19:59:31 +08:00
ZhenYi
b3e4cb7c7a docs(changelog): add April 28 entry for semantic search and tag vectorization
Some checks are pending
CI / Rust Tests (push) Waiting to run
CI / Frontend Lint & Type Check (push) Waiting to run
CI / Frontend Build (push) Blocked by required conditions
CI / Rust Lint & Check (push) Waiting to run
Update changelog with new features: semantic search for messages and tags,
room-scoped search, and incremental tag indexing. All 4 languages (en/cn/de/fr).
2026-04-28 13:15:58 +08:00
ZhenYi
a34cd73fdf fix(frontend): update search API types and fix IMEditor stale closure
Add room/pn search params to SearchMessagesData type definition.
Fix stale closure issue in IMEditor useEditor's onUpdate callback.
2026-04-28 13:12:42 +08:00
ZhenYi
0acacbf57c feat(search): add room-scoped message search with project name filter
Add room parameter (UUID) and pn (project name) to search/messages API.
Service layer supports filtering messages by room and project scope.
Frontend search page updated with room-scoped search support.
2026-04-28 13:12:29 +08:00
ZhenYi
64ca5eeea1 fix(room): improve AI label fallback to never show "Unknown AI"
Fallback chain: modelName -> short model ID (no provider) -> 'AI'
2026-04-28 11:01:51 +08:00
ZhenYi
da2853d0ec fix(blob): use TextDecoder for proper UTF-8 decoding
- atob() returns Latin-1 binary string, not UTF-8
- Chinese characters decoded incorrectly causing mojibake
- Use TextDecoder("utf-8") with Uint8Array for correct handling
2026-04-28 09:42:52 +08:00
ZhenYi
21d0d1eae6 fix(commits): compute total count on cache miss for pagination
- git_commit_log now computes count when Redis cache misses
- Previous: returned total: 0 when cache empty
- Now: compute + cache on miss (5min TTL)
2026-04-28 09:42:47 +08:00
ZhenYi
ddd24bfb6d fix(streaming): add seq field for strict chunk ordering
- Add seq: u64 to RoomMessageStreamChunkEvent
- Frontend sorts by seq on insert for ordered replay
- Initial event now includes seq: 0
2026-04-28 09:42:41 +08:00
ZhenYi
2bd40aee1b fix(room): clear AI stream state on room switch and hide cursor for saved chunks
- Clear activeAiStream, streamingChunks, and timers when room changes
- Add showCursor prop to OrderedStreamChunks — only show cursor
  during active streaming, not for saved content
2026-04-27 22:57:18 +08:00
ZhenYi
ab1ef0d1a7 feat(changelog): add /changelog page with i18n support
Create changelog page with language tabs (EN/CN/DE/FR),
timeline layout, and MDX rendering. Add generate script
to build changelog data from mdx files.
2026-04-27 21:59:50 +08:00
ZhenYi
915c68e8e2 fix(sidebar): center notify icon and add user menu text when collapsed 2026-04-27 18:19:46 +08:00
ZhenYi
368b10d4e0 feat(i18n): integrate i18n into main.tsx, routes and settings page 2026-04-27 18:19:42 +08:00
ZhenYi
d05a13d7fc feat(i18n): integrate LanguageSwitcher into landing nav and theme panel 2026-04-27 18:19:37 +08:00
ZhenYi
77e0923f28 feat(i18n): add LanguageSwitcher component and useLanguage hook 2026-04-27 18:19:32 +08:00
ZhenYi
74f38d0d42 feat(i18n): initialize i18n infrastructure 2026-04-27 18:19:10 +08:00
ZhenYi
1deea4c671 fix(frontend): resolve TypeScript type errors in repository pages
- commits.tsx: fix Unix timestamp (time_secs) not multiplied by 1000
- RoomMessageSearch.tsx: add explicit generic type for resp.data
- RoomPinPanel.tsx: make sender_id optional (string | null)
- message-list.tsx: remove unused index variable in map
- repository-context.tsx: use correct RepoInfo field names
- use-audio-recording.ts: use audioStream state instead of undefined var
- universal-ws.ts: rename unused id to _id
2026-04-27 16:39:43 +08:00
ZhenYi
09645d8641 fix: resolve multiple bugs across backend and frontend
Security fixes:
- Remove WS token from plaintext log output (ws_universal.rs)
- Replace weak LCG PRNG with rand::thread_rng() for access key generation
- Add project membership check to issue triage endpoint (prevent unauthorized AI usage)
- Validate deepLinkUrl to prevent javascript: navigation (XSS defense-in-depth)

Data integrity fixes:
- Fix UUID truncation in AI model sync (as_u128() as i64 -> timestamp_millis)
- Wrap PR cascade delete in database transaction
- Add missing cascade deletes for room_message_reaction, room_message_edit_history, room_notifications
- Fix N+1 query for last_commit_times (single grouped query instead of per-repo)

Panic prevention:
- Replace unwrap() with safe fallbacks in health/metrics endpoints (email, git-hook apps)
- Replace unwrap() in access key scopes serialization
- Replace expect() in tool executor result map with synthetic error
- Replace expect() in log level parsing with default fallback

Logic bugs:
- Fix users_online metric double-decrement (decrement only when count reaches 0)
- Fix Map iteration + deletion bug in universal-ws.ts onclose handler
- Fix stale audioStream reference in catch block (use local stream variable)
- Add missing reInit event cleanup in carousel.tsx
- Fix email retry backoff integer overflow ((1 << i) as u64 -> 1u64 << i)

React fixes:
- Use message.id instead of index as key in message-list
- Add audio stream cleanup on unmount in use-audio-recording
2026-04-27 13:54:21 +08:00
ZhenYi
cce9d216b8 fix: resolve 4 remaining "design decision" bugs
- SSH rate limiter: wire SshRateLimiter into SSHServer with IP-based
  rate limiting on new_client connections
- Room startup: cap initial room load at 1000 via limit() to prevent
  resource exhaustion on large instances
- WS token exposure: only include token in URL for cross-origin
  connections; same-origin web clients authenticate via secure cookies
- CSRF: confirmed SameSite::Lax + Secure + HttpOnly are all set
  (session config defaults)
2026-04-27 11:20:38 +08:00
ZhenYi
1e975c0837 fix: regex injection in message search + semaphore expect panic
- Escape regex special chars in highlightText to prevent ReDoS
- Replace semaphore.acquire().expect() with graceful skip
- Add toast error feedback for search failures
- Remove unsafe (resp.data as any) bypass
2026-04-27 11:12:26 +08:00
ZhenYi
e96bb29434 fix: additional bugs - push notification unwraps and as any cleanup
- Replace Option::unwrap() with let-chains for push subscription fields
- Remove unsafe (repo as any).branch_count access in settings
2026-04-27 11:01:59 +08:00
ZhenYi
bdb5393835 fix: resolve 30+ bugs from security audit
Critical:
- CORS: replace allow_any_origin + credentials with env-configured origins
- XSS: escape HTML before dangerouslySetInnerHTML in search results
- Path traversal: sanitize storage keys to reject ".." components
- Auth missing: add Session requirement to git init/open/is-repo endpoints
- Transaction: wrap issue cascade delete in DB transaction

High:
- Mutex poisoning: replace unwrap() with poison-recovering guards
- Drop tokio::spawn: use runtime handle or fallback thread for lock release
- Redis KEYS: replace with non-blocking SCAN for typing events
- SSH panic: handle missing stdin/stdout/stderr gracefully
- LFS auth: remove x-user-uid header injection vector, generate per-request tokens

Medium:
- Memory leak: remove Box::leak in provider normalization
- Race conditions: query closed count directly instead of subtraction
- Silent failures: add tracing::warn for AI tasks, room events, activity logs
- Frontend nav: sync activeRoomId when initialRoomId prop changes
- Duplicate nav: remove redundant setActiveRoom in delete handler
- Callback conflict: skip undefined values in updateCallbacks merge
- Stale closure: use wsClient state instead of wsClientRef.current in useMemo

Low:
- Captcha: validate captcha not empty before login submission
- Broadcast capacity: reduce from 100K to 1000
- Error handling: add try/catch for removeMember and updateMemberRole
- Loading state: show placeholder instead of null in RepositoryContextProvider
- WebSocket: add heartbeat ping and jitter to reconnect backoff
2026-04-27 10:57:23 +08:00
ZhenYi
a26551343c fix(frontend): refresh WS token after connection failures and handle AI/repo events
Clear wsToken on auth-related close codes (3000-4999), connection
timeout, and after 3 consecutive reconnect failures so the next connect
attempt fetches a fresh token. Add onRoomAiUpdated and onRepoChanged
callbacks that re-fetch AI configs and repo list when pushed via WS.
Fix AI member list to never display raw UUID.
2026-04-26 23:59:07 +08:00
ZhenYi
c8eba28e7a feat(frontend): add repo type to mention autocomplete system
Add 'repo' to MentionType across all editor types, include repos in the
@ trigger pool, add repo badge (green chip), Repos section in the
mention dropdown, and MentionBadge styles. Wire projectRepos from
room context into IMEditor mentionItems.
2026-04-26 23:58:59 +08:00
ZhenYi
99ebfc14a7 fix(frontend): scrollToIndex smooth option uses behavior property
Some checks are pending
CI / Rust Lint & Check (push) Waiting to run
CI / Rust Tests (push) Waiting to run
CI / Frontend Lint & Type Check (push) Waiting to run
CI / Frontend Build (push) Blocked by required conditions
TanStack Virtual uses 'behavior' for scroll animation, not 'smooth'.
2026-04-26 13:31:11 +08:00
ZhenYi
07e74c230c feat: thinking_content column + first-project budget logic
Some checks are pending
CI / Rust Lint & Check (push) Waiting to run
CI / Rust Tests (push) Waiting to run
CI / Frontend Lint & Type Check (push) Waiting to run
CI / Frontend Build (push) Blocked by required conditions
- Add thinking_content column to room_message table
- Migration for thinking_content column
- ws-protocol update with streaming chunk types
- Billing: first project gets $10, first workspace gets $30
- Subsequent projects/workspaces get $0 budget
2026-04-26 13:11:06 +08:00
ZhenYi
0939aa240b fix(frontend): ordered chunk rendering + initial scroll-to-bottom
- OrderedStreamChunks renders think/answer interleaved per arrival order
- parseSavedChunks parses stored __chunks__ JSON on page refresh
- Tool call chunks hidden from frontend display
- Fix streaming join('') instead of join('\n') to avoid per-token newlines
- Fix MessageList scroll-to-bottom using virtualizer.scrollToIndex
- Remove unused streamingContent/streamingThinkingContent state
- Add retryable error patterns for HTTP connection issues
2026-04-26 13:10:51 +08:00
ZhenYi
8b47f677bb fix(avatar): add upload API routes and fix URL path prefix
Some checks are pending
CI / Rust Lint & Check (push) Waiting to run
CI / Rust Tests (push) Waiting to run
CI / Frontend Lint & Type Check (push) Waiting to run
CI / Frontend Build (push) Blocked by required conditions
- Add /api/users/me/avatar and /api/projects/{name}/avatar multipart upload endpoints
- Fix avatar URL path: missing /avatar prefix (static.gitdata.ai/avatar/{file})
- Fix project avatar: Utc::now() → .timestamp(), missing extension, wrong return type
- Replace broken SkipNoisyPaths middleware with self-contained RequestLogger
  (actix-web 4.13 body type incompatibility with newer actix-http)
- Exclude /assets/* requests from main app logger
- Exclude /avatar/*, /blob/*, /media/*, /static/* from static server logger
- Fix TypingEvent missing sender_type field in ws_universal.rs and connection.rs
- Wire real fetch-based upload in user profile settings
- Add project avatar upload UI to project settings page
2026-04-25 23:19:22 +08:00
ZhenYi
61210da7a1 feat(frontend): typing indicator with AI/human split, page visibility reconnect
- TypingUsers state split by sender_type: AI vs human typing
- AI typing shows "{Name} is thinking..." with accent color
- Human typing shows "{Name} is typing..." with muted style
- AI typing relies on backend 60s TTL stop (no client-side 4s fallback)
- Add Page Visibility API to reconnect WS on tab become visible
- Add debug logs for typing flow tracing
- Pass sender_type through WS room.typing event routing
2026-04-25 22:45:11 +08:00
ZhenYi
963e3ee299 chore: update vite.config.ts and IMEditor dependencies 2026-04-25 20:09:50 +08:00
ZhenYi
73ba6329ea fix(frontend): prevent typing.stop on editor init, add typing display
- MessageInput: ignore empty text in handleEditorUpdate to avoid
  TipTap's onUpdate("") on init clearing the typing state
- DiscordChatPanel: show typing indicator when other users are typing
- room-context: wire onTypingStart/Stop into ws callbacks
2026-04-25 20:09:03 +08:00
ZhenYi
99bc4eeb80 chore: API and frontend UI adjustments
- API: issue label bulk add, search messages, room WS push, openapi
- Frontend: notify page, issue detail AI triage banner, search page,
  repository settings, preferences, PR components, file browser
- Room: DiscordChannelSidebar, RoomPinPanel, RoomMessageActions,
  RoomThreadPanel, MessageContent, repository-context
- Frontend SDK regenerated from openapi.json
2026-04-25 09:54:05 +08:00
ZhenYi
dfa5f7664a feat: add notification drawer, command registry, keyboard shortcuts, hooks
New components:
- NotificationDrawer: global bell button with unread badge + Sheet drawer
- CommandPalette: Cmd+K / Ctrl+Alt+F command palette with real API data
- KeyboardShortcutsSheet: ? shortcut reference sheet
- GlobalNavigationShortcuts: g+n/i/r/m two-key navigation
- useNotification: real-time notification management hook
- useCommandRegistry: global command registration hook
- useKeyboardShortcut: keyboard shortcut formatting hook
- useTypingIndicator: unified typing indicator hook
- LinkPreview / CodeBlock / CodeReference: code-aware chat rendering
- ContentRenderer: unified content rendering
- MiniChat: compact inline chat component
- MentionBadge: @mention badge renderer

New libs:
- libs/api/agent/issue_triage.rs: AI issue triage API endpoint
- libs/service/agent/issue_triage.rs: AI triage service
- src/lib/mention.ts: mention parsing and rendering
- src/lib/link-unfurl.ts: URL pattern detection
- src/lib/code-lang-detect.ts: code language detection
- src/lib/code-ref-parser.ts: line-level code reference parsing
2026-04-25 09:53:49 +08:00
ZhenYi
7620f2f281 feat(command): use real API data for navigation, fix notification button
CommandPalette: replace workspaceProjects with getCurrentUserProjects
(no workspace dependency so it works outside WorkspaceProvider).
Repos fetched per-project to preserve correct /repository/ns/repo
routes. Keyboard shortcut correctly matches Ctrl+Alt+F / Cmd+Ctrl+F.

sidebar-user: fix notification button layout — bell icon and label
now on the same row instead of separate stacked elements.
2026-04-25 09:53:12 +08:00
ZhenYi
616c0c0e88 fix(room): scroll-to-bottom logic and AI sender display name
- Remove duplicate smooth scroll effect from DiscordChatPanel; handle
  all scroll logic in MessageList instead
- MessageList: track isInitialLoadRef to instant-jump to bottom on
  first load (no animation), and only auto-scroll for new messages
  when user is already near the bottom
- sender.ts: getSenderDisplayName rejects UUID values and falls back
  to 'AI' for AI messages; getSenderModelId uses display_name
2026-04-25 09:52:58 +08:00
ZhenYi
261989fca3 feat(frontend): TipTap mention nodes with keyboard nav and sectioned dropdown
- MentionNode.tsx: custom TipTap atom node for @/#//mentions
- MentionView.tsx: colored inline labels by type (user=blue, ai=indigo, special=orange)
- IMEditor.tsx: register MentionNode, ↑↓/Enter/Tab/Esc keyboard nav,
  sectioned dropdown (@ groups Notify/AI/Members, # channels, / commands),
  serialize AST to @[type🆔label] on send
- MessageInput.tsx: wire roomAiConfigs into mentionItems, AST serialization
- MessageBubble.tsx: default expanded text (showFullText=true), AI messages never collapsed
2026-04-24 13:16:59 +08:00
ZhenYi
6aca08b8ab feat(room-ui): typing indicator, quick reactions, message grouping, @here/@channel, drag-drop categories, REST category loading
- DiscordChatPanel: typing indicator with animated dots and user names
- MessageActions: quick emoji bar (👍❤️😂🎉😮) on hover
- MessageList: group consecutive messages from same sender within 5min
- MessageInput/IMEditor: @here/@channel special mention suggestions
- DiscordChannelSidebar: useDroppable on category headers for drag-drop,
  empty categories now render, rooms/categories loaded via REST API
- room-context: typingUsers state, REST roomList/categoryList, category
  merge into rooms
2026-04-24 00:04:46 +08:00
ZhenYi
59640c6f44 feat(ws-client): add TypingStart/TypingStop protocol types and client handlers
ws-protocol.ts: TypingStartPayload/TypingStopPayload interfaces,
WsEventPayload union types.

room-ws-client.ts: onTypingStart/onTypingStop callbacks, sendTyping()
method, event dispatch for typing.start/typing_start.

editor/types.ts: special_here/special_channel MentionType + description
field on MentionItem.
2026-04-24 00:04:36 +08:00
ZhenYi
587dc06e8c chore(api): regenerate TypeScript SDK with new user endpoints
Some checks are pending
CI / Rust Lint & Check (push) Waiting to run
CI / Rust Tests (push) Waiting to run
CI / Frontend Lint & Type Check (push) Waiting to run
CI / Frontend Build (push) Blocked by required conditions
New endpoints: GET /api/users/{username}/activity, GET /api/users/{username}/stars,
GET /api/users/{username}/following. Updated types: UserActivityItem, UserActivityResponse,
UserStarsResponse, RepoStarItem, ProjectFollowItem, UserCard.
2026-04-22 22:39:19 +08:00
ZhenYi
80e2201b8b feat(user): add Activity, Following, Stars, Security tabs to profile page
- Backend: user_activity service (user_activity_log + project_activity)
- Backend: stars service (repo_star + project_follow)
- Backend: user_get_following_list (with is_following_me mutual check)
- Frontend: Tab navigation on /user/{username} with Overview/Activity/Following/Stars/Security
- Frontend: UserActivity timeline, FollowingList grid, StarsList, SecurityTab (SSH keys + PATs)
2026-04-22 22:39:14 +08:00
ZhenYi
a705bdc938 fix(frontend): various UI display and type corrections
Some checks are pending
CI / Rust Lint & Check (push) Waiting to run
CI / Rust Tests (push) Waiting to run
CI / Frontend Lint & Type Check (push) Waiting to run
CI / Frontend Build (push) Blocked by required conditions
- workspaces/[id]: Member type fix
- projects/[id]: display adjustments
- platform/sessions: session display improvements
- env.ts: env type corrections
- src/: frontend page and types updates
2026-04-22 10:31:33 +08:00
ZhenYi
4d3afc5e71 fix(frontend): Discord UI polish, room streaming and kanban improvements
- DiscordChatPanel: update threading layout, message list padding
- DiscordMemberList: role colors, online status indicators
- RoomThreadPanel, MessageBubble, MessageInput: UI refinements
- IMEditor: editor state improvements
- KanbanCard, KanbanColumn: card layout, column styling
- room-context.tsx, room-ws-client.ts, ws-protocol.ts: streaming
- pull-request-detail.tsx: PR review improvements
- Add RoomPinPanel component
2026-04-21 22:31:48 +08:00
ZhenYi
a527428b2d fix(frontend): room streaming, dedup, reactions, uploads, and render perf
- room-context: dedup by id not seq (streaming seq=0); single atomic
  setStreamingContent with delta detection; preserve reactions from WS
- MessageBubble: fix avatar lookup (members before IIFE); handleReaction
  deps (no message.reactions); add reactions to wsMessageToUiMessage
- MessageInput: memoize mentionItems; fix upload path with VITE_API_BASE_URL
- IMEditor: warn on upload failure instead of silent swallow
- RoomSettingsPanel: sync form on room switch; loadModels before useEffect
- DiscordChatPanel: extract inline callbacks to useCallback stable refs
2026-04-21 13:43:38 +08:00
ZhenYi
43e2d26ea2 feat(frontend): channel sidebar toggle, member list default closed, fix accent-fg colors
Some checks are pending
CI / Rust Lint & Check (push) Waiting to run
CI / Rust Tests (push) Waiting to run
CI / Frontend Lint & Type Check (push) Waiting to run
CI / Frontend Build (push) Blocked by required conditions
2026-04-20 19:33:14 +08:00
ZhenYi
e43d9fc8bf feat(frontend): add attachment_ids to message creation flow and types 2026-04-20 19:33:09 +08:00
ZhenYi
7736869fc4 feat(frontend): integrate ThemeSwitcher, restore custom palette on page load 2026-04-20 19:33:04 +08:00
ZhenYi
ce29eb3062 feat(frontend): Discord design system tokens and palette variables 2026-04-20 19:32:59 +08:00
ZhenYi
4d5c62e46a feat: add project tools (repos, issues, boards, arxiv, curl, members) and ThemeSwitcher component 2026-04-20 19:31:44 +08:00
ZhenYi
6f6f57f062 feat(frontend): add push notification hooks, image compression, and update room/chat components 2026-04-20 15:45:47 +08:00
ZhenYi
c4d4b2ecf5 fix(room): fix channel sidebar clickability and polish UI
- Fix DraggableRow: remove opacity-0 wrapper that was hiding
  RoomButton; drag handles now work without blocking clicks
- Move "+ Add Category" to bottom of channel list
- Reduce channel item padding (6px → 4px) for compact look
- Shrink # hash icon to 12px
- Add explicit text-align: left to channel names
- Reduce Add Category button/input to 10px font
2026-04-19 20:47:07 +08:00
ZhenYi
63c75ad453 feat(room): add category creation and drag-to-assign for channels
Some checks are pending
CI / Rust Lint & Check (push) Waiting to run
CI / Rust Tests (push) Waiting to run
CI / Frontend Lint & Type Check (push) Waiting to run
CI / Frontend Build (push) Blocked by required conditions
- Rewrite DiscordChannelSidebar with @dnd-kit drag-and-drop:
  rooms are sortable within categories; dragging onto a different
  category header assigns the room to that category
- Add inline 'Add Category' button: Enter/Esc to confirm/cancel
- Wire category create/move handlers in room.tsx via RoomContext
- Fix onAiStreamChunk to accumulate content properly and avoid
  redundant re-renders during AI streaming (dedup guard)
- No backend changes needed: category CRUD and room category update
  endpoints were already wired
2026-04-19 16:44:31 +08:00
ZhenYi
b73cc8d421 refactor(room): Discord-style UI redesign for channel sidebar and member list
Some checks are pending
CI / Rust Lint & Check (push) Waiting to run
CI / Rust Tests (push) Waiting to run
CI / Frontend Lint & Type Check (push) Waiting to run
CI / Frontend Build (push) Blocked by required conditions
2026-04-19 01:12:38 +08:00
ZhenYi
7831d08848 feat(auth): add password reset confirmation endpoint and page
Some checks are pending
CI / Rust Lint & Check (push) Waiting to run
CI / Rust Tests (push) Waiting to run
CI / Frontend Lint & Type Check (push) Waiting to run
CI / Frontend Build (push) Blocked by required conditions
Add the second half of the password reset flow: /password/confirm API
endpoint with token validation, transactional password update, and a
frontend confirm-password-reset-page with proper error handling for
expired/used tokens. Updates generated SDK/client bindings.
2026-04-18 23:02:39 +08:00
ZhenYi
76ca5fb1dd fix(frontend): wire up message search button in DiscordChatPanel
- Add showSearch state and RoomMessageSearch panel (420px slide-in)
- Search button now toggles panel and highlights when active
- Clicking a search result scrolls to the message and closes panel
- Add msg-{id} anchors on message containers for scroll-into-view
2026-04-18 21:13:03 +08:00
ZhenYi
a09f66b779 refactor(room): WebSocket queue and message editor improvements
Some checks are pending
CI / Rust Lint & Check (push) Waiting to run
CI / Rust Tests (push) Waiting to run
CI / Frontend Lint & Type Check (push) Waiting to run
CI / Frontend Build (push) Blocked by required conditions
- Enhance ws_universal.rs with queue message support
- Add queue types and producer improvements
- Simplify MessageBubble.tsx rendering logic
- Refactor IMEditor.tsx with improved message handling
- Update DiscordChatPanel.tsx with message enhancements
2026-04-18 19:29:36 +08:00
ZhenYi
821b0e998d refactor(room): Discord layout and room WebSocket client refactor
- Refactor room-context.tsx with improved WebSocket state management
- Enhance room-ws-client.ts with reconnect logic and message handling
- Update Discord layout components with message editor improvements
- Add WebSocket universal endpoint support in ws_universal.rs
2026-04-18 19:05:21 +08:00
ZhenYi
0cccec33b2 feat(frontend): invitations page with project and workspace support
- Add /invitations route with dedicated page and sidebar button
- Display both project invitations (accept/decline) and workspace invitations (accept only)
- Merge and sort both invitation types by most recent first
- Export new SDK functions: workspaceMyInvitations, workspaceAcceptInvitationBySlug
2026-04-18 19:05:14 +08:00
ZhenYi
00a5369fe1 feat(frontend): Discord layout + AI Studio theme + Room Settings
Some checks are pending
CI / Rust Lint & Check (push) Waiting to run
CI / Rust Tests (push) Waiting to run
CI / Frontend Lint & Type Check (push) Waiting to run
CI / Frontend Build (push) Blocked by required conditions
Frontend:
- Add Discord-style 3-column layout (server icons / channel sidebar / chat)
- AI Studio design system: new CSS token palette (--room-* vars)
- Replace all hardcoded Discord colors with CSS variable tokens
- Add RoomSettingsPanel (name, visibility, AI model management)
- Settings + Member list panels mutually exclusive (don't overlap)
- AI models shown at top of member list with green accent
- Fix TS errors: TipTap SuggestionOptions, unused imports, StarterKit options
- Remove MentionInput, MentionPopover, old room components (废弃代码清理)

Backend:
- RoomAiResponse returns model_name from agents.model JOIN
- room_ai_list and room_ai_upsert fetch model name for each config
- AiConfigData ws-protocol interface updated with model_name

Note: RoomSettingsPanel UI still uses shadcn defaults (未完全迁移到AI Studio)
2026-04-18 16:59:36 +08:00
ZhenYi
aac32b1b92 fix(frontend): block selectionchange during MentionInput DOM updates
Root cause: when MentionInput updates innerHTML to reflect value changes,
the browser resets the selection to position 0. The selectionchange event
handler reads this wrong cursor position and sets ms.cursorOffset=0,
breaking mentionState calculation for the popover.

Fix:
- MentionInput sets window.__mentionBlockSelection=true before innerHTML
- Clears it via requestAnimationFrame after caret is restored
- selectionchange handler skips cursor reading when flag is set
2026-04-18 11:49:03 +08:00
ZhenYi
53b0b03716 fix(frontend): use selectionchange event for cursor tracking instead of per-render
The per-render tracking effect was reading DOM cursor position before
the browser had finished positioning the caret after innerHTML updates,
causing ms.cursorOffset to be set to the old position and overwriting
the deferred correct value.

Switch to document.selectionchange event which:
- Fires only when the user actually moves the cursor (arrow keys, mouse clicks)
- Does NOT fire during programmatic DOM updates
- Uses focusNode/focusOffset directly from the selection API

This completely eliminates the timing race between render effects and
programmatic cursor updates.
2026-04-18 11:42:43 +08:00
ZhenYi
4330325bfc fix(frontend): skip tracking effect update when caret is at end of text
Root cause: after onCategoryEnter sets value="@ai:", the MentionInput sync
effect sets innerHTML with the new content. The browser caret may be at
position 2 (not moved from the user's perspective), but prevCursorRef was
4. The tracking effect read DOM caret=2 and overwrote ms.setCursorOffset(4)
→ cursor jumped to position 2.

Fix: skip tracking effect update when:
- count (DOM caret) is at end of text (ms.value.length), AND
- prevCursorRef was also at end of text
This means the caret hasn't actually moved from the user's POV (just
positioned by the browser after innerHTML), so don't update state.
2026-04-18 11:39:16 +08:00
ZhenYi
126ffda4fe fix(frontend): skip cursor tracking effect during deferred cursor updates
Root cause: when onCategoryEnter scheduled a deferred setCursorOffset,
the tracking effect ran BEFORE setTimeout and read the OLD DOM cursor
position (still "@a" → position 2), overwriting the new cursor position
of 4 in a subsequent render.

Fix: add skipCursorTrackingRef flag. Set it before setTimeout fires,
clear it when setTimeout executes. The tracking effect checks the flag
and skips its update during the flush window.

Same fix applied to insertCategory imperative handle.
2026-04-18 11:27:37 +08:00
ZhenYi
fb09553b79 fix(frontend): defer cursor offset update in onCategoryEnter
When @category is selected, ms.setCursorOffset and ms.setValue were called
in the same event loop tick — the cursor sync effect later read the DOM
before the new mention value flushed, restoring the old caret position.

Defer ms.setCursorOffset via setTimeout so it fires after the DOM
reconciliation. Same fix applied to insertCategory imperative handle.
2026-04-18 11:24:01 +08:00
ZhenYi
5103d99a00 fix(frontend): rewrite MentionInput sync to prevent onChange overwriting mention draft
The root cause: handleMentionSelect set draft to mention HTML, but the
subsequent MentionInput.onInput event fired with plain text (after the
programmatic DOM insert) and overwrote the draft.

Solution: replace pendingSyncRef trick with a clean isUserInputRef flag.
- useEffect: if getPlainText(el) === value, DOM already correct (skip).
  Mark isUserInputRef = false so next useEffect skips caret restore.
- handleInput: always set isUserInputRef = true before calling onChange.

This eliminates the pendingSyncRef/__mentionSkipSync global flag mess
entirely.
2026-04-18 11:20:48 +08:00
ZhenYi
4ace651c6f fix(frontend): pass selected item to doInsert on Enter key and fix list keys
- handleSelectRef.current() was called without argument → suggestion was
  undefined → suggestion.type threw. Now passes the selected item.
- key prop moved to outer map wrapper div so React can diff the list
  correctly. Inner SuggestionItem/CategoryHeader no longer need keys.
2026-04-18 11:16:04 +08:00
ZhenYi
989a4117db fix(frontend): fix useMemo deps syntax and replace stale ref reads in render body
useMemo received deps as trailing comma-separated args instead of array.
Replace all render-body reads of mentionStateRef.current with reactive
mentionState from useMemo. Keep ref for event listener closures only.
2026-04-18 11:14:10 +08:00
ZhenYi
434a3595eb fix(frontend): mention popover respects shouldBelow for above/below placement
ShouldBelow was computed but ignored — popover always rendered below the
cursor. Now uses shouldBelow correctly to render above when insufficient
space below. Also removes unused cRect clone measurement.
2026-04-18 11:11:39 +08:00
ZhenYi
3a164f6dcc fix(frontend): restore missing useMemo import in MentionPopover 2026-04-18 11:09:53 +08:00
ZhenYi
a834564c0f fix(frontend): show mention popover when @ is typed
Effect watches mentionState and toggles showMentionPopover accordingly.
Without this, ms.setShowMentionPopover was never called in onChange,
so the popover never appeared.
2026-04-18 11:09:17 +08:00
ZhenYi
8d3ecca0bc fix(frontend): restore missing cn import in RoomChatPanel 2026-04-18 11:07:15 +08:00
ZhenYi
f152aaeed9 fix(frontend): 4 mention chain bugs — cursor tracking, caret placement, undefined refs
- Fix undefined setDraftAndNotify (replaced with onDraftChangeRef + ms.setValue)
- Add DOM→ms.cursorOffset tracking on every render via TreeWalker
- Fix mention insertion caret placement: skip MentionInput sync-effect caret
  restoration when parent sets value (via __mentionSkipSync window flag)
- Remove unused _draftTick state

Bug #1: setDraftAndNotify referenced but never defined → runtime crash
Bug #2: ms.cursorOffset never updated from DOM → popover always at wrong position
Bug #3: mention insertion saved pre-insertion caret, restored on longer HTML → cursor inside mention tag
Bug #4: _draftTick declared but state value never read → dead code
2026-04-18 01:34:22 +08:00
ZhenYi
168fdc4da8 refactor(frontend): rewrite mention system with clean state architecture
Replace module-level refs and circular dependencies with a centralized
mention state hook (useMentionState) and shared types (mention-types).

- Introduce mention-types.ts for shared types (avoid circular deps)
- Introduce mention-state.ts with useMentionState hook (replace global refs)
- Rewrite MentionInput as contenteditable with AST-based mention rendering
- Rewrite MentionPopover to use props-only communication (no module refs)
- Fix MessageMentions import cycle (mention-types instead of MentionPopover)
- Wire ChatInputArea to useMentionState with proper cursor handling
2026-04-18 01:26:35 +08:00
ZhenYi
d2935f3ddc fix(frontend): repair MentionInput contenteditable implementation
Some checks are pending
CI / Rust Lint & Check (push) Waiting to run
CI / Rust Tests (push) Waiting to run
CI / Frontend Lint & Type Check (push) Waiting to run
CI / Frontend Build (push) Blocked by required conditions
- MentionInput: use forwarded ref, internal state ref, pendingSyncRef
  flag to prevent value↔DOM sync cycles; getContentText walks both
  text nodes and non-editable mention spans to preserve mention length
- RoomChatPanel: replace cursorRef with getCaretOffset()/setCaretOffset()
  helpers, remove stale cursorRef.current references throughout
- MentionPopover: update textareaRef type to HTMLDivElement,
  handleSelect uses TreeWalker to read from contenteditable div,
  positioning effect always uses TreeWalker for text measurement
2026-04-18 01:17:04 +08:00
ZhenYi
b7328e22f3 feat(frontend): render mentions as styled buttons in input and messages
Some checks are pending
CI / Frontend Build (push) Blocked by required conditions
CI / Rust Lint & Check (push) Waiting to run
CI / Rust Tests (push) Waiting to run
CI / Frontend Lint & Type Check (push) Waiting to run
- MentionInput: contenteditable div that renders all mention types as
  emoji+label pill spans (🤖 AI, 👤 User, 📦 Repo, 🔔 Notify)
- Single-backspace deletes entire mention at cursor (detects caret
  at mention start boundary)
- Ctrl+Enter sends, plain Enter swallowed, Shift+Enter inserts newline
- Placeholder CSS via data-placeholder attribute
- MessageMentions: emoji button rendering extended to all mention types
  (user, repository, notify) with click-to-insert support
- Rich input synced via cursorRef (no stale-state re-renders)
2026-04-18 01:06:39 +08:00
ZhenYi
b96ef0342c feat(room): render AI mentions as 🤖 button with click-to-insert action
Some checks are pending
CI / Rust Lint & Check (push) Waiting to run
CI / Rust Tests (push) Waiting to run
CI / Frontend Lint & Type Check (push) Waiting to run
CI / Frontend Build (push) Blocked by required conditions
AI mentions now render as "🤖 AI: name" buttons instead of plain text.
Clicking a 🤖 button inserts the @ai:mention into the message input at
the cursor position, enabling users to summon that AI model into the conversation.

Implementation:
- MessageMentions renders AI mentions as styled buttons with 🤖 icon
- Click dispatches 'mention-click' CustomEvent on document
- ChatInputArea listens and inserts the mention HTML at cursor
2026-04-18 00:57:27 +08:00
ZhenYi
3a24022972 fix(room): load model list inside fetchRoomAiConfigs so AI names are always resolved
Some checks are pending
CI / Rust Lint & Check (push) Waiting to run
CI / Rust Tests (push) Waiting to run
CI / Frontend Lint & Type Check (push) Waiting to run
CI / Frontend Build (push) Blocked by required conditions
Previously availableModels was fetched in parallel with roomAiConfigs, so
the first call to fetchRoomAiConfigs had empty availableModels and all AI
configs showed model IDs instead of names.

Now fetchRoomAiConfigs loads the model list itself when called, guaranteeing
that model names are always available.
2026-04-18 00:55:18 +08:00
ZhenYi
17e878c8b8 fix(room): fix Enter-on-category via React state update instead of DOM manipulation
Problem: dispatchEvent('input') doesn't trigger React's onChange in React 17+.

Solution: pass onCategoryEnter callback from ChatInputArea to MentionPopover.
When Enter is pressed on a category, MentionPopover calls onCategoryEnter(category)
which directly calls React setState (onDraftChange, setCursorPosition,
setShowMentionPopover) inside ChatInputArea, properly triggering re-render.
2026-04-18 00:51:14 +08:00
ZhenYi
14de80b24b fix(room): Enter on category navigates into it, not out of popover
When a category (Repository/User/AI) is selected and Enter is pressed,
append ':' to the textarea value to trigger the next-level item list.
E.g. '@ai' + Enter → '@ai:' → shows AI model items.
2026-04-18 00:42:08 +08:00
ZhenYi
245384ef50 fix(room): handle Enter/Tab mention selection directly in ChatInputArea.handleKeyDown
Previous approach used a native addEventListener in MentionPopover to handle
Enter, but it wasn't firing reliably due to complex event ordering.

New approach: ChatInputArea.handleKeyDown detects @ mention directly from
the DOM (not React state), reads the selected item from module-level
mentionVisibleRef/mentionSelectedIdxRef, and performs the insertion directly.
This completely bypasses the native listener timing issues.
2026-04-18 00:39:06 +08:00
ZhenYi
b8a61b0802 fix(room): make handleSelect read DOM directly instead of stale props
Root cause: MentionPopover's native keydown listener fires before React
state updates, so handleSelect read stale inputValue/cursorPosition props
and silently returned early.

Fix: handleSelect now reads textarea.value/selectionStart directly from
the DOM, matching the approach already used in ChatInputArea's
handleMentionSelect. No more stale closure.
2026-04-18 00:35:21 +08:00
ZhenYi
3cd5b3003c fix(room): fix mention Enter key by reading textarea DOM directly
Problem: showMentionPopover state is stale when handleKeyDown fires
immediately after handleChange (both in same event loop), causing Enter
to be silently swallowed.

Solution:
- Read textarea.value directly in handleKeyDown to detect @ mentions
- Module-level refs (mentionSelectedIdxRef, mentionVisibleRef) share
  selection state between MentionPopover and ChatInputArea
- handleMentionSelect reads DOM instead of relying on props state
2026-04-18 00:25:03 +08:00
ZhenYi
13f5ff328c fix(room): hoist mentionConfirmRef to module scope to fix TDZ error
ChatInputArea is defined before RoomChatPanel in the file, so its JSX
runs before mentionConfirmRef is declared inside RoomChatPanel. Moving the
ref to module level ensures it's initialized before either component renders.
2026-04-18 00:17:47 +08:00
ZhenYi
14bcc04991 fix(room): update keyboard shortcuts — Ctrl+Enter sends, Shift+Enter newlines, Enter only for mention select
- Ctrl+Enter: send message (was plain Enter)
- Shift+Enter: insert newline (textarea default, passes through)
- Enter alone: only triggers mention selection when popover is open, otherwise does nothing
- Update MentionPopover footer/header hints to reflect new shortcuts
2026-04-18 00:11:13 +08:00