Commit Graph

31 Commits

Author SHA1 Message Date
ZhenYi
991d86237b fix: remove stale onRenderedCountChange prop from RoomMessageList usage 2026-04-17 21:23:03 +08:00
ZhenYi
70381006cf chore(room): remove Performance Stats panel
Unused debug overlay that was tracking virtualized row counts.
2026-04-17 21:21:59 +08:00
ZhenYi
f2a2ae5d7f fix(room): use WS for message fetching, eliminate duplicate WS connection
- Fix initial room load being skipped: `setup()` called `loadMoreRef.current`
  which was null on first mount (ref assigned in later effect). Call `loadMore`
  directly so the initial fetch always fires. WS message.list used when
  connected, HTTP fallback otherwise.
- Rewrite useRoomWs to use shared RoomWsClient instead of creating its own
  raw WebSocket, eliminating duplicate WS connection per room.
- Remove dead loadMoreRef now that setup calls loadMore directly.
2026-04-17 21:18:56 +08:00
ZhenYi
cf5c728286 fix(room): fix scrolling lag, N+1 queries, and multiple WS token requests
Frontend:
- P0: Replace constant estimateSize(40px) with content-based estimation
  using line count and reply presence for accurate virtual list scroll
- P1: Replace Shadow DOM custom elements with styled spans for @mentions,
  eliminating expensive attachShadow calls per mention instance
- P1: Remove per-message ResizeObserver (one per bubble), replace with
  static inline toolbar layout to avoid observer overhead
- P2: Fix WS token re-fetch on every room switch by preserving token
  across navigation and not clearing activeRoomIdRef on cleanup

Backend:
- P1: Fix reaction check+insert race condition by moving into transaction
  instead of separate query + on-conflict insert
- P2: Fix N+1 queries in get_mention_notifications with batch fetch
  for users and rooms using IN clauses
- P2: Update room_last_activity in broadcast_stream_chunk to prevent
  idle room cleanup during active AI streaming
- P3: Use enum comparison instead of to_string() in room_member_leave
2026-04-17 21:08:40 +08:00
ZhenYi
60d8c3a617 fix(room): resolve remaining defects from second review
- reaction.rs: query before insert to detect new vs duplicate reactions,
  only publish Redis event when a reaction was actually added
- room.rs: delete Redis seq key on room deletion to prevent seq
  collision on re-creation
- message.rs: use Redis-atomic next_room_message_seq_internal for
  concurrent safety; look up sender display name once for both
  mention notifications and response body; add warn log when
  should_ai_respond fails instead of silent unwrap_or(false)
- ws_universal.rs: re-check room access permission when re-subscribing
  dead streams after error to prevent revoked permissions being bypassed
- RoomChatPanel.tsx: truncate reply preview content to 80 chars
- RoomMessageList.tsx: remove redundant inline style on message row div
2026-04-17 20:28:45 +08:00
ZhenYi
5256e72be7 fix(room): add access check to ws_universal subscribe and fix stream handling
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 `check_room_access` before `manager.subscribe()` in ws_universal
  to prevent unauthorized room subscription (security fix)
- Fix busy-wait in `poll_push_streams`: sleep 50ms when streams are
  empty, yield only when there are active streams
- Re-subscribe dead rooms after stream errors so events are not
  permanently lost until manual reconnect
- Fix streaming message placeholder using fake content as room_id:
  use chunk.room_id from backend instead
- Show toast error on history load failures instead of silent fallback
2026-04-17 17:15:34 +08:00
ZhenYi
d0fc590491 fix(frontend): remove unused Zap import in landing-sections.tsx
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
2026-04-16 21:10:39 +08:00
ZhenYi
5a59f56319 fix(room): revert stale edited_at if messageGet fetch fails
onMessageEdited optimistically set edited_at, then fetched the full
message. If the fetch failed the "Edited" indicator persisted even though
the content was stale. Fix by capturing the original edited_at and
reverting it in the catch block — consistent with editMessage rollback.
2026-04-16 19:34:59 +08:00
ZhenYi
beea8854ce fix(room): fix stale room subscribe after async connect
connect() is async/fire-and-forget — if the user switches rooms while
WS is still connecting, the subscribeRoom() call captures the stale
(activeRoomId) closure value and subscribes to the wrong room. Fix by
re-reading activeRoomIdRef.current after the await so we always subscribe
to the room that is active when the connection actually opens.
2026-04-16 19:34:07 +08:00
ZhenYi
7989f7ba4b fix(room): fix StrictMode reconnect loop, add revokeMessage rollback
- useEffect([wsClient]): remove wsClient from deps to prevent
  React StrictMode double-mount from disconnecting the real client.
  First mount connects client-1; StrictMode cleanup disconnects it.
  Second mount connects client-2; first mount's second cleanup would
  then disconnect client-2, leaving WS permanently unconnected.
  Changing to useEffect([]) + optional chaining fixes this.
- revokeMessage: add optimistic removal + rollback on server rejection,
  consistent with editMessage pattern. Previously a failed delete left the
  message visible with no feedback.
2026-04-16 19:33:14 +08:00
ZhenYi
7416f37cec fix(room): prevent double-send, log resubscribe errors, dim pending messages
- sendMessage: guard with sendingRef to prevent concurrent in-flight
  sends (was missing — rapid clicks could create duplicate messages)
- resubscribeAll: log at warn level instead of silently swallowing,
  so operators can observe auth expiry or persistent failure patterns
- RoomMessageBubble: apply opacity-60 when isPending or isFailed,
  and hide action toolbar for pending messages (can't react/act on
  unconfirmed messages)
2026-04-16 19:29:34 +08:00
ZhenYi
677e88980b fix(room): add edit rollback, clean stream channels on room shutdown/idle 2026-04-16 19:28:23 +08:00
ZhenYi
c89f01b718 feat(room): improve robustness — optimistic send, atomic seq, jitter reconnect
Backend:
- Atomic seq assignment via Redis Lua script: INCR + GET run atomically
  inside a Lua script, preventing duplicate seqs under concurrent requests.
  DB reconciliation only triggers on cross-server handoff (rare path).
- Broadcast channel capacity: 10,000 → 100,000 to prevent message drops
  under high-throughput rooms.

Frontend:
- Optimistic sendMessage: adds message to UI immediately (marked
  isOptimistic=true) so user sees it instantly. Replaces with
  server-confirmed message on success, marks as isOptimisticError on
  failure. Fire-and-forget to IndexedDB for persistence.
- Seq-based dedup in onRoomMessage: replaces optimistic message by
  matching seq, preventing duplicates when WS arrives before REST confirm.
- Reconnect jitter: replaced deterministic backoff with full jitter
  (random within backoff window), preventing thundering herd on server
  restart.
- Visual WS status dot in room header: green=connected, amber
  (pulsing)=connecting, red=error/disconnected.
- isPending check extended to cover both old 'temp-' prefix and new
  isOptimistic flag, showing 'Sending...' / 'Failed' badges.
2026-04-16 19:23:06 +08:00
ZhenYi
5482283727 feat(seo): add useHead to all landing pages with Command as Service titles and descriptions
Some checks are pending
CI / Frontend Build (push) Blocked by required conditions
CI / Frontend Lint & Type Check (push) Waiting to run
CI / Rust Lint & Check (push) Waiting to run
CI / Rust Tests (push) Waiting to run
2026-04-16 19:12:06 +08:00
ZhenYi
022b45d44f docs(landing): replace 'Real-time' with 'Command-first' in nav, align Enterprise nav desc
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-16 19:08:20 +08:00
ZhenYi
e59edf6c1a docs(landing): align docs page hero with Command as Service platform
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-16 19:05:57 +08:00
ZhenYi
757a7044bf docs(landing): align Enterprise pricing and Public Rooms nav with Command as Service
Some checks are pending
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
CI / Rust Tests (push) Waiting to run
2026-04-16 19:04:34 +08:00
ZhenYi
260d154db2 docs(landing): final alignment — rooms features, API endpoint, and Pro pricing tagline
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-16 19:03:27 +08:00
ZhenYi
c9f4e2dbe7 docs(landing): replace 'chat rooms' with 'command-first rooms' in feature descriptions
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-16 19:02:26 +08:00
ZhenYi
84f2604106 docs(landing): align remaining landing pages with Command as Service concept
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-16 19:01:27 +08:00
ZhenYi
4c77426965 docs(landing): align all non-business pages with Command as Service concept
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-16 18:59:37 +08:00
ZhenYi
4eb93da28b docs(landing): update README and SEO defaults to Command as Service tagline
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-16 18:58:28 +08:00
ZhenYi
a4cb18580b docs(landing): rewrite tagline and features around Command as Service
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
- Badge: 'Command as Service · Human + Agent Engineering'
- Subtitle: 'Every action is a command. Every command is versioned,
  auditable, and composable.'
- Terminal demo: show service deploy, skill run, and replay commands
- Features: lead with Command as Service, rewrite all descriptions
  around the command stream paradigm
- Section header: 'Build. Review. Automate. All via Commands.'
- Highlight: 'Your CLI is also your API'
- Nav/Footer: surface Command as Service in Platform menu
2026-04-16 18:54:50 +08:00
ZhenYi
89deebced6 fix(api): add clone url
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-16 18:31:05 +08:00
ZhenYi
8b433c9169 feat(repo): return ssh/https clone URLs from backend
Some checks are pending
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
CI / Rust Tests (push) Waiting to run
Add ssh_clone_url and https_clone_url to ProjectRepositoryItem,
constructed from config.ssh_domain() and config.git_http_domain().
Update frontend RepoInfo interface and header.tsx to use the
server-provided URLs instead of hardcoded values.
2026-04-16 18:20:48 +08:00
ZhenYi
b1e93a7cfc fix(init): use resp.error to detect project_not_found instead of HTTP status
Some checks are pending
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
CI / Rust Tests (push) Waiting to run
The generated client returns AxiosError as resp when throwOnError=false.
Check resp.error (set by the client to err.response?.data) for the
business-level code/error fields rather than relying on HTTP status.
2026-04-16 18:05:44 +08:00
ZhenYi
41f96af064 fix(init): use isAxiosError to correctly detect 404 on project name availability check 2026-04-16 17:22:25 +08:00
ZhenYi
2afad11cb6 fix(frontend): use workspaceInfo API to get full workspace data for sidebar 2026-04-15 22:55:01 +08:00
ZhenYi
a1ebe47564 fix(frontend): remove unused imports and fix workspace type in homepage 2026-04-15 22:45:07 +08:00
ZhenYi
afbc58d9bf feat(frontend): landing pages with Command as Service concept
- Add landing subpages: pricing, skills, solutions, network, about, docs
- Nav pop cards link to all subpages with nested routes
- Homepage: full landing content with top nav (no sidebar) for logged-in users
- Rewrite copy based on real backend: Git repos, Issues/PRs, Rooms, AI Agents
- Introduce "Command as Service" as core product concept
- Terminal demo shows realistic gitdata CLI commands
- Footer links updated to real routes
- Fix workspace redirect slug guard (undefined route)
2026-04-15 21:45:30 +08:00
ZhenYi
93cfff9738 init 2026-04-15 09:08:09 +08:00